Merge changes Ica870d27,Ibaddc7f1 into msm-3.0

* changes:
  ARM: architected timers: Add A15 specific sched_clock implementation
  ARM: local timers: Add A15 architected timer support
diff --git a/Documentation/sound/alsa/compress/snd_compress_data.txt b/Documentation/sound/alsa/compress/snd_compress_data.txt
new file mode 100644
index 0000000..98e2cc9
--- /dev/null
+++ b/Documentation/sound/alsa/compress/snd_compress_data.txt
@@ -0,0 +1,187 @@
+		snd_compress_data.txt
+		=====================
+	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+		Vinod Koul <vinod.koul@linux.intel.com>
+
+Overview
+
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compability break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+Requirements
+
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+ - Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+
+The new API shares a number of concepts with with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+- get_codecs
+This routine returns the list of audio formats supported. Querying the
+codecs on a capture stream will return encoders, decoders will be
+listed for playback streams.
+
+- get_codec_caps
+For each codec, this routine returns a list of capabilities. The
+intent is to make sure all the capabilities correspond to valid
+settings, and to minimize the risks of configuration failures. For
+example, for a complex codec such as AAC, the number of channels
+supported may depend on a specific profile. If the capabilities were
+exposed with a single descriptor, it may happen that a specific
+combination of profiles/channels/formats may not be
+supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+it is likely that some implementations make the list of capabilities
+dynamic and dependent on existing workloads.
+
+- set_params
+This routine sets the configuration chosen for a specific codec. The
+most important field in the parameters is the codec type; in most
+cases decoders will ignore other fields, while encoders will strictly
+comply to the settings
+
+- get_params
+This routines returns the actual settings used by the DSP. Changes to
+the settings should remain the exception.
+
+- get_timestamp
+The timestamp becomes a multiple field structure. It lists the number
+of bytes transferred, the number of samples processed and the number
+of samples rendered/grabbed. All these values can be used to determine
+the avarage bitrate, figure out if the ring buffer needs to be
+refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+Not supported:
+
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices
+
+Instead,
+  offloaded processing will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any premption
+  mechanisms.
+
+- No notion of underun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overun and
+  maybe dealt in user-library
+
+Credits:
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index dbf3427..2b7b749 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -40,17 +40,6 @@
 /* Address of GIC 0 CPU interface */
 void __iomem *gic_cpu_base_addr __read_mostly;
 
-struct gic_chip_data {
-	unsigned int irq_offset;
-	void __iomem *dist_base;
-	void __iomem *cpu_base;
-	unsigned int max_irq;
-#ifdef CONFIG_PM
-	unsigned int wakeup_irqs[32];
-	unsigned int enabled_irqs[32];
-#endif
-};
-
 /*
  * Supported arch specific GIC irq extension.
  * Default make them NULL.
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 3e754fc..f617aff 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -55,6 +55,7 @@
 CONFIG_NEON=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_SUSPEND is not set
+CONFIG_HOTPLUG_CPU=y
 CONFIG_NET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
index 7da4daf..4aabe08 100644
--- a/arch/arm/configs/msm7627_defconfig
+++ b/arch/arm/configs/msm7627_defconfig
@@ -288,13 +288,20 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 90d4c4a..f81cc3d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -230,6 +230,8 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_IMX072=y
 CONFIG_RADIO_TAVARUA=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 53d6367..4836af0 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -228,6 +228,8 @@
 CONFIG_MSM_CAMERA_FLASH_SC628A=y
 CONFIG_IMX072=y
 CONFIG_RADIO_TAVARUA=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
@@ -304,15 +306,21 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
 CONFIG_LATENCYTOP=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
 # CONFIG_FTRACE is not set
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 2cd7b97..3791d0e 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -262,6 +262,8 @@
 CONFIG_MT9E013=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 362babe..bd60092 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -253,6 +253,8 @@
 # CONFIG_MFD_PM8XXX_DEBUG is not set
 # CONFIG_MFD_PM8XXX_PWM is not set
 # CONFIG_MFD_PM8XXX_MISC is not set
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_FB=y
@@ -346,14 +348,20 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 # CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_CRYPTO_SHA256=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index dccefd8..ca64436 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -320,6 +320,8 @@
 CONFIG_RADIO_TAVARUA=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index c4941db..f78ed74 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -308,6 +308,8 @@
 CONFIG_MT9E013=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
@@ -409,9 +411,13 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
+CONFIG_LOCKUP_DETECTOR=y
 CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
+CONFIG_SLUB_DEBUG_ON=y
 # CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
@@ -419,6 +425,8 @@
 CONFIG_DEBUG_VM=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PAGEALLOC=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
old mode 100755
new mode 100644
index f9117cb..e136a0a
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -269,7 +269,7 @@
 CONFIG_ISL9519_CHARGER=y
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
-CONFIG_SENSORS_PM8921_ADC=y
+CONFIG_SENSORS_PM8XXX_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
 CONFIG_THERMAL_PM8XXX=y
@@ -292,6 +292,8 @@
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
 CONFIG_ION_MSM=y
+CONFIG_GENLOCK=y
+CONFIG_GENLOCK_MISCDEVICE=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_FB=y
@@ -339,7 +341,7 @@
 CONFIG_USB_SERIAL_QUALCOMM=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_QCOM_DIAG_BRIDGE=y
-CONFIG_USB_QCOM_DUN_BRIDGE=y
+CONFIG_USB_QCOM_MDM_BRIDGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 8689712..e1b45e1 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -97,6 +97,8 @@
 # CONFIG_MSM_RMNET is not set
 CONFIG_MSM_RMNET_BAM=y
 # CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_MISC=y
@@ -132,11 +134,39 @@
 CONFIG_REGULATOR_GPIO=y
 # CONFIG_HID_SUPPORT is not set
 CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_CI13XXX_MSM=y
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 27adea3..e90400b 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -43,6 +43,17 @@
 void gic_enable_ppi(unsigned int);
 bool gic_is_spi_pending(unsigned int irq);
 void gic_clear_spi_pending(unsigned int irq);
+
+struct gic_chip_data {
+	unsigned int irq_offset;
+	void __iomem *dist_base;
+	void __iomem *cpu_base;
+	unsigned int max_irq;
+#ifdef CONFIG_PM
+	unsigned int wakeup_irqs[32];
+	unsigned int enabled_irqs[32];
+#endif
+};
 #endif
 
 #endif
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index c8f963c..be324ac 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -85,7 +85,7 @@
 	void		(*start)(void);
 	void		(*stop)(void);
 	void		(*reset)(void *);
-	const unsigned	(*cache_map)[PERF_COUNT_HW_CACHE_MAX]
+	unsigned	(*cache_map)[PERF_COUNT_HW_CACHE_MAX]
 				    [PERF_COUNT_HW_CACHE_OP_MAX]
 				    [PERF_COUNT_HW_CACHE_RESULT_MAX];
 	const unsigned	(*event_map)[PERF_COUNT_HW_MAX];
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
index 579cd3b..1c2206f 100644
--- a/arch/arm/kernel/perf_event_msm.c
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -128,7 +128,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
 
-static const unsigned armv7_scorpion_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv7_scorpion_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 1e77489..e3e9bf2 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -15,20 +15,41 @@
 
 #ifdef CONFIG_CPU_V7
 #define KRAIT_EVT_PREFIX 1
-#define KRAIT_MAX_L1_REG 2
+#define KRAIT_VENUMEVT_PREFIX 2
 /*
    event encoding:                prccg
-   p  = prefix (1 for Krait L1)
+   p  = prefix (1 for Krait L1) (2 for Krait VeNum events)
    r  = register
    cc = code
    g  = group
 */
-#define KRAIT_L1_ICACHE_MISS    0x10010
-#define KRAIT_L1_ICACHE_ACCESS  0x10011
-#define KRAIT_DTLB_ACCESS       0x121B2
-#define KRAIT_ITLB_ACCESS       0x121C0
 
-u32 evt_type_base[] = {0x4c, 0x50, 0x54};
+#define KRAIT_L1_ICACHE_ACCESS 0x10011
+#define KRAIT_L1_ICACHE_MISS 0x10010
+
+#define KRAIT_P1_L1_ITLB_ACCESS 0x121b2
+#define KRAIT_P1_L1_DTLB_ACCESS 0x121c0
+
+#define KRAIT_P2_L1_ITLB_ACCESS 0x12222
+#define KRAIT_P2_L1_DTLB_ACCESS 0x12210
+
+u32 evt_type_base[][4] = {
+	{0x4c, 0x50, 0x54},		/* Pass 1 */
+	{0xcc, 0xd0, 0xd4, 0xd8},	/* Pass 2 */
+};
+
+#define KRAIT_MIDR_PASS1 0x510F04D0
+#define KRAIT_MIDR_MASK 0xfffffff0
+
+/*
+ * This offset is used to calculate the index
+ * into evt_type_base[][] and krait_functions[]
+ */
+#define VENUM_BASE_OFFSET 3
+
+/* Krait Pass 1 has 3 groups, Pass 2 has 4 */
+static u32 krait_ver, evt_index;
+static u32 krait_max_l1_reg;
 
 static const unsigned armv7_krait_perf_map[PERF_COUNT_HW_MAX] = {
 	[PERF_COUNT_HW_CPU_CYCLES]	    = ARMV7_PERFCTR_CPU_CYCLES,
@@ -40,7 +61,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
 
-static const unsigned armv7_krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv7_krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
@@ -93,11 +114,11 @@
 	},
 	[C(DTLB)] = {
 		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_DTLB_ACCESS,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_DTLB_ACCESS,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
@@ -107,11 +128,11 @@
 	},
 	[C(ITLB)] = {
 		[C(OP_READ)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_ITLB_ACCESS,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= KRAIT_ITLB_ACCESS,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
 			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
@@ -170,17 +191,26 @@
 	u8 group;
 
 	prefix = (krait_evt_type & 0xF0000) >> 16;
-	reg    = (krait_evt_type & 0x0F000) >> 12;
-	code   = (krait_evt_type & 0x00FF0) >> 4;
-	group  =  krait_evt_type & 0x0000F;
+	reg = (krait_evt_type & 0x0F000) >> 12;
+	code = (krait_evt_type & 0x00FF0) >> 4;
+	group = krait_evt_type & 0x0000F;
 
-	if ((prefix != KRAIT_EVT_PREFIX) || (group > 3) ||
-	    (reg > KRAIT_MAX_L1_REG))
+	if ((group > 3) || (reg > krait_max_l1_reg))
 		return -EINVAL;
 
+	if (prefix != KRAIT_EVT_PREFIX || prefix != KRAIT_VENUMEVT_PREFIX)
+		return -EINVAL;
+
+	if (prefix == KRAIT_VENUMEVT_PREFIX) {
+		if ((code & 0xe0) || krait_ver != 2)
+			return -EINVAL;
+		else
+			reg += VENUM_BASE_OFFSET;
+	}
+
 	evtinfo->group_setval = 0x80000000 | (code << (group * 8));
 	evtinfo->groupcode = reg;
-	evtinfo->armv7_evt_type = evt_type_base[reg] | group;
+	evtinfo->armv7_evt_type = evt_type_base[evt_index][reg] | group;
 
 	return evtinfo->armv7_evt_type;
 }
@@ -224,9 +254,59 @@
 	asm volatile("mcr p15, 1, %0, c9, c15, 2" : : "r" (val));
 }
 
+static u32 krait_read_vmresr0(void)
+{
+	u32 val;
+
+	asm volatile ("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
+	return val;
+}
+
+static void krait_write_vmresr0(u32 val)
+{
+	asm volatile ("mcr p10, 7, %0, c11, c0, 0" : : "r" (val));
+}
+
+static DEFINE_PER_CPU(u32, venum_orig_val);
+static DEFINE_PER_CPU(u32, fp_orig_val);
+
+static void krait_pre_vmresr0(void)
+{
+	u32 venum_new_val;
+	u32 fp_new_val;
+	u32 v_orig_val;
+	u32 f_orig_val;
+
+	/* CPACR Enable CP10 access */
+	v_orig_val = get_copro_access();
+	venum_new_val = v_orig_val | CPACC_SVC(10);
+	set_copro_access(venum_new_val);
+	/* Store orig venum val */
+	__get_cpu_var(venum_orig_val) = v_orig_val;
+
+	/* Enable FPEXC */
+	f_orig_val = fmrx(FPEXC);
+	fp_new_val = f_orig_val | FPEXC_EN;
+	fmxr(FPEXC, fp_new_val);
+	/* Store orig fp val */
+	__get_cpu_var(fp_orig_val) = f_orig_val;
+
+}
+
+static void krait_post_vmresr0(void)
+{
+	/* Restore FPEXC */
+	fmxr(FPEXC, __get_cpu_var(fp_orig_val));
+	isb();
+	/* Restore CPACR */
+	set_copro_access(__get_cpu_var(venum_orig_val));
+}
+
 struct krait_access_funcs {
 	u32 (*read) (void);
 	void (*write) (u32);
+	void (*pre) (void);
+	void (*post) (void);
 };
 
 /*
@@ -235,9 +315,11 @@
  * Having the following array modularizes the code for doing that.
  */
 struct krait_access_funcs krait_functions[] = {
-	{krait_read_pmresr0, krait_write_pmresr0},
-	{krait_read_pmresr1, krait_write_pmresr1},
-	{krait_read_pmresr2, krait_write_pmresr2},
+	{krait_read_pmresr0, krait_write_pmresr0, NULL, NULL},
+	{krait_read_pmresr1, krait_write_pmresr1, NULL, NULL},
+	{krait_read_pmresr2, krait_write_pmresr2, NULL, NULL},
+	{krait_read_vmresr0, krait_write_vmresr0, krait_pre_vmresr0,
+	 krait_post_vmresr0},
 };
 
 static inline u32 krait_get_columnmask(u32 evt_code)
@@ -252,9 +334,15 @@
 {
 	u32 val;
 
+	if (krait_functions[gr].pre)
+		krait_functions[gr].pre();
+
 	val = krait_get_columnmask(evt_code) & krait_functions[gr].read();
 	val = val | setval;
 	krait_functions[gr].write(val);
+
+	if (krait_functions[gr].post)
+		krait_functions[gr].post();
 }
 
 static void krait_clear_pmuregs(void)
@@ -262,15 +350,25 @@
 	krait_write_pmresr0(0);
 	krait_write_pmresr1(0);
 	krait_write_pmresr2(0);
+
+	krait_pre_vmresr0();
+	krait_write_vmresr0(0);
+	krait_post_vmresr0();
 }
 
 static void krait_clearpmu(u32 grp, u32 val, u32 evt_code)
 {
 	u32 new_pmuval;
 
+	if (krait_functions[grp].pre)
+		krait_functions[grp].pre();
+
 	new_pmuval = krait_functions[grp].read() &
 		krait_get_columnmask(evt_code);
 	krait_functions[grp].write(new_pmuval);
+
+	if (krait_functions[grp].post)
+		krait_functions[grp].post();
 }
 
 static void krait_pmu_disable_event(struct hw_perf_event *hwc, int idx)
@@ -380,6 +478,19 @@
 	.max_period		= (1LLU << 32) - 1,
 };
 
+int get_krait_ver(void)
+{
+	int ver = 0;
+	int midr = read_cpuid_id();
+
+	if ((midr & KRAIT_MIDR_MASK) != KRAIT_MIDR_PASS1)
+		ver = 2;
+
+	pr_debug("krait_ver: %d, midr: %x\n", ver, midr);
+
+	return ver;
+}
+
 static const struct arm_pmu *__init armv7_krait_pmu_init(void)
 {
 	krait_pmu.id		= ARM_PERF_PMU_ID_KRAIT;
@@ -388,6 +499,41 @@
 	krait_pmu.event_map	= &armv7_krait_perf_map;
 	krait_pmu.num_events	= armv7_read_num_pmnc_events();
 	krait_clear_pmuregs();
+
+	krait_ver = get_krait_ver();
+
+	if (krait_ver > 0) {
+		evt_index = 1;
+		krait_max_l1_reg = 3;
+		armv7_krait_perf_cache_map[C(ITLB)]
+			[C(OP_READ)]
+			[C(RESULT_ACCESS)] = KRAIT_P2_L1_ITLB_ACCESS;
+		armv7_krait_perf_cache_map[C(ITLB)]
+			[C(OP_WRITE)]
+			[C(RESULT_ACCESS)] = KRAIT_P2_L1_ITLB_ACCESS;
+		armv7_krait_perf_cache_map[C(DTLB)]
+			[C(OP_READ)]
+			[C(RESULT_ACCESS)] = KRAIT_P2_L1_DTLB_ACCESS;
+		armv7_krait_perf_cache_map[C(DTLB)]
+			[C(OP_WRITE)]
+			[C(RESULT_ACCESS)] = KRAIT_P2_L1_DTLB_ACCESS;
+	} else {
+		evt_index = 0;
+		krait_max_l1_reg = 2;
+		armv7_krait_perf_cache_map[C(ITLB)]
+			[C(OP_READ)]
+			[C(RESULT_ACCESS)] = KRAIT_P1_L1_ITLB_ACCESS;
+		armv7_krait_perf_cache_map[C(ITLB)]
+			[C(OP_WRITE)]
+			[C(RESULT_ACCESS)] = KRAIT_P1_L1_ITLB_ACCESS;
+		armv7_krait_perf_cache_map[C(DTLB)]
+			[C(OP_READ)]
+			[C(RESULT_ACCESS)] = KRAIT_P1_L1_DTLB_ACCESS;
+		armv7_krait_perf_cache_map[C(DTLB)]
+			[C(OP_WRITE)]
+			[C(RESULT_ACCESS)] = KRAIT_P1_L1_DTLB_ACCESS;
+	}
+
 	return &krait_pmu;
 }
 
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index f1e8dd9..0635b7e 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -74,7 +74,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
 };
 
-static const unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv6_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
@@ -213,7 +213,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
 };
 
-static const unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv6mpcore_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 462aefb..4031c7b 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -203,7 +203,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
 
-static const unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv7_a8_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
@@ -314,7 +314,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_CLOCK_CYCLES,
 };
 
-static const unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static  unsigned armv7_a9_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					  [PERF_COUNT_HW_CACHE_OP_MAX]
 					  [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
@@ -424,7 +424,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
 };
 
-static const unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv7_a5_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
@@ -540,7 +540,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = ARMV7_PERFCTR_BUS_CYCLES,
 };
 
-static const unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned armv7_a15_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					[PERF_COUNT_HW_CACHE_OP_MAX]
 					[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 39affbe..21977cf 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -57,7 +57,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = HW_OP_UNSUPPORTED,
 };
 
-static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+static unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
 					   [PERF_COUNT_HW_CACHE_OP_MAX]
 					   [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
 	[C(L1D)] = {
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d8d1a5e..bccc05b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -301,3 +301,5 @@
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30-regulator.o
 obj-$(CONFIG_ARCH_MSM7X27A) += board-msm7x27a-regulator.o
 endif
+
+obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
diff --git a/arch/arm/mach-msm/acpuclock-7201.c b/arch/arm/mach-msm/acpuclock-7201.c
index 4702e51..0338d53 100644
--- a/arch/arm/mach-msm/acpuclock-7201.c
+++ b/arch/arm/mach-msm/acpuclock-7201.c
@@ -341,10 +341,86 @@
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
 };
 
+/* 7x27a pll2 at 1200mhz with GSM capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_737_pll2_1200_pll4_800[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1,  61440 },
+	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2,  61440 },
+	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3,  61440 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+	{ 0, 400000, ACPU_PLL_4, 6, 1, 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 },
+	{ 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} }
+};
+
+/* 7x27a pll2 at 1200mhz with CDMA only modem */
+static struct clkctl_acpu_speed pll0_960_pll1_589_pll2_1200_pll4_800[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
+	{ 0, 65536, ACPU_PLL_1, 1, 8,  8192, 3, 1,  49152 },
+	{ 1, 98304, ACPU_PLL_1, 1, 5,  12288, 3, 2,  49152 },
+	{ 1, 196608, ACPU_PLL_1, 1, 2, 24576, 3, 3,  98304 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 120000 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 120000 },
+	{ 0, 400000, ACPU_PLL_4, 6, 1, 50000, 3, 4, 120000 },
+	{ 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} }
+};
+
+/* 7x27aa pll4 at 1008mhz with GSM capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_737_pll2_1200_pll4_1008[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1, 61440 },
+	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2, 61440 },
+	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3, 61440 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
+	{ 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} }
+};
+
+/* 7x27aa pll4 at 1008mhz with CDMA capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_589_pll2_1200_pll4_1008[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 24576 },
+	{ 0, 65536, ACPU_PLL_1, 1, 8,  8192, 3, 1, 49152 },
+	{ 1, 98304, ACPU_PLL_1, 1, 5,  12288, 3, 2, 49152 },
+	{ 1, 196608, ACPU_PLL_1, 1, 2, 24576, 3, 3, 98304 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+	{ 1, 480000, ACPU_PLL_0, 4, 1, 60000, 3, 5, 122880 },
+	{ 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} }
+};
+
+/* 7x25a pll2 at 1200mhz with GSM capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_737_pll2_1200_pll4_800_25a[] = {
+	{ 0, 19200, ACPU_PLL_TCXO, 0, 0, 2400, 3, 0, 30720 },
+	{ 0, 61440, ACPU_PLL_1, 1, 11,  7680, 3, 1,  61440 },
+	{ 1, 122880, ACPU_PLL_1, 1, 5,  15360, 3, 2,  61440 },
+	{ 1, 245760, ACPU_PLL_1, 1, 2, 30720, 3, 3,  61440 },
+	{ 0, 300000, ACPU_PLL_2, 2, 3, 37500, 3, 4, 150000 },
+	{ 1, 320000, ACPU_PLL_0, 4, 2, 40000, 3, 4, 122880 },
+	{ 0, 400000, ACPU_PLL_4, 6, 1, 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} }
+};
+
 #define PLL_0_MHZ	0
 #define PLL_196_MHZ	10
 #define PLL_245_MHZ	12
 #define PLL_491_MHZ	25
+#define PLL_589_MHZ	30
+#define PLL_737_MHZ	38
 #define PLL_768_MHZ	40
 #define PLL_800_MHZ	41
 #define PLL_960_MHZ	50
@@ -380,6 +456,10 @@
 	PLL_CONFIG(960, 196, 1200, 800),
 	PLL_CONFIG(960, 245, 1200, 1008),
 	PLL_CONFIG(960, 196, 1200, 1008),
+	PLL_CONFIG(960, 737, 1200, 800),
+	PLL_CONFIG(960, 589, 1200, 800),
+	PLL_CONFIG(960, 737, 1200, 1008),
+	PLL_CONFIG(960, 589, 1200, 1008),
 	{ 0, 0, 0, 0, 0 }
 };
 
@@ -868,6 +948,9 @@
 		if (pll1_l == PLL_245_MHZ) {
 			acpu_freq_tbl =
 				pll0_960_pll1_245_pll2_1200_pll4_800_25a;
+		} else if (pll1_l == PLL_737_MHZ) {
+			acpu_freq_tbl =
+				pll0_960_pll1_737_pll2_1200_pll4_800_25a;
 		}
 	} else {
 		/* Select the right table to use. */
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index c70e1b5..ede298d 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -55,6 +55,7 @@
 static uint32_t bam_dmux_write_cnt;
 static uint32_t bam_dmux_write_cpy_cnt;
 static uint32_t bam_dmux_write_cpy_bytes;
+static uint32_t bam_dmux_tx_sps_failure_cnt;
 
 #define DBG(x...) do {		                 \
 		if (msm_bam_dmux_debug_enable)  \
@@ -83,11 +84,17 @@
 				 __func__, bam_dmux_write_cpy_cnt,          \
 				 bam_dmux_write_cpy_bytes);                 \
 	} while (0)
+
+#define DBG_INC_TX_SPS_FAILURE_CNT() do {	\
+		bam_dmux_tx_sps_failure_cnt++;		\
+} while (0)
+
 #else
 #define DBG(x...) do { } while (0)
 #define DBG_INC_READ_CNT(x...) do { } while (0)
 #define DBG_INC_WRITE_CNT(x...) do { } while (0)
 #define DBG_INC_WRITE_CPY(x...) do { } while (0)
+#define DBG_INC_TX_SPS_FAILURE_CNT() do { } while (0)
 #endif
 
 struct bam_ch_info {
@@ -377,6 +384,7 @@
 		DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
 		spin_lock(&bam_tx_pool_spinlock);
 		list_del(&pkt->list_node);
+		DBG_INC_TX_SPS_FAILURE_CNT();
 		spin_unlock(&bam_tx_pool_spinlock);
 		kfree(pkt);
 	}
@@ -509,6 +517,7 @@
 		DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
 		spin_lock(&bam_tx_pool_spinlock);
 		list_del(&pkt->list_node);
+		DBG_INC_TX_SPS_FAILURE_CNT();
 		spin_unlock(&bam_tx_pool_spinlock);
 		kfree(pkt);
 	}
@@ -815,6 +824,37 @@
 	return i;
 }
 
+static int debug_ul_pkt_cnt(char *buf, int max)
+{
+	struct list_head *p;
+	unsigned long flags;
+	int n = 0;
+
+	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
+	__list_for_each(p, &bam_tx_pool) {
+		++n;
+	}
+	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
+
+	return scnprintf(buf, max, "Number of UL packets in flight: %d\n", n);
+}
+
+static int debug_stats(char *buf, int max)
+{
+	int i = 0;
+
+	i += scnprintf(buf + i, max - i,
+			"skb copy cnt:    %u\n"
+			"skb copy bytes:  %u\n"
+			"sps tx failures: %u\n",
+			bam_dmux_write_cpy_cnt,
+			bam_dmux_write_cpy_bytes,
+			bam_dmux_tx_sps_failure_cnt
+			);
+
+	return i;
+}
+
 #define DEBUG_BUFMAX 4096
 static char debug_buffer[DEBUG_BUFMAX];
 
@@ -877,9 +917,17 @@
 
 static void ul_timeout(struct work_struct *work)
 {
+	unsigned long flags;
+	int ret;
+
 	if (in_global_reset)
 		return;
-	write_lock(&ul_wakeup_lock);
+	ret = write_trylock_irqsave(&ul_wakeup_lock, flags);
+	if (!ret) { /* failed to grab lock, reschedule and bail */
+		schedule_delayed_work(&ul_timeout_work,
+				msecs_to_jiffies(UL_TIMEOUT_DELAY));
+		return;
+	}
 	if (ul_packet_written) {
 		ul_packet_written = 0;
 		schedule_delayed_work(&ul_timeout_work,
@@ -889,7 +937,7 @@
 		bam_is_connected = 0;
 		notify_all(BAM_DMUX_UL_DISCONNECTED, (unsigned long)(NULL));
 	}
-	write_unlock(&ul_wakeup_lock);
+	write_unlock_irqrestore(&ul_wakeup_lock, flags);
 }
 static void ul_wakeup(void)
 {
@@ -1299,8 +1347,11 @@
 	struct dentry *dent;
 
 	dent = debugfs_create_dir("bam_dmux", 0);
-	if (!IS_ERR(dent))
+	if (!IS_ERR(dent)) {
 		debug_create("tbl", 0444, dent, debug_tbl);
+		debug_create("ul_pkt_cnt", 0444, dent, debug_ul_pkt_cnt);
+		debug_create("stats", 0444, dent, debug_stats);
+	}
 #endif
 	subsys_notif_register_notifier("modem", &restart_notifier);
 	return platform_driver_register(&bam_dmux_driver);
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
index 00886c6..53c290e 100644
--- a/arch/arm/mach-msm/board-apq8064.c
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -661,6 +661,7 @@
 
 static struct platform_device *rumi3_devices[] __initdata = {
 	&apq8064_device_uart_gsbi1,
+	&msm_device_sps_apq8064,
 };
 
 static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
diff --git a/arch/arm/mach-msm/board-mahimahi-smb329.c b/arch/arm/mach-msm/board-mahimahi-smb329.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 1435774..05b4896 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -1072,7 +1072,7 @@
 #define MSM_PMEM_MDP_SIZE       0x1900000
 #define MSM7x25A_MSM_PMEM_MDP_SIZE	0x1000000
 
-#define MSM_PMEM_ADSP_SIZE      0x1000000
+#define MSM_PMEM_ADSP_SIZE      0x2000000
 #define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
 
 
@@ -3041,7 +3041,7 @@
 #define ATMEL_X_OFFSET 13
 #define ATMEL_Y_OFFSET 0
 
-static struct mxt_platform_data atmel_ts_pdata = {
+static struct maxtouch_platform_data atmel_ts_pdata = {
 	.numtouch = 4,
 	.init_platform_hw = atmel_ts_platform_init,
 	.exit_platform_hw = atmel_ts_platform_exit,
diff --git a/arch/arm/mach-msm/board-msm7x30-regulator.c b/arch/arm/mach-msm/board-msm7x30-regulator.c
index 0ca7f16..5329bbe 100644
--- a/arch/arm/mach-msm/board-msm7x30-regulator.c
+++ b/arch/arm/mach-msm/board-msm7x30-regulator.c
@@ -274,7 +274,7 @@
 	 *             name  id  supp    min uV    max uV  R   P  A  B  V  S */
 	PCOM_VREG_SMP(smps0,  3, NULL,   500000,  1500000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps1,  4, NULL,   500000,  1500000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_SMP(smps2, 28, NULL,  1225000,  1225000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_SMP(smps2, 28, NULL,  1300000,  1300000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps3, 29, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_SMP(smps4, 43, NULL,  2200000,  2200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo00,  5, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
@@ -282,7 +282,7 @@
 	PCOM_VREG_LDO(ldo03, 19, NULL,  1800000,  3000000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo04,  9, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo05, 18, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo06, 16, NULL,  3075000,  3075000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo06, 16, NULL,  3075000,  3400000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo07, 44, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo08, 32, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo09,  8, NULL,  2050000,  2050000, 0, -1, 0, 0, 0, 0),
@@ -291,16 +291,16 @@
 	PCOM_VREG_LDO(ldo12, 34, NULL,  1800000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo13, 15, NULL,  2900000,  2900000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo14, 24, NULL,  2850000,  2850000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo15, 23, NULL,  3100000,  3100000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo15, 23, NULL,  3050000,  3100000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo16, 35, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo17, 36, NULL,  2600000,  2600000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo18, 37, NULL,  2200000,  2200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo19, 45, NULL,  2500000,  2500000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo20, 38, NULL,  1500000,  1500000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo20, 38, NULL,  1500000,  1800000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo21, 39, NULL,  1100000,  1100000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo22, 40, NULL,  1300000,  1300000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo23, 22, NULL,  1350000,  1350000, 0, -1, 0, 0, 0, 0),
-	PCOM_VREG_LDO(ldo24, 41, NULL,  1225000,  1225000, 0, -1, 0, 0, 0, 0),
+	PCOM_VREG_LDO(ldo24, 41, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
 	PCOM_VREG_LDO(ldo25, 42, NULL,  1200000,  1200000, 0, -1, 0, 0, 0, 0),
 
 	/* Low-voltage switches */
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index eda29cd..d73f612 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -37,6 +37,7 @@
 #include <linux/input/cy8c_ts.h>
 #include <linux/msm_adc.h>
 #include <linux/dma-mapping.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -331,56 +332,43 @@
 };
 
 static struct kobject *properties_kobj;
+static struct regulator_bulk_data cyttsp_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo15", .min_uV = 3050000, .max_uV = 3100000 },
+};
 
 #define CYTTSP_TS_GPIO_IRQ	150
 static int cyttsp_platform_init(struct i2c_client *client)
 {
 	int rc = -EINVAL;
-	struct vreg *vreg_ldo8, *vreg_ldo15;
 
-	vreg_ldo8 = vreg_get(NULL, "gp7");
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
 
-	if (!vreg_ldo8) {
-		pr_err("%s: VREG L8 get failed\n", __func__);
-		return rc;
-	}
-
-	rc = vreg_set_level(vreg_ldo8, 1800);
 	if (rc) {
-		pr_err("%s: VREG L8 set failed\n", __func__);
-		goto l8_put;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_ldo8);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+
 	if (rc) {
-		pr_err("%s: VREG L8 enable failed\n", __func__);
-		goto l8_put;
+		pr_err("%s: could not set regulator voltages: %d\n", __func__,
+				rc);
+		goto regs_free;
 	}
 
-	vreg_ldo15 = vreg_get(NULL, "gp6");
+	rc = regulator_bulk_enable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
 
-	if (!vreg_ldo15) {
-		pr_err("%s: VREG L15 get failed\n", __func__);
-		goto l8_disable;
-	}
-
-	rc = vreg_set_level(vreg_ldo15, 3050);
 	if (rc) {
-		pr_err("%s: VREG L15 set failed\n", __func__);
-		goto l8_disable;
-	}
-
-	rc = vreg_enable(vreg_ldo15);
-	if (rc) {
-		pr_err("%s: VREG L15 enable failed\n", __func__);
-		goto l8_disable;
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+		goto regs_free;
 	}
 
 	/* check this device active by reading first byte/register */
 	rc = i2c_smbus_read_byte_data(client, 0x01);
 	if (rc < 0) {
 		pr_err("%s: i2c sanity check failed\n", __func__);
-		goto l8_disable;
+		goto regs_disable;
 	}
 
 	rc = gpio_tlmm_config(GPIO_CFG(CYTTSP_TS_GPIO_IRQ, 0, GPIO_CFG_INPUT,
@@ -388,7 +376,7 @@
 	if (rc) {
 		pr_err("%s: Could not configure gpio %d\n",
 					 __func__, CYTTSP_TS_GPIO_IRQ);
-		goto l8_disable;
+		goto regs_disable;
 	}
 
 	/* virtual keys */
@@ -404,10 +392,11 @@
 
 	return CY_OK;
 
-l8_disable:
-	vreg_disable(vreg_ldo8);
-l8_put:
-	vreg_put(vreg_ldo8);
+regs_disable:
+	regulator_bulk_disable(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+regs_free:
+	regulator_bulk_free(ARRAY_SIZE(cyttsp_regs), cyttsp_regs);
+out:
 	return rc;
 }
 
@@ -1371,58 +1360,54 @@
 	pr_info("%s: power off amplifier\n", __func__);
 }
 
-static struct vreg *snddev_vreg_ncp, *snddev_vreg_gp4;
+static struct regulator_bulk_data snddev_regs[] = {
+	{ .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "ncp", .min_uV = 1800000, .max_uV = 1800000 },
+};
 
-void msm_snddev_hsed_voltage_on(void)
+static int __init snddev_hsed_voltage_init(void)
 {
 	int rc;
 
-	snddev_vreg_gp4 = vreg_get(NULL, "gp4");
-	if (IS_ERR(snddev_vreg_gp4)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "gp4", PTR_ERR(snddev_vreg_gp4));
-		return;
-	}
-	rc = vreg_enable(snddev_vreg_gp4);
-	if (rc)
-		pr_err("%s: vreg_enable(gp4) failed (%d)\n", __func__, rc);
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(snddev_regs), snddev_regs);
 
-	snddev_vreg_ncp = vreg_get(NULL, "ncp");
-	if (IS_ERR(snddev_vreg_ncp)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "ncp", PTR_ERR(snddev_vreg_ncp));
-		return;
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
-	rc = vreg_enable(snddev_vreg_ncp);
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(snddev_regs), snddev_regs);
+
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto regs_free;
+	}
+
+	return 0;
+
+regs_free:
+	regulator_bulk_free(ARRAY_SIZE(snddev_regs), snddev_regs);
+out:
+	return rc;
+}
+
+
+void msm_snddev_hsed_voltage_on(void)
+{
+	int rc = regulator_bulk_enable(ARRAY_SIZE(snddev_regs), snddev_regs);
+
 	if (rc)
-		pr_err("%s: vreg_enable(ncp) failed (%d)\n", __func__, rc);
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
 }
 
 void msm_snddev_hsed_voltage_off(void)
 {
-	int rc;
+	int rc = regulator_bulk_disable(ARRAY_SIZE(snddev_regs), snddev_regs);
 
-	if (IS_ERR(snddev_vreg_ncp)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "ncp", PTR_ERR(snddev_vreg_ncp));
-		return;
+	if (rc) {
+		pr_err("%s: could not disable regulators: %d\n", __func__, rc);
 	}
-	rc = vreg_disable(snddev_vreg_ncp);
-	if (rc)
-		pr_err("%s: vreg_disable(ncp) failed (%d)\n", __func__, rc);
-	vreg_put(snddev_vreg_ncp);
-
-	if (IS_ERR(snddev_vreg_gp4)) {
-		pr_err("%s: vreg_get(%s) failed (%ld)\n",
-		__func__, "gp4", PTR_ERR(snddev_vreg_gp4));
-		return;
-	}
-	rc = vreg_disable(snddev_vreg_gp4);
-	if (rc)
-		pr_err("%s: vreg_disable(gp4) failed (%d)\n", __func__, rc);
-
-	vreg_put(snddev_vreg_gp4);
-
 }
 
 static unsigned aux_pcm_gpio_on[] = {
@@ -1605,10 +1590,9 @@
 	VER_UNSUPPORTED = 0xFF
 };
 
-
-static struct vreg *vreg_marimba_1;
-static struct vreg *vreg_marimba_2;
-static struct vreg *vreg_marimba_3;
+static struct regulator *vreg_marimba_1;
+static struct regulator *vreg_marimba_2;
+static struct regulator *vreg_bahama;
 
 static struct msm_gpio timpani_reset_gpio_cfg[] = {
 { GPIO_CFG(TIMPANI_RESET_GPIO, 0, GPIO_CFG_OUTPUT,
@@ -1666,34 +1650,33 @@
 	if (rc < 0)
 		goto out;
 
-	rc = vreg_enable(vreg_marimba_1);
+	rc = regulator_enable(vreg_marimba_1);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 		goto out;
 	}
-	rc = vreg_enable(vreg_marimba_2);
+
+	rc = regulator_enable(vreg_marimba_2);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
-		goto fail_disable_vreg_marimba_1;
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto disable_marimba_1;
 	}
 
 	rc = gpio_direction_output(TIMPANI_RESET_GPIO, 1);
 	if (rc < 0) {
-		printk(KERN_ERR
-			"%s: gpio_direction_output failed (%d)\n",
+		pr_err("%s: gpio_direction_output failed (%d)\n",
 				__func__, rc);
 		msm_gpios_free(timpani_reset_gpio_cfg,
 				ARRAY_SIZE(timpani_reset_gpio_cfg));
-		vreg_disable(vreg_marimba_2);
-	} else
-		goto out;
+		goto disable_marimba_2;
+	}
 
+	return 0;
 
-fail_disable_vreg_marimba_1:
-	vreg_disable(vreg_marimba_1);
-
+disable_marimba_2:
+	regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+	regulator_disable(vreg_marimba_1);
 out:
 	return rc;
 };
@@ -1702,23 +1685,18 @@
 {
 	int rc;
 
-	rc = vreg_disable(vreg_marimba_1);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
-	rc = vreg_disable(vreg_marimba_2);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
+	rc = regulator_disable(vreg_marimba_2);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+	rc = regulator_disable(vreg_marimba_1);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
 
 	rc = gpio_direction_output(TIMPANI_RESET_GPIO, 0);
-	if (rc < 0) {
-		printk(KERN_ERR
-			"%s: gpio_direction_output failed (%d)\n",
+	if (rc < 0)
+		pr_err("%s: gpio_direction_output failed (%d)\n",
 				__func__, rc);
-	}
 
 	msm_gpios_free(timpani_reset_gpio_cfg,
 				   ARRAY_SIZE(timpani_reset_gpio_cfg));
@@ -1767,13 +1745,10 @@
 
 static unsigned int msm_bahama_setup_power(void)
 {
-	int rc;
+	int rc = regulator_enable(vreg_bahama);
 
-	rc = vreg_enable(vreg_marimba_3);
-	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-				__func__, rc);
-	}
+	if (rc)
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 
 	return rc;
 };
@@ -1783,11 +1758,11 @@
 	int rc = 0;
 
 	if (value != BAHAMA_ID) {
-		rc = vreg_disable(vreg_marimba_3);
-		if (rc) {
-			printk(KERN_ERR "%s: return val: %d\n",
+		rc = regulator_disable(vreg_bahama);
+
+		if (rc)
+			pr_err("%s: regulator_disable failed (%d)\n",
 					__func__, rc);
-		}
 	}
 
 	return rc;
@@ -1817,39 +1792,42 @@
 {
 	int rc;
 
-	rc = vreg_enable(vreg_marimba_1);
+	rc = regulator_enable(vreg_marimba_1);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
 		goto out;
 	}
-	rc = vreg_enable(vreg_marimba_2);
+
+	rc = regulator_enable(vreg_marimba_2);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		goto out;
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto disable_marimba_1;
 	}
 
 	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = msm_gpios_request_enable(marimba_svlte_config_clock,
 				ARRAY_SIZE(marimba_svlte_config_clock));
 		if (rc < 0) {
-			printk(KERN_ERR
-				"%s: msm_gpios_request_enable failed (%d)\n",
+			pr_err("%s: msm_gpios_request_enable failed (%d)\n",
 					__func__, rc);
-			return rc;
+			goto disable_marimba_2;
 		}
 
 		rc = gpio_direction_output(GPIO_PIN
 			(marimba_svlte_config_clock->gpio_cfg), 0);
 		if (rc < 0) {
-			printk(KERN_ERR
-				"%s: gpio_direction_output failed (%d)\n",
+			pr_err("%s: gpio_direction_output failed (%d)\n",
 					__func__, rc);
-			return rc;
+			goto disable_marimba_2;
 		}
 	}
 
+	return 0;
+
+disable_marimba_2:
+	regulator_disable(vreg_marimba_2);
+disable_marimba_1:
+	regulator_disable(vreg_marimba_1);
 out:
 	return rc;
 };
@@ -1858,16 +1836,13 @@
 {
 	int rc;
 
-	rc = vreg_disable(vreg_marimba_1);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-	}
-	rc = vreg_disable(vreg_marimba_2);
-	if (rc) {
-		printk(KERN_ERR "%s: return val: %d \n",
-					__func__, rc);
-	}
+	rc = regulator_disable(vreg_marimba_2);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
+
+	rc = regulator_disable(vreg_marimba_1);
+	if (rc)
+		pr_err("%s: regulator_disable failed (%d)\n", __func__, rc);
 };
 
 static int bahama_present(void)
@@ -1888,81 +1863,89 @@
 	}
 }
 
-struct vreg *fm_regulator;
+struct regulator *fm_regulator;
 static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
 {
-	int rc;
+	int rc, voltage;
 	uint32_t irqcfg;
 	const char *id = "FMPW";
 
 	int bahama_not_marimba = bahama_present();
 
-	if (bahama_not_marimba == -1) {
-		printk(KERN_WARNING "%s: bahama_present: %d\n",
+	if (bahama_not_marimba < 0) {
+		pr_warn("%s: bahama_present: %d\n",
 				__func__, bahama_not_marimba);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out;
 	}
-	if (bahama_not_marimba)
-		fm_regulator = vreg_get(NULL, "s3");
-	else
-		fm_regulator = vreg_get(NULL, "s2");
+	if (bahama_not_marimba) {
+		fm_regulator = regulator_get(NULL, "s3");
+		voltage = 1800000;
+	} else {
+		fm_regulator = regulator_get(NULL, "s2");
+		voltage = 1300000;
+	}
 
 	if (IS_ERR(fm_regulator)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(fm_regulator));
-		return -1;
+		rc = PTR_ERR(fm_regulator);
+		pr_err("%s: regulator_get failed (%d)\n", __func__, rc);
+		goto out;
 	}
-	if (!bahama_not_marimba) {
 
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
+	rc = regulator_set_voltage(fm_regulator, voltage, voltage);
 
-		if (rc < 0) {
-			printk(KERN_ERR "%s: voltage level vote failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	}
-	rc = vreg_enable(fm_regulator);
 	if (rc) {
-		printk(KERN_ERR "%s: vreg_enable() = %d\n",
-					__func__, rc);
-		return rc;
+		pr_err("%s: regulator_set_voltage failed (%d)\n", __func__, rc);
+		goto regulator_free;
 	}
 
-	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
-					  PMAPP_CLOCK_VOTE_ON);
-	if (rc < 0) {
-		printk(KERN_ERR "%s: clock vote failed (%d)\n",
-			__func__, rc);
-		goto fm_clock_vote_fail;
+	rc = regulator_enable(fm_regulator);
+
+	if (rc) {
+		pr_err("%s: regulator_enable failed (%d)\n", __func__, rc);
+		goto regulator_free;
 	}
+
+	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_ON);
+
+	if (rc < 0) {
+		pr_err("%s: clock vote failed (%d)\n", __func__, rc);
+		goto regulator_disable;
+	}
+
 	/*Request the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
 	of svlte*/
-	if (machine_is_msm8x55_svlte_surf() ||
-			machine_is_msm8x55_svlte_ffa())	{
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = marimba_gpio_config(1);
-		if (rc < 0)
-			printk(KERN_ERR "%s: clock enable for svlte : %d\n",
-						__func__, rc);
+		if (rc < 0) {
+			pr_err("%s: clock enable for svlte : %d\n",
+					__func__, rc);
+			goto clock_devote;
+		}
 	}
 	irqcfg = GPIO_CFG(147, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA);
 	rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
 	if (rc) {
-		printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
-				__func__, irqcfg, rc);
+		pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
 		rc = -EIO;
-		goto fm_gpio_config_fail;
+		goto gpio_deconfig;
 
 	}
 	return 0;
-fm_gpio_config_fail:
-	pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
-				  PMAPP_CLOCK_VOTE_OFF);
-fm_clock_vote_fail:
-	vreg_disable(fm_regulator);
-	return rc;
 
+gpio_deconfig:
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa())
+		marimba_gpio_config(0);
+clock_devote:
+	pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO, PMAPP_CLOCK_VOTE_OFF);
+regulator_disable:
+	regulator_disable(fm_regulator);
+regulator_free:
+	regulator_put(fm_regulator);
+	fm_regulator = NULL;
+out:
+	return rc;
 };
 
 static void fm_radio_shutdown(struct marimba_fm_platform_data *pdata)
@@ -1974,48 +1957,36 @@
 
 	int bahama_not_marimba = bahama_present();
 	if (bahama_not_marimba == -1) {
-		printk(KERN_WARNING "%s: bahama_present: %d\n",
-			__func__, bahama_not_marimba);
+		pr_warn("%s: bahama_present: %d\n",
+				__func__, bahama_not_marimba);
 		return;
 	}
 
 	rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
 	if (rc) {
-		printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n",
-				__func__, irqcfg, rc);
+		pr_err("%s: gpio_tlmm_config(%#x)=%d\n", __func__, irqcfg, rc);
 	}
-	if (fm_regulator != NULL) {
-		rc = vreg_disable(fm_regulator);
+	if (!IS_ERR_OR_NULL(fm_regulator)) {
+		rc = regulator_disable(fm_regulator);
 
-		if (rc) {
-			printk(KERN_ERR "%s: return val: %d\n",
-					__func__, rc);
-		}
+		if (rc)
+			pr_err("%s: return val: %d\n", __func__, rc);
+
+		regulator_put(fm_regulator);
 		fm_regulator = NULL;
 	}
 	rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
 					  PMAPP_CLOCK_VOTE_OFF);
 	if (rc < 0)
-		printk(KERN_ERR "%s: clock_vote return val: %d\n",
-						__func__, rc);
+		pr_err("%s: clock_vote return val: %d\n", __func__, rc);
 
 	/*Disable the Clock Using GPIO34/AP2MDM_MRMBCK_EN in case
 	of svlte*/
-	if (machine_is_msm8x55_svlte_surf() ||
-			machine_is_msm8x55_svlte_ffa())	{
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa()) {
 		rc = marimba_gpio_config(0);
 		if (rc < 0)
-			printk(KERN_ERR "%s: clock disable for svlte : %d\n",
-						__func__, rc);
-	}
-
-
-	if (!bahama_not_marimba)	{
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
-
-		if (rc < 0)
-			printk(KERN_ERR "%s: vreg level vote return val: %d\n",
-						__func__, rc);
+			pr_err("%s: clock disable for svlte : %d\n",
+					__func__, rc);
 	}
 }
 
@@ -2042,82 +2013,60 @@
 #define BAHAMA_SLAVE_ID_QMEMBIST_ADDR   0x7B
 
 static const char *tsadc_id = "MADC";
-static const char *vregs_tsadc_name[] = {
-	"gp12",
-	"s2",
-};
-static struct vreg *vregs_tsadc[ARRAY_SIZE(vregs_tsadc_name)];
 
-static const char *vregs_timpani_tsadc_name[] = {
-	"s3",
-	"gp12",
-	"gp16"
+static struct regulator_bulk_data regs_tsadc_marimba[] = {
+	{ .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+	{ .supply = "s2",   .min_uV = 1300000, .max_uV = 1300000 },
 };
-static struct vreg *vregs_timpani_tsadc[ARRAY_SIZE(vregs_timpani_tsadc_name)];
+
+static struct regulator_bulk_data regs_tsadc_timpani[] = {
+	{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp12", .min_uV = 2200000, .max_uV = 2200000 },
+	{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static struct regulator_bulk_data *regs_tsadc;
+static int regs_tsadc_count;
 
 static int marimba_tsadc_power(int vreg_on)
 {
-	int i, rc = 0;
+	int rc = 0;
 	int tsadc_adie_type = adie_get_detected_codec_type();
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			if (!vregs_timpani_tsadc[i]) {
-				pr_err("%s: vreg_get %s failed(%d)\n",
-				__func__, vregs_timpani_tsadc_name[i], rc);
-				goto vreg_fail;
-			}
-
-			rc = vreg_on ? vreg_enable(vregs_timpani_tsadc[i]) :
-				  vreg_disable(vregs_timpani_tsadc[i]);
-			if (rc < 0) {
-				pr_err("%s: vreg %s %s failed(%d)\n",
-					__func__, vregs_timpani_tsadc_name[i],
-				       vreg_on ? "enable" : "disable", rc);
-				goto vreg_fail;
-			}
-		}
-		/* Vote for D0 and D1 buffer */
+	switch (tsadc_adie_type) {
+	case TIMPANI_ID:
 		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
 			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
 		if (rc)	{
 			pr_err("%s: unable to %svote for d1 clk\n",
 				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
+			goto D1_vote_fail;
 		}
+
+		/* fall through */
+	case MARIMBA_ID:
 		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
 			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
 		if (rc)	{
 			pr_err("%s: unable to %svote for d1 clk\n",
 				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
+			goto D0_vote_fail;
 		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			if (!vregs_tsadc[i]) {
-				pr_err("%s: vreg_get %s failed (%d)\n",
-					__func__, vregs_tsadc_name[i], rc);
-				goto vreg_fail;
-			}
 
-			rc = vreg_on ? vreg_enable(vregs_tsadc[i]) :
-				  vreg_disable(vregs_tsadc[i]);
-			if (rc < 0) {
-				pr_err("%s: vreg %s %s failed (%d)\n",
-					__func__, vregs_tsadc_name[i],
-				       vreg_on ? "enable" : "disable", rc);
-				goto vreg_fail;
-			}
+		WARN_ON(regs_tsadc_count == 0);
+
+		rc = vreg_on ?
+			regulator_bulk_enable(regs_tsadc_count, regs_tsadc) :
+			regulator_bulk_disable(regs_tsadc_count, regs_tsadc);
+
+		if (rc) {
+			pr_err("%s: regulator %sable failed: %d\n",
+					__func__, vreg_on ? "en" : "dis", rc);
+			goto regulator_switch_fail;
 		}
-		/* If marimba vote for DO buffer */
-		rc = pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
-			vreg_on ? PMAPP_CLOCK_VOTE_ON : PMAPP_CLOCK_VOTE_OFF);
-		if (rc)	{
-			pr_err("%s: unable to %svote for d0 clk\n",
-				__func__, vreg_on ? "" : "de-");
-			goto do_vote_fail;
-		}
-	} else {
+
+		break;
+	default:
 		pr_err("%s:Adie %d not supported\n",
 				__func__, tsadc_adie_type);
 		return -ENODEV;
@@ -2127,112 +2076,69 @@
 
 	return 0;
 
-do_vote_fail:
-vreg_fail:
-	while (i) {
-		if (vreg_on) {
-			if (tsadc_adie_type == TIMPANI_ID)
-				vreg_disable(vregs_timpani_tsadc[--i]);
-			else if (tsadc_adie_type == MARIMBA_ID)
-				vreg_disable(vregs_tsadc[--i]);
-		} else {
-			if (tsadc_adie_type == TIMPANI_ID)
-				vreg_enable(vregs_timpani_tsadc[--i]);
-			else if (tsadc_adie_type == MARIMBA_ID)
-				vreg_enable(vregs_tsadc[--i]);
-		}
-	}
-
-	return rc;
-}
-
-static int marimba_tsadc_vote(int vote_on)
-{
-	int rc = 0;
-
-	if (adie_get_detected_codec_type() == MARIMBA_ID) {
-		int level = vote_on ? 1300 : 0;
-		rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, level);
-		if (rc < 0)
-			pr_err("%s: vreg level %s failed (%d)\n",
-			__func__, vote_on ? "on" : "off", rc);
-	}
-
+regulator_switch_fail:
+	pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_DO,
+		vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D0_vote_fail:
+	if (tsadc_adie_type == TIMPANI_ID)
+		pmapp_clock_vote(tsadc_id, PMAPP_CLOCK_ID_D1,
+			vreg_on ? PMAPP_CLOCK_VOTE_OFF : PMAPP_CLOCK_VOTE_ON);
+D1_vote_fail:
 	return rc;
 }
 
 static int marimba_tsadc_init(void)
 {
-	int i, rc = 0;
+	int rc = 0;
 	int tsadc_adie_type = adie_get_detected_codec_type();
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			vregs_timpani_tsadc[i] = vreg_get(NULL,
-						vregs_timpani_tsadc_name[i]);
-			if (IS_ERR(vregs_timpani_tsadc[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-				       __func__, vregs_timpani_tsadc_name[i],
-				       PTR_ERR(vregs_timpani_tsadc[i]));
-				rc = PTR_ERR(vregs_timpani_tsadc[i]);
-				goto vreg_get_fail;
-			}
-		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			vregs_tsadc[i] = vreg_get(NULL, vregs_tsadc_name[i]);
-			if (IS_ERR(vregs_tsadc[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-				       __func__, vregs_tsadc_name[i],
-				       PTR_ERR(vregs_tsadc[i]));
-				rc = PTR_ERR(vregs_tsadc[i]);
-				goto vreg_get_fail;
-			}
-		}
-	} else {
+	switch (tsadc_adie_type) {
+	case MARIMBA_ID:
+		regs_tsadc = regs_tsadc_marimba;
+		regs_tsadc_count = ARRAY_SIZE(regs_tsadc_marimba);
+		break;
+	case TIMPANI_ID:
+		regs_tsadc = regs_tsadc_timpani;
+		regs_tsadc_count = ARRAY_SIZE(regs_tsadc_timpani);
+		break;
+	default:
 		pr_err("%s:Adie %d not supported\n",
 				__func__, tsadc_adie_type);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out;
+	}
+
+	rc = regulator_bulk_get(NULL, regs_tsadc_count, regs_tsadc);
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
+	}
+
+	rc = regulator_bulk_set_voltage(regs_tsadc_count, regs_tsadc);
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto vreg_free;
 	}
 
 	return 0;
 
-vreg_get_fail:
-	while (i) {
-		if (tsadc_adie_type == TIMPANI_ID)
-			vreg_put(vregs_timpani_tsadc[--i]);
-		else if (tsadc_adie_type == MARIMBA_ID)
-			vreg_put(vregs_tsadc[--i]);
-	}
+vreg_free:
+	regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+out:
+	regs_tsadc = NULL;
+	regs_tsadc_count = 0;
 	return rc;
 }
 
 static int marimba_tsadc_exit(void)
 {
-	int i, rc = 0;
-	int tsadc_adie_type = adie_get_detected_codec_type();
+	regulator_bulk_free(regs_tsadc_count, regs_tsadc);
+	regs_tsadc_count = 0;
+	regs_tsadc = NULL;
 
-	if (tsadc_adie_type == TIMPANI_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_timpani_tsadc_name); i++) {
-			if (vregs_tsadc[i])
-				vreg_put(vregs_timpani_tsadc[i]);
-		}
-	} else if (tsadc_adie_type == MARIMBA_ID) {
-		for (i = 0; i < ARRAY_SIZE(vregs_tsadc_name); i++) {
-			if (vregs_tsadc[i])
-				vreg_put(vregs_tsadc[i]);
-		}
-		rc = pmapp_vreg_level_vote(tsadc_id, PMAPP_VREG_S2, 0);
-		if (rc < 0)
-			pr_err("%s: vreg level off failed (%d)\n",
-						__func__, rc);
-	} else {
-		pr_err("%s:Adie %d not supported\n",
-				__func__, tsadc_adie_type);
-		rc = -ENODEV;
-	}
-
-	return rc;
+	return 0;
 }
 
 
@@ -2252,7 +2158,6 @@
 	.marimba_tsadc_power =  marimba_tsadc_power,
 	.init		     =  marimba_tsadc_init,
 	.exit		     =  marimba_tsadc_exit,
-	.level_vote	     =  marimba_tsadc_vote,
 	.tsadc_prechg_en = true,
 	.can_wakeup	= false,
 	.setup = {
@@ -2271,39 +2176,47 @@
 	.tssc_data = &msm_ts_data,
 };
 
-static struct vreg *vreg_codec_s4;
+static struct regulator_bulk_data codec_regs[] = {
+	{ .supply = "s4", .min_uV = 2200000, .max_uV = 2200000 },
+};
+
+static int __init msm_marimba_codec_init(void)
+{
+	int rc = regulator_bulk_get(NULL, ARRAY_SIZE(codec_regs), codec_regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(codec_regs), codec_regs);
+	if (rc) {
+		pr_err("%s: could not set regulator voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
+	}
+
+	return rc;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(codec_regs), codec_regs);
+out:
+	return rc;
+}
+
 static int msm_marimba_codec_power(int vreg_on)
 {
-	int rc = 0;
+	int rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(codec_regs), codec_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(codec_regs), codec_regs);
 
-	if (!vreg_codec_s4) {
-
-		vreg_codec_s4 = vreg_get(NULL, "s4");
-
-		if (IS_ERR(vreg_codec_s4)) {
-			printk(KERN_ERR "%s: vreg_get() failed (%ld)\n",
-				__func__, PTR_ERR(vreg_codec_s4));
-			rc = PTR_ERR(vreg_codec_s4);
-			goto  vreg_codec_s4_fail;
-		}
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d",
+				__func__, vreg_on ? "en" : "dis", rc);
+		return rc;
 	}
 
-	if (vreg_on) {
-		rc = vreg_enable(vreg_codec_s4);
-		if (rc)
-			printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		goto vreg_codec_s4_fail;
-	} else {
-		rc = vreg_disable(vreg_codec_s4);
-		if (rc)
-			printk(KERN_ERR "%s: vreg_disable() = %d \n",
-					__func__, rc);
-		goto vreg_codec_s4_fail;
-	}
-
-vreg_codec_s4_fail:
-	return rc;
+	return 0;
 }
 
 static struct marimba_codec_platform_data mariba_codec_pdata = {
@@ -2334,29 +2247,38 @@
 {
 	int rc;
 
-	vreg_marimba_1 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_marimba_1)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_1));
-		return;
-	}
-	rc = vreg_set_level(vreg_marimba_1, 1800);
+	struct regulator_bulk_data regs[] = {
+		{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+		{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+		{ .supply = "usb2", .min_uV = 1800000, .max_uV = 1800000 },
+	};
 
-	vreg_marimba_2 = vreg_get(NULL, "gp16");
-	if (IS_ERR(vreg_marimba_1)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_1));
-		return;
-	}
-	rc = vreg_set_level(vreg_marimba_2, 1200);
+	rc = msm_marimba_codec_init();
 
-	vreg_marimba_3 = vreg_get(NULL, "usb2");
-	if (IS_ERR(vreg_marimba_3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_marimba_3));
+	if (rc) {
+		pr_err("%s: msm_marimba_codec_init failed (%d)\n",
+				__func__, rc);
 		return;
 	}
-	rc = vreg_set_level(vreg_marimba_3, 1800);
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		return;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		regulator_bulk_free(ARRAY_SIZE(regs), regs);
+		return;
+	}
+
+	vreg_marimba_1 = regs[0].consumer;
+	vreg_marimba_2 = regs[1].consumer;
+	vreg_bahama    = regs[2].consumer;
 }
 
 static struct marimba_codec_platform_data timpani_codec_pdata = {
@@ -2748,6 +2670,13 @@
 	"optnav_chip_select" },
 };
 
+static struct regulator_bulk_data optnav_regulators[] = {
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp4", .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "gp9", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "usb", .min_uV = 3300000, .max_uV = 3300000 },
+};
+
 static void __iomem *virtual_optnav;
 
 static int optnav_gpio_setup(void)
@@ -2756,6 +2685,9 @@
 	rc = msm_gpios_request_enable(optnav_config_data,
 			ARRAY_SIZE(optnav_config_data));
 
+	if (rc)
+		return rc;
+
 	/* Configure the FPGA for GPIOs */
 	virtual_optnav = ioremap(FPGA_OPTNAV_GPIO_ADDR, 0x4);
 	if (!virtual_optnav) {
@@ -2767,6 +2699,22 @@
 	 * normal, active(enabled), output(MSM to SURF)
 	 */
 	writew(0x311E, virtual_optnav);
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
+	if (rc)
+		return rc;
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
+
+	if (rc)
+		goto regulator_put;
+
+	return rc;
+
+regulator_put:
+	regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
 	return rc;
 }
 
@@ -2775,13 +2723,9 @@
 	msm_gpios_disable_free(optnav_config_data,
 		ARRAY_SIZE(optnav_config_data));
 	iounmap(virtual_optnav);
+	regulator_bulk_free(ARRAY_SIZE(optnav_regulators), optnav_regulators);
 }
 
-static struct vreg *vreg_gp7;
-static struct vreg *vreg_gp4;
-static struct vreg *vreg_gp9;
-static struct vreg *vreg_usb3_3;
-
 static int optnav_enable(void)
 {
 	int rc;
@@ -2789,80 +2733,24 @@
 	 * Enable the VREGs L8(gp7), L10(gp4), L12(gp9), L6(usb)
 	 * for I2C communication with keyboard.
 	 */
-	vreg_gp7 = vreg_get(NULL, "gp7");
-	rc = vreg_set_level(vreg_gp7, 1800);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp7;
-	}
 
-	rc = vreg_enable(vreg_gp7);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp7;
-	}
+	rc = regulator_bulk_enable(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
 
-	vreg_gp4 = vreg_get(NULL, "gp4");
-	rc = vreg_set_level(vreg_gp4, 2600);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp4;
-	}
-
-	rc = vreg_enable(vreg_gp4);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp4;
-	}
-
-	vreg_gp9 = vreg_get(NULL, "gp9");
-	rc = vreg_set_level(vreg_gp9, 1800);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_gp9;
-	}
-
-	rc = vreg_enable(vreg_gp9);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_gp9;
-	}
-
-	vreg_usb3_3 = vreg_get(NULL, "usb");
-	rc = vreg_set_level(vreg_usb3_3, 3300);
-	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_3_3;
-	}
-
-	rc = vreg_enable(vreg_usb3_3);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_3_3;
-	}
+	if (rc)
+		return rc;
 
 	/* Enable the chip select GPIO */
 	gpio_set_value(OPTNAV_CHIP_SELECT, 1);
 	gpio_set_value(OPTNAV_CHIP_SELECT, 0);
 
 	return 0;
-
-fail_vreg_3_3:
-	vreg_disable(vreg_gp9);
-fail_vreg_gp9:
-	vreg_disable(vreg_gp4);
-fail_vreg_gp4:
-	vreg_disable(vreg_gp7);
-fail_vreg_gp7:
-	return rc;
 }
 
 static void optnav_disable(void)
 {
-	vreg_disable(vreg_usb3_3);
-	vreg_disable(vreg_gp9);
-	vreg_disable(vreg_gp4);
-	vreg_disable(vreg_gp7);
+	regulator_bulk_disable(ARRAY_SIZE(optnav_regulators),
+			optnav_regulators);
 
 	gpio_set_value(OPTNAV_CHIP_SELECT, 1);
 }
@@ -2907,74 +2795,61 @@
 };
 
 #ifdef CONFIG_BOSCH_BMA150
-static struct vreg *vreg_gp6;
-static int sensors_ldo_enable(void)
+
+static struct regulator_bulk_data sensors_ldo[] = {
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+};
+
+static int __init sensors_ldo_init(void)
 {
 	int rc;
 
-	/*
-	 * Enable the VREGs L8(gp7), L15(gp6)
-	 * for I2C communication with sensors.
-	 */
-	pr_info("sensors_ldo_enable called!!\n");
-	vreg_gp7 = vreg_get(NULL, "gp7");
-	if (IS_ERR(vreg_gp7)) {
-		pr_err("%s: vreg_get gp7 failed\n", __func__);
-		rc = PTR_ERR(vreg_gp7);
-		goto fail_gp7_get;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(sensors_ldo), sensors_ldo);
 
-	rc = vreg_set_level(vreg_gp7, 1800);
 	if (rc) {
-		pr_err("%s: vreg_set_level gp7 failed\n", __func__);
-		goto fail_gp7_level;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_gp7);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
 	if (rc) {
-		pr_err("%s: vreg_enable gp7 failed\n", __func__);
-		goto fail_gp7_level;
-	}
-
-	vreg_gp6 = vreg_get(NULL, "gp6");
-	if (IS_ERR(vreg_gp6)) {
-		pr_err("%s: vreg_get gp6 failed\n", __func__);
-		rc = PTR_ERR(vreg_gp6);
-		goto fail_gp6_get;
-	}
-
-	rc = vreg_set_level(vreg_gp6, 3050);
-	if (rc) {
-		pr_err("%s: vreg_set_level gp6 failed\n", __func__);
-		goto fail_gp6_level;
-	}
-
-	rc = vreg_enable(vreg_gp6);
-	if (rc) {
-		pr_err("%s: vreg_enable gp6 failed\n", __func__);
-		goto fail_gp6_level;
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	return 0;
 
-fail_gp6_level:
-	vreg_put(vreg_gp6);
-fail_gp6_get:
-	vreg_disable(vreg_gp7);
-fail_gp7_level:
-	vreg_put(vreg_gp7);
-fail_gp7_get:
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+out:
 	return rc;
 }
 
+static int sensors_ldo_set(int on)
+{
+	int rc = on ?
+		regulator_bulk_enable(ARRAY_SIZE(sensors_ldo), sensors_ldo) :
+		regulator_bulk_disable(ARRAY_SIZE(sensors_ldo), sensors_ldo);
+
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, on ? "en" : "dis", rc);
+
+	return rc;
+}
+
+static int sensors_ldo_enable(void)
+{
+	return sensors_ldo_set(1);
+}
+
 static void sensors_ldo_disable(void)
 {
-	pr_info("sensors_ldo_disable called!!\n");
-	vreg_disable(vreg_gp6);
-	vreg_put(vreg_gp6);
-	vreg_disable(vreg_gp7);
-	vreg_put(vreg_gp7);
+	sensors_ldo_set(0);
 }
+
 static struct bma150_platform_data bma150_data = {
 	.power_on = sensors_ldo_enable,
 	.power_off = sensors_ldo_disable,
@@ -3262,27 +3137,27 @@
 #endif
 
 #ifdef CONFIG_USB_MSM_OTG_72K
-static struct vreg *vreg_3p3;
+static struct regulator *vreg_3p3;
 static int msm_hsusb_ldo_init(int init)
 {
 	uint32_t version = 0;
-	int def_vol = 3400;
+	int def_vol = 3400000;
 
 	version = socinfo_get_version();
 
 	if (SOCINFO_VERSION_MAJOR(version) >= 2 &&
 			SOCINFO_VERSION_MINOR(version) >= 1) {
-		def_vol = 3075;
+		def_vol = 3075000;
 		pr_debug("%s: default voltage:%d\n", __func__, def_vol);
 	}
 
 	if (init) {
-		vreg_3p3 = vreg_get(NULL, "usb");
+		vreg_3p3 = regulator_get(NULL, "usb");
 		if (IS_ERR(vreg_3p3))
 			return PTR_ERR(vreg_3p3);
-		vreg_set_level(vreg_3p3, def_vol);
+		regulator_set_voltage(vreg_3p3, def_vol, def_vol);
 	} else
-		vreg_put(vreg_3p3);
+		regulator_put(vreg_3p3);
 
 	return 0;
 }
@@ -3300,14 +3175,14 @@
 	ldo_status = enable;
 
 	if (enable)
-		return vreg_enable(vreg_3p3);
-
-	return vreg_disable(vreg_3p3);
+		return regulator_enable(vreg_3p3);
+	else
+		return regulator_disable(vreg_3p3);
 }
 
 static int msm_hsusb_ldo_set_voltage(int mV)
 {
-	static int cur_voltage = 3400;
+	static int cur_voltage;
 
 	if (!vreg_3p3 || IS_ERR(vreg_3p3))
 		return -ENODEV;
@@ -3319,7 +3194,7 @@
 
 	pr_debug("%s: (%d)\n", __func__, mV);
 
-	return vreg_set_level(vreg_3p3, mV);
+	return regulator_set_voltage(vreg_3p3, mV*1000, mV*1000);
 }
 #endif
 
@@ -3500,35 +3375,163 @@
 	GPIO_CFG(37, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA);
 #endif
 
-static int gpio_set(const char *label, const char *name, int level, int on)
+static struct regulator_bulk_data hdmi_core_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static struct regulator_bulk_data hdmi_comm_regs[] = {
+	{ .supply = "ldo8",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo10", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static struct regulator_bulk_data hdmi_cec_regs[] = {
+	{ .supply = "ldo17", .min_uV = 2600000, .max_uV = 2600000 },
+};
+
+static int __init hdmi_init_regs(void)
 {
-	struct vreg *vreg = vreg_get(NULL, label);
 	int rc;
 
-	if (IS_ERR(vreg)) {
-		rc = PTR_ERR(vreg);
-		pr_err("%s: vreg %s get failed (%d)\n",
-			__func__, name, rc);
-		return rc;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_core_regs),
+			hdmi_core_regs);
 
-	rc = vreg_set_level(vreg, level);
 	if (rc) {
-		pr_err("%s: vreg %s set level failed (%d)\n",
-			__func__, name, rc);
-		return rc;
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "core", rc);
+		goto out;
 	}
 
-	if (on)
-		rc = vreg_enable(vreg);
-	else
-		rc = vreg_disable(vreg);
-	if (rc)
-		pr_err("%s: vreg %s enable failed (%d)\n",
-			__func__, name, rc);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_core_regs),
+			hdmi_core_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "core", rc);
+		goto free_core;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_comm_regs),
+			hdmi_comm_regs);
+
+	if (rc) {
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "comm", rc);
+		goto free_core;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_comm_regs),
+			hdmi_comm_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "comm", rc);
+		goto free_comm;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(hdmi_cec_regs),
+			hdmi_cec_regs);
+
+	if (rc) {
+		pr_err("%s: could not get %s regulators: %d\n",
+				__func__, "cec", rc);
+		goto free_comm;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(hdmi_cec_regs),
+			hdmi_cec_regs);
+
+	if (rc) {
+		pr_err("%s: could not set %s voltages: %d\n",
+				__func__, "cec", rc);
+		goto free_cec;
+	}
+
+	return 0;
+
+free_cec:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_cec_regs), hdmi_cec_regs);
+free_comm:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_comm_regs), hdmi_comm_regs);
+free_core:
+	regulator_bulk_free(ARRAY_SIZE(hdmi_core_regs), hdmi_core_regs);
+out:
 	return rc;
 }
 
+static int hdmi_init_irq(void)
+{
+	int rc = msm_gpios_enable(dtv_panel_irq_gpios,
+			ARRAY_SIZE(dtv_panel_irq_gpios));
+	if (rc < 0) {
+		pr_err("%s: gpio enable failed: %d\n", __func__, rc);
+		return rc;
+	}
+	pr_info("%s\n", __func__);
+
+	return 0;
+}
+
+static int hdmi_enable_5v(int on)
+{
+	int pmic_gpio_hdmi_5v_en ;
+
+	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
+						machine_is_msm7x30_fluid())
+		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
+	else
+		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
+
+	pr_info("%s: %d\n", __func__, on);
+	if (on) {
+		int rc;
+		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
+			"hdmi_5V_en");
+		if (rc) {
+			pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
+				__func__);
+			return rc;
+		}
+		gpio_set_value_cansleep(
+			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
+	} else {
+		gpio_set_value_cansleep(
+			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
+		gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
+	}
+	return 0;
+}
+
+static int hdmi_comm_power(int on, int show)
+{
+	if (show)
+		pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
+	return on ?
+		regulator_bulk_enable(ARRAY_SIZE(hdmi_comm_regs),
+				hdmi_comm_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_comm_regs),
+				hdmi_comm_regs);
+}
+
+static int hdmi_core_power(int on, int show)
+{
+	if (show)
+		pr_info("%s: %d <LDO8>\n", __func__, on);
+	return on ?
+		regulator_bulk_enable(ARRAY_SIZE(hdmi_core_regs),
+				hdmi_core_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_core_regs),
+				hdmi_core_regs);
+}
+
+static int hdmi_cec_power(int on)
+{
+	pr_info("%s: %d <LDO17>\n", __func__, on);
+	return on ? regulator_bulk_enable(ARRAY_SIZE(hdmi_cec_regs),
+				hdmi_cec_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(hdmi_cec_regs),
+				hdmi_cec_regs);
+}
+
 #if defined(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) || defined(CONFIG_BOSCH_BMA150)
 /* there is an i2c address conflict between adv7520 and bma150 sensor after
  * power up on fluid. As a solution, the default address of adv7520's packet
@@ -3541,7 +3544,6 @@
 	struct i2c_msg msgs[3];
 	int res;
 	int rc = -EINVAL;
-	struct vreg *vreg_ldo8;
 	struct i2c_adapter *adapter;
 
 	if (machine_is_msm7x30_fluid()) {
@@ -3552,24 +3554,13 @@
 		}
 
 		/* turn on LDO8 */
-		vreg_ldo8 = vreg_get(NULL, "gp7");
-		if (!vreg_ldo8) {
-			pr_err("%s: VREG L8 get failed\n", __func__);
+		rc = hdmi_core_power(1, 0);
+		if (rc) {
+			pr_err("%s: could not enable hdmi core regs: %d",
+					__func__, rc);
 			goto adapter_put;
 		}
 
-		rc = vreg_set_level(vreg_ldo8, 1800);
-		if (rc) {
-			pr_err("%s: VREG L8 set failed\n", __func__);
-			goto ldo8_put;
-		}
-
-		rc = vreg_enable(vreg_ldo8);
-		if (rc) {
-			pr_err("%s: VREG L8 enable failed\n", __func__);
-			goto ldo8_put;
-		}
-
 		/* change packet memory address to 0x74 */
 		wBuff[0] = 0x45;
 		wBuff[1] = 0x74;
@@ -3627,9 +3618,7 @@
 	return 0;
 
 ldo8_disable:
-	vreg_disable(vreg_ldo8);
-ldo8_put:
-	vreg_put(vreg_ldo8);
+	hdmi_core_power(0, 0);
 adapter_put:
 	i2c_put_adapter(adapter);
 	return rc;
@@ -3637,77 +3626,6 @@
 fs_initcall_sync(fluid_i2c_address_fixup);
 #endif
 
-static int hdmi_comm_power(int on, int show)
-{
-	int rc = gpio_set("gp7", "LDO8", 1800, on);
-	if (rc) {
-		pr_warning("hdmi_comm_power: LDO8 gpio failed: rc=%d\n", rc);
-		return rc;
-	}
-	rc = gpio_set("gp4", "LDO10", 2600, on);
-	if (rc)
-		pr_warning("hdmi_comm_power: LDO10 gpio failed: rc=%d\n", rc);
-	if (show)
-		pr_info("%s: i2c comm: %d <LDO8+LDO10>\n", __func__, on);
-	return rc;
-}
-
-static int hdmi_init_irq(void)
-{
-	int rc = msm_gpios_enable(dtv_panel_irq_gpios,
-			ARRAY_SIZE(dtv_panel_irq_gpios));
-	if (rc < 0) {
-		pr_err("%s: gpio enable failed: %d\n", __func__, rc);
-		return rc;
-	}
-	pr_info("%s\n", __func__);
-
-	return 0;
-}
-
-static int hdmi_enable_5v(int on)
-{
-	int pmic_gpio_hdmi_5v_en ;
-
-	if (machine_is_msm8x55_svlte_surf() || machine_is_msm8x55_svlte_ffa() ||
-						machine_is_msm7x30_fluid())
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V2 ;
-	else
-		pmic_gpio_hdmi_5v_en = PMIC_GPIO_HDMI_5V_EN_V3 ;
-
-	pr_info("%s: %d\n", __func__, on);
-	if (on) {
-		int rc;
-		rc = gpio_request(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en),
-			"hdmi_5V_en");
-		if (rc) {
-			pr_err("%s PMIC_GPIO_HDMI_5V_EN gpio_request failed\n",
-				__func__);
-			return rc;
-		}
-		gpio_set_value_cansleep(
-			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 1);
-	} else {
-		gpio_set_value_cansleep(
-			PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en), 0);
-		gpio_free(PM8058_GPIO_PM_TO_SYS(pmic_gpio_hdmi_5v_en));
-	}
-	return 0;
-}
-
-static int hdmi_core_power(int on, int show)
-{
-	if (show)
-		pr_info("%s: %d <LDO8>\n", __func__, on);
-	return gpio_set("gp7", "LDO8", 1800, on);
-}
-
-static int hdmi_cec_power(int on)
-{
-	pr_info("%s: %d <LDO17>\n", __func__, on);
-	return gpio_set("gp11", "LDO17", 2600, on);
-}
-
 static bool hdmi_check_hdcp_hw_support(void)
 {
 	if (machine_is_msm7x30_fluid())
@@ -4024,18 +3942,86 @@
 	},
 };
 
+static struct regulator *mddi_ldo20;
+static struct regulator *mddi_ldo12;
+static struct regulator *mddi_ldo16;
+static struct regulator *mddi_ldo6;
+static struct regulator *mddi_lcd;
+
+static int display_common_init(void)
+{
+	struct regulator_bulk_data regs[5] = {
+		{ .supply = "ldo20", /* voltage set in display_common_power */},
+		{ .supply = "ldo12", .min_uV = 1800000, .max_uV = 1800000 },
+		{ .supply = "ldo6",  .min_uV = 3075000, .max_uV = 3400000 },
+		{ .supply = "ldo16", .min_uV = 2600000, .max_uV = 2600000 },
+		{ .supply = NULL,    /* mddi_lcd, initialized below */ },
+	};
+
+	int rc = 0;
+
+	if (machine_is_msm7x30_fluid()) {
+		/* lcd: LDO8 @1.8V */
+		regs[4].supply = "ldo8";
+		regs[4].min_uV = 1800000;
+		regs[4].max_uV = 1800000;
+	} else {
+		/* lcd: LDO15 @3.1V */
+		regs[4].supply = "ldo15";
+		regs[4].min_uV = 3100000;
+		regs[4].max_uV = 3100000;
+	}
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+	if (rc) {
+		pr_err("%s: regulator_bulk_get failed: %d\n",
+				__func__, rc);
+		goto bail;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+	if (rc) {
+		pr_err("%s: regulator_bulk_set_voltage failed: %d\n",
+				__func__, rc);
+		goto put_regs;
+	}
+
+	mddi_ldo20 = regs[0].consumer;
+	mddi_ldo12 = regs[1].consumer;
+	mddi_ldo6  = regs[2].consumer;
+	mddi_ldo16 = regs[3].consumer;
+	mddi_lcd   = regs[4].consumer;
+
+	return rc;
+
+put_regs:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+	return rc;
+}
+
 static int display_common_power(int on)
 {
 	int rc = 0, flag_on = !!on;
 	static int display_common_power_save_on;
-	struct vreg *vreg_ldo12, *vreg_ldo15 = NULL, *vreg_ldo6;
-	struct vreg *vreg_ldo20, *vreg_ldo16, *vreg_ldo8 = NULL;
+	static bool display_regs_initialized;
 
 	if (display_common_power_save_on == flag_on)
 		return 0;
 
 	display_common_power_save_on = flag_on;
 
+	if (unlikely(!display_regs_initialized)) {
+		rc = display_common_init();
+		if (rc) {
+			pr_err("%s: regulator init failed: %d\n",
+					__func__, rc);
+			return rc;
+		}
+		display_regs_initialized = true;
+	}
+
+
 	if (on) {
 		/* reset Toshiba WeGA chip -- toggle reset pin -- gpio_180 */
 		rc = gpio_tlmm_config(wega_reset_gpio, GPIO_CFG_ENABLE);
@@ -4075,172 +4061,57 @@
 		}
 	}
 
-	/* Toshiba WeGA power -- has 3 power source */
-	/* 1.5V -- LDO20*/
-	vreg_ldo20 = vreg_get(NULL, "gp13");
-
-	if (IS_ERR(vreg_ldo20)) {
-		rc = PTR_ERR(vreg_ldo20);
-		pr_err("%s: gp13 vreg get failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	/* 1.8V -- LDO12 */
-	vreg_ldo12 = vreg_get(NULL, "gp9");
-
-	if (IS_ERR(vreg_ldo12)) {
-		rc = PTR_ERR(vreg_ldo12);
-		pr_err("%s: gp9 vreg get failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	/* 2.6V -- LDO16 */
-	vreg_ldo16 = vreg_get(NULL, "gp10");
-
-	if (IS_ERR(vreg_ldo16)) {
-		rc = PTR_ERR(vreg_ldo16);
-		pr_err("%s: gp10 vreg get failed (%d)\n",
-			   __func__, rc);
-		return rc;
-	}
-
-	/* 3.075V -- LDO6 */
-	vreg_ldo6 = vreg_get(NULL, "usb");
-
-	if (IS_ERR(vreg_ldo6)) {
-		rc = PTR_ERR(vreg_ldo6);
-		pr_err("%s: usb vreg get failed (%d)\n",
-			   __func__, rc);
-		return rc;
-	}
-
-	if (machine_is_msm7x30_fluid()) {
-		/* 1.8V -- LDO8 */
-		vreg_ldo8 = vreg_get(NULL, "gp7");
-
-		if (IS_ERR(vreg_ldo8)) {
-			rc = PTR_ERR(vreg_ldo8);
-			pr_err("%s: gp7 vreg get failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	} else {
-		/* lcd panel power */
-		/* 3.1V -- LDO15 */
-		vreg_ldo15 = vreg_get(NULL, "gp6");
-
-		if (IS_ERR(vreg_ldo15)) {
-			rc = PTR_ERR(vreg_ldo15);
-			pr_err("%s: gp6 vreg get failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
-	}
-
-	/* For QuickLogic chip, LDO20 requires 1.8V */
-	/* Toshiba chip requires 1.5V, but can tolerate 1.8V since max is 3V */
 	if (quickvx_mddi_client)
-		rc = vreg_set_level(vreg_ldo20, 1800);
+		rc = regulator_set_voltage(mddi_ldo20, 1800000, 1800000);
 	else
-		rc = vreg_set_level(vreg_ldo20, 1500);
+		rc = regulator_set_voltage(mddi_ldo20, 1500000, 1500000);
+
 	if (rc) {
-		pr_err("%s: vreg LDO20 set level failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	rc = vreg_set_level(vreg_ldo12, 1800);
-	if (rc) {
-		pr_err("%s: vreg LDO12 set level failed (%d)\n",
-		       __func__, rc);
-		return rc;
-	}
-
-	if (other_mddi_client) {
-		rc = vreg_set_level(vreg_ldo16, 2600);
-		if (rc) {
-			pr_err("%s: vreg LDO16 set level failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-	}
-
-	if (quickvx_mddi_client) {
-		rc = vreg_set_level(vreg_ldo6, 3075);
-		if (rc) {
-			pr_err("%s: vreg LDO6 set level failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-	}
-
-	if (machine_is_msm7x30_fluid()) {
-		rc = vreg_set_level(vreg_ldo8, 1800);
-		if (rc) {
-			pr_err("%s: vreg LDO8 set level failed (%d)\n",
+		pr_err("%s: could not set voltage for ldo20: %d\n",
 				__func__, rc);
-			return rc;
-		}
-	} else {
-		rc = vreg_set_level(vreg_ldo15, 3100);
-		if (rc) {
-			pr_err("%s: vreg LDO15 set level failed (%d)\n",
-				__func__, rc);
-			return rc;
-		}
+		return rc;
 	}
 
 	if (on) {
-		rc = vreg_enable(vreg_ldo20);
+		rc = regulator_enable(mddi_ldo20);
 		if (rc) {
-			pr_err("%s: LDO20 vreg enable failed (%d)\n",
+			pr_err("%s: LDO20 regulator enable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
-		rc = vreg_enable(vreg_ldo12);
+		rc = regulator_enable(mddi_ldo12);
 		if (rc) {
-			pr_err("%s: LDO12 vreg enable failed (%d)\n",
+			pr_err("%s: LDO12 regulator enable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
 		if (other_mddi_client) {
-			rc = vreg_enable(vreg_ldo16);
+			rc = regulator_enable(mddi_ldo16);
 			if (rc) {
-				pr_err("%s: LDO16 vreg enable failed (%d)\n",
+				pr_err("%s: LDO16 regulator enable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
 		}
 
-		if (quickvx_mddi_client && quickvx_ldo_enabled) {
+		if (quickvx_ldo_enabled) {
 			/* Disable LDO6 during display ON */
-			rc = vreg_disable(vreg_ldo6);
+			rc = regulator_disable(mddi_ldo6);
 			if (rc) {
-				pr_err("%s: LDO6 vreg disable failed (%d)\n",
+				pr_err("%s: LDO6 regulator disable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
 			quickvx_ldo_enabled = 0;
 		}
 
-		if (machine_is_msm7x30_fluid()) {
-			rc = vreg_enable(vreg_ldo8);
-			if (rc) {
-				pr_err("%s: LDO8 vreg enable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
-		} else {
-			rc = vreg_enable(vreg_ldo15);
-			if (rc) {
-				pr_err("%s: LDO15 vreg enable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
+		rc = regulator_enable(mddi_lcd);
+		if (rc) {
+			pr_err("%s: LCD regulator enable failed (%d)\n",
+				__func__, rc);
+			return rc;
 		}
 
 		mdelay(5);		/* ensure power is stable */
@@ -4279,18 +4150,18 @@
 		}
 
 	} else {
-		rc = vreg_disable(vreg_ldo20);
+		rc = regulator_disable(mddi_ldo20);
 		if (rc) {
-			pr_err("%s: LDO20 vreg disable failed (%d)\n",
+			pr_err("%s: LDO20 regulator disable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
 
 
 		if (other_mddi_client) {
-			rc = vreg_disable(vreg_ldo16);
+			rc = regulator_disable(mddi_ldo16);
 			if (rc) {
-				pr_err("%s: LDO16 vreg disable failed (%d)\n",
+				pr_err("%s: LDO16 regulator disable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
@@ -4299,9 +4170,9 @@
 		if (quickvx_mddi_client && !quickvx_ldo_enabled) {
 			/* Enable LDO6 during display OFF for
 			   Quicklogic chip to sleep with data retention */
-			rc = vreg_enable(vreg_ldo6);
+			rc = regulator_enable(mddi_ldo6);
 			if (rc) {
-				pr_err("%s: LDO6 vreg enable failed (%d)\n",
+				pr_err("%s: LDO6 regulator enable failed (%d)\n",
 					   __func__, rc);
 				return rc;
 			}
@@ -4316,27 +4187,18 @@
 				PMIC_GPIO_QUICKVX_CLK), 0);
 		}
 
-		if (machine_is_msm7x30_fluid()) {
-			rc = vreg_disable(vreg_ldo8);
-			if (rc) {
-				pr_err("%s: LDO8 vreg disable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
-		} else {
-			rc = vreg_disable(vreg_ldo15);
-			if (rc) {
-				pr_err("%s: LDO15 vreg disable failed (%d)\n",
-					__func__, rc);
-				return rc;
-			}
+		rc = regulator_disable(mddi_lcd);
+		if (rc) {
+			pr_err("%s: LCD regulator disable failed (%d)\n",
+				__func__, rc);
+			return rc;
 		}
 
 		mdelay(5);	/* ensure power is stable */
 
-		rc = vreg_disable(vreg_ldo12);
+		rc = regulator_disable(mddi_ldo12);
 		if (rc) {
-			pr_err("%s: LDO12 vreg disable failed (%d)\n",
+			pr_err("%s: LDO12 regulator disable failed (%d)\n",
 			       __func__, rc);
 			return rc;
 		}
@@ -4365,51 +4227,19 @@
 
 static int msm_fb_mddi_client_power(u32 client_id)
 {
-	struct vreg *vreg_ldo20, *vreg_ldo16;
-	int rc;
-
 	printk(KERN_NOTICE "\n client_id = 0x%x", client_id);
 	/* Check if it is Quicklogic client */
 	if (client_id == 0xc5835800) {
 		printk(KERN_NOTICE "\n Quicklogic MDDI client");
 		other_mddi_client = 0;
-		vreg_ldo16 = vreg_get(NULL, "gp10");
-
-		if (IS_ERR(vreg_ldo16)) {
-			rc = PTR_ERR(vreg_ldo16);
-			pr_err("%s: gp10 vreg get failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-
-		rc = vreg_disable(vreg_ldo16);
-		if (rc) {
-			pr_err("%s: LDO16 vreg enable failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
 	} else {
 		printk(KERN_NOTICE "\n Non-Quicklogic MDDI client");
 		quickvx_mddi_client = 0;
 		gpio_set_value(97, 0);
 		gpio_set_value_cansleep(PM8058_GPIO_PM_TO_SYS(
 			PMIC_GPIO_QUICKVX_CLK), 0);
-
-		vreg_ldo20 = vreg_get(NULL, "gp13");
-
-		if (IS_ERR(vreg_ldo20)) {
-			rc = PTR_ERR(vreg_ldo20);
-			pr_err("%s: gp13 vreg get failed (%d)\n",
-				   __func__, rc);
-			return rc;
-		}
-		rc = vreg_set_level(vreg_ldo20, 1500);
-		if (rc) {
-			pr_err("%s: vreg LDO20 set level failed (%d)\n",
-			       __func__, rc);
-			return rc;
-		}
 	}
+
 	return 0;
 }
 
@@ -4574,13 +4404,18 @@
 static int lcdc_panel_power(int on)
 {
 	int flag_on = !!on;
-	static int lcdc_power_save_on;
+	static int lcdc_power_save_on, lcdc_power_initialized;
 
 	if (lcdc_power_save_on == flag_on)
 		return 0;
 
 	lcdc_power_save_on = flag_on;
-	quickvx_mddi_client = 0;
+
+	if (unlikely(!lcdc_power_initialized)) {
+		quickvx_mddi_client = 0;
+		display_common_init();
+		lcdc_power_initialized = 1;
+	}
 
 	if (machine_is_msm7x30_fluid())
 		return lcdc_sharp_panel_power(on);
@@ -4592,47 +4427,64 @@
 	.lcdc_power_save   = lcdc_panel_power,
 };
 
+static struct regulator *atv_s4, *atv_ldo9;
+
+static int __init atv_dac_power_init(void)
+{
+	int rc;
+	struct regulator_bulk_data regs[] = {
+		{ .supply = "smps4", .min_uV = 2200000, .max_uV = 2200000 },
+		{ .supply = "ldo9",  .min_uV = 2050000, .max_uV = 2050000 },
+	};
+
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto bail;
+	}
+
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
+	}
+
+	atv_s4   = regs[0].consumer;
+	atv_ldo9 = regs[1].consumer;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+bail:
+	return rc;
+}
+
 static int atv_dac_power(int on)
 {
 	int rc = 0;
-	struct vreg *vreg_s4, *vreg_ldo9;
-
-	vreg_s4 = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_s4)) {
-		rc = PTR_ERR(vreg_s4);
-		pr_err("%s: s4 vreg get failed (%d)\n",
-			__func__, rc);
-		return -1;
-	}
-	vreg_ldo9 = vreg_get(NULL, "gp1");
-	if (IS_ERR(vreg_ldo9)) {
-		rc = PTR_ERR(vreg_ldo9);
-		pr_err("%s: ldo9 vreg get failed (%d)\n",
-			__func__, rc);
-		return rc;
-	}
 
 	if (on) {
-		rc = vreg_enable(vreg_s4);
+		rc = regulator_enable(atv_s4);
 		if (rc) {
 			pr_err("%s: s4 vreg enable failed (%d)\n",
 				__func__, rc);
 			return rc;
 		}
-		rc = vreg_enable(vreg_ldo9);
+		rc = regulator_enable(atv_ldo9);
 		if (rc) {
 			pr_err("%s: ldo9 vreg enable failed (%d)\n",
 				__func__, rc);
 			return rc;
 		}
 	} else {
-		rc = vreg_disable(vreg_ldo9);
+		rc = regulator_disable(atv_ldo9);
 		if (rc) {
 			pr_err("%s: ldo9 vreg disable failed (%d)\n",
 				   __func__, rc);
 			return rc;
 		}
-		rc = vreg_disable(vreg_s4);
+		rc = regulator_disable(atv_s4);
 		if (rc) {
 			pr_err("%s: s4 vreg disable failed (%d)\n",
 				   __func__, rc);
@@ -4707,24 +4559,31 @@
 		"UART1DM_Tx" }
 };
 
-static const char *vregs_bt_marimba_name[] = {
-	"s3",
-	"s2",
-	"gp16",
-	"wlan"
-};
-static struct vreg *vregs_bt_marimba[ARRAY_SIZE(vregs_bt_marimba_name)];
-
-static const char *vregs_bt_bahama_name[] = {
-	"s3",
-	"usb2",
-	"s2",
-	"wlan"
-};
-static struct vreg *vregs_bt_bahama[ARRAY_SIZE(vregs_bt_bahama_name)];
-
 static u8 bahama_version;
 
+static struct regulator_bulk_data regs_bt_marimba[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+	{ .supply = "ldo24", .min_uV = 1200000, .max_uV = 1200000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v1[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "smps2", .min_uV = 1300000, .max_uV = 1300000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data regs_bt_bahama_v2[] = {
+	{ .supply = "smps3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "ldo13", .min_uV = 2900000, .max_uV = 2900000 },
+};
+
+static struct regulator_bulk_data *regs_bt;
+static int regs_bt_count;
+
 static int marimba_bt(int on)
 {
 	int rc;
@@ -4946,15 +4805,6 @@
 
 	on = on ? 1 : 0;
 
-	bahama_version = read_bahama_ver();
-
-	if (((int)bahama_version) < 0 ||
-		bahama_version == VER_UNSUPPORTED) {
-		dev_err(&msm_bt_power_device.dev,
-			"%s: i2c failure or unsupported version: %d\n",
-			__func__, bahama_version);
-		return -EIO;
-	}
 
 	if (bahama_version == VER_2_0) {
 		if (marimba_get_fm_status(&config))
@@ -4990,69 +4840,62 @@
 	else
 		marimba_set_bt_status(&config, false);
 
-	if (bahama_version == VER_2_0 && on) { /* variant of bahama v2 */
-		/* Disable s2 as bahama v2 uses internal LDO regulator */
-		for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
-			if (!strcmp(vregs_bt_bahama_name[i], "s2")) {
-				rc = vreg_disable(vregs_bt_bahama[i]);
-				if (rc < 0) {
-					printk(KERN_ERR
-						"%s: vreg %s disable "
-						"failed (%d)\n",
-						__func__,
-						vregs_bt_bahama_name[i], rc);
-					return -EIO;
-				}
-				rc = pmapp_vreg_level_vote("BTPW",
-								PMAPP_VREG_S2,
-								0);
-				if (rc < 0) {
-					printk(KERN_ERR "%s: vreg "
-						"level off failed (%d)\n",
-						__func__, rc);
-					return -EIO;
-				}
-				printk(KERN_INFO "%s: vreg disable & "
-					"level off successful (%d)\n",
-					__func__, rc);
-			}
-		}
-	}
-
 	return 0;
 }
 
-static int bluetooth_power_regulators(int on, int bahama_not_marimba)
+static int bluetooth_regs_init(int bahama_not_marimba)
 {
-	int i, rc;
-	const char **vregs_name;
-	struct vreg **vregs;
-	int vregs_size;
+	int rc = 0;
+	struct device *const dev = &msm_bt_power_device.dev;
 
 	if (bahama_not_marimba) {
-		vregs_name = vregs_bt_bahama_name;
-		vregs = vregs_bt_bahama;
-		vregs_size = ARRAY_SIZE(vregs_bt_bahama_name);
+		bahama_version = read_bahama_ver();
+
+		switch (bahama_version) {
+		case VER_1_0:
+			regs_bt = regs_bt_bahama_v1;
+			regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v1);
+			break;
+		case VER_2_0:
+			regs_bt = regs_bt_bahama_v2;
+			regs_bt_count = ARRAY_SIZE(regs_bt_bahama_v2);
+			break;
+		case VER_UNSUPPORTED:
+		default:
+			dev_err(dev,
+				"%s: i2c failure or unsupported version: %d\n",
+				__func__, bahama_version);
+			rc = -EIO;
+			goto out;
+		}
 	} else {
-		vregs_name = vregs_bt_marimba_name;
-		vregs = vregs_bt_marimba;
-		vregs_size = ARRAY_SIZE(vregs_bt_marimba_name);
+		regs_bt = regs_bt_marimba;
+		regs_bt_count = ARRAY_SIZE(regs_bt_marimba);
 	}
 
-	for (i = 0; i < vregs_size; i++) {
-		if (bahama_not_marimba && (bahama_version == VER_2_0) &&
-			!on && !strcmp(vregs_bt_bahama_name[i], "s2"))
-			continue;
-		rc = on ? vreg_enable(vregs[i]) :
-			  vreg_disable(vregs[i]);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_name[i],
-			       on ? "enable" : "disable", rc);
-			return -EIO;
-		}
+	rc = regulator_bulk_get(&msm_bt_power_device.dev,
+			regs_bt_count, regs_bt);
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
 	}
+
+	rc = regulator_bulk_set_voltage(regs_bt_count, regs_bt);
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
+	}
+
 	return 0;
+
+reg_free:
+	regulator_bulk_free(regs_bt_count, regs_bt);
+out:
+	regs_bt_count = 0;
+	regs_bt = NULL;
+	return rc;
 }
 
 static int bluetooth_power(int on)
@@ -5068,17 +4911,16 @@
 		return -ENODEV;
 	}
 
-	if (on) {
-		rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 1300);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg level on failed (%d)\n",
-				__func__, rc);
+	if (unlikely(regs_bt_count == 0)) {
+		rc = bluetooth_regs_init(bahama_not_marimba);
+		if (rc)
 			return rc;
-		}
+	}
 
-		rc = bluetooth_power_regulators(on, bahama_not_marimba);
-		if (rc < 0)
-			return -EIO;
+	if (on) {
+		rc = regulator_bulk_enable(regs_bt_count, regs_bt);
+		if (rc)
+			return rc;
 
 		rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_DO,
 					  PMAPP_CLOCK_VOTE_ON);
@@ -5135,18 +4977,10 @@
 		if (rc < 0)
 			return -EIO;
 
-		rc = bluetooth_power_regulators(on, bahama_not_marimba);
-		if (rc < 0)
-			return -EIO;
+		rc = regulator_bulk_disable(regs_bt_count, regs_bt);
+		if (rc)
+			return rc;
 
-		if (bahama_version == VER_1_0) {
-			rc = pmapp_vreg_level_vote(id, PMAPP_VREG_S2, 0);
-			if (rc < 0) {
-				printk(KERN_ERR "%s: vreg level off failed "
-				"(%d)\n", __func__, rc);
-				return -EIO;
-			}
-		}
 	}
 
 out:
@@ -5157,29 +4991,7 @@
 
 static void __init bt_power_init(void)
 {
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(vregs_bt_marimba_name); i++) {
-		vregs_bt_marimba[i] = vreg_get(NULL, vregs_bt_marimba_name[i]);
-		if (IS_ERR(vregs_bt_marimba[i])) {
-			printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
-			       __func__, vregs_bt_marimba_name[i],
-			       PTR_ERR(vregs_bt_marimba[i]));
-			return;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(vregs_bt_bahama_name); i++) {
-		vregs_bt_bahama[i] = vreg_get(NULL, vregs_bt_bahama_name[i]);
-		if (IS_ERR(vregs_bt_bahama[i])) {
-			printk(KERN_ERR "%s: vreg get %s failed (%ld)\n",
-			       __func__, vregs_bt_bahama_name[i],
-			       PTR_ERR(vregs_bt_bahama[i]));
-			return;
-		}
-	}
-
-    msm_bt_power_device.dev.platform_data = &bluetooth_power;
+	msm_bt_power_device.dev.platform_data = &bluetooth_power;
 }
 #else
 #define bt_power_init(x) do {} while (0)
@@ -5415,7 +5227,7 @@
 }
 /*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-static struct vreg *qup_vreg;
+static struct regulator *qup_vreg;
 #endif
 static void
 qup_i2c_gpio_config(int adap_id, int config_type)
@@ -5434,15 +5246,10 @@
 		printk(KERN_ERR "QUP GPIO enable failed: %d\n", rc);
 	/*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-	if (qup_vreg) {
-		int rc = vreg_set_level(qup_vreg, 1800);
+	if (!IS_ERR_OR_NULL(qup_vreg)) {
+		rc = regulator_enable(qup_vreg);
 		if (rc) {
-			pr_err("%s: vreg LVS1 set level failed (%d)\n",
-			__func__, rc);
-		}
-		rc = vreg_enable(qup_vreg);
-		if (rc) {
-			pr_err("%s: vreg_enable() = %d \n",
+			pr_err("%s: regulator_enable failed: %d\n",
 			__func__, rc);
 		}
 	}
@@ -5491,9 +5298,10 @@
 	qup_device_i2c.dev.platform_data = &qup_i2c_pdata;
 	/*This needs to be enabled only for OEMS*/
 #ifndef CONFIG_QUP_EXCLUSIVE_TO_CAMERA
-	qup_vreg = vreg_get(NULL, "lvsw1");
+	qup_vreg = regulator_get(&qup_device_i2c.dev, "lvsw1");
 	if (IS_ERR(qup_vreg)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
+		dev_err(&qup_device_i2c.dev,
+			"%s: regulator_get failed: %ld\n",
 			__func__, PTR_ERR(qup_vreg));
 	}
 #endif
@@ -5516,9 +5324,6 @@
 	{GPIO_CFG(115, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "ebi2_busy1"},
 };
 
-struct vreg *vreg_s3;
-struct vreg *vreg_mmc;
-
 #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\
 	|| defined(CONFIG_MMC_MSM_SDC2_SUPPORT)\
 	|| defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\
@@ -5615,12 +5420,7 @@
 	},
 };
 
-struct sdcc_vreg {
-	struct vreg *vreg_data;
-	unsigned level;
-};
-
-static struct sdcc_vreg sdcc_vreg_data[4];
+static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
 
 static unsigned long vreg_sts, gpio_sts;
 
@@ -5656,37 +5456,36 @@
 static uint32_t msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
 {
 	int rc = 0;
-	struct sdcc_vreg *curr;
+	struct regulator *curr = sdcc_vreg_data[dev_id - 1];
 	static int enabled_once[] = {0, 0, 0, 0};
 
-	curr = &sdcc_vreg_data[dev_id - 1];
-
-	if (!(test_bit(dev_id, &vreg_sts)^enable))
+	if (test_bit(dev_id, &vreg_sts) == enable)
 		return rc;
 
 	if (!enable || enabled_once[dev_id - 1])
 		return 0;
 
+	if (!curr)
+		return -ENODEV;
+
+	if (IS_ERR(curr))
+		return PTR_ERR(curr);
+
 	if (enable) {
 		set_bit(dev_id, &vreg_sts);
-		rc = vreg_set_level(curr->vreg_data, curr->level);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_set_level() = %d \n",
+
+		rc = regulator_enable(curr);
+		if (rc)
+			pr_err("%s: could not enable regulator: %d\n",
 					__func__, rc);
-		}
-		rc = vreg_enable(curr->vreg_data);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable() = %d \n",
-					__func__, rc);
-		}
 		enabled_once[dev_id - 1] = 1;
 	} else {
 		clear_bit(dev_id, &vreg_sts);
-		rc = vreg_disable(curr->vreg_data);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_disable() = %d \n",
+
+		rc = regulator_disable(curr);
+		if (rc)
+			pr_err("%s: could not disable regulator: %d\n",
 					__func__, rc);
-		}
 	}
 	return rc;
 }
@@ -5757,109 +5556,76 @@
 	return rc;
 }
 
-static int mbp_setup_rf_vregs(int state)
+static struct regulator_bulk_data mbp_regs_io[2];
+static struct regulator_bulk_data mbp_regs_rf[2];
+static struct regulator_bulk_data mbp_regs_adc[1];
+static struct regulator_bulk_data mbp_regs_core[1];
+
+static int mbp_init_regs(struct device *dev)
 {
-	struct vreg *vreg_rf = NULL;
-	struct vreg *vreg_rf_switch	= NULL;
+	struct regulator_bulk_data regs[] = {
+		/* Analog and I/O regs */
+		{ .supply = "gp4",  .min_uV = 2600000, .max_uV = 2600000 },
+		{ .supply = "s3",   .min_uV = 1800000, .max_uV = 1800000 },
+		/* RF regs */
+		{ .supply = "s2",   .min_uV = 1300000, .max_uV = 1300000 },
+		{ .supply = "rf",   .min_uV = 2600000, .max_uV = 2600000 },
+		/* ADC regs */
+		{ .supply = "s4",   .min_uV = 2200000, .max_uV = 2200000 },
+		/* Core regs */
+		{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+	};
+
+	struct regulator_bulk_data *regptr = regs;
 	int rc;
 
-	vreg_rf = vreg_get(NULL, "s2");
-	if (IS_ERR(vreg_rf)) {
-		pr_err("%s: s2 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_rf));
-		return -EFAULT;
-	}
-	vreg_rf_switch = vreg_get(NULL, "rf");
-	if (IS_ERR(vreg_rf_switch)) {
-		pr_err("%s: rf vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_rf_switch));
-		return -EFAULT;
+	rc = regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
+		goto out;
 	}
 
-	if (state) {
-		rc = vreg_set_level(vreg_rf, 1300);
-		if (rc) {
-			pr_err("%s: vreg s2 set level failed (%d)\n",
-					__func__, rc);
-			return rc;
-		}
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs), regs);
 
-		rc = vreg_enable(vreg_rf);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable(s2) = %d\n",
-					__func__, rc);
-		}
-
-		rc = vreg_set_level(vreg_rf_switch, 2600);
-		if (rc) {
-			pr_err("%s: vreg rf switch set level failed (%d)\n",
-					__func__, rc);
-			return rc;
-		}
-		rc = vreg_enable(vreg_rf_switch);
-		if (rc) {
-			printk(KERN_ERR "%s: vreg_enable(rf) = %d\n",
-					__func__, rc);
-		}
-	} else {
-		(void) vreg_disable(vreg_rf);
-		(void) vreg_disable(vreg_rf_switch);
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
+
+	memcpy(mbp_regs_io, regptr, sizeof(mbp_regs_io));
+	regptr += ARRAY_SIZE(mbp_regs_io);
+
+	memcpy(mbp_regs_rf, regptr, sizeof(mbp_regs_rf));
+	regptr += ARRAY_SIZE(mbp_regs_rf);
+
+	memcpy(mbp_regs_adc, regptr, sizeof(mbp_regs_adc));
+	regptr += ARRAY_SIZE(mbp_regs_adc);
+
+	memcpy(mbp_regs_core, regptr, sizeof(mbp_regs_core));
+
 	return 0;
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs), regs);
+out:
+	return rc;
+}
+
+static int mbp_setup_rf_vregs(int state)
+{
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_rf), mbp_regs_rf);
 }
 
 static int mbp_setup_vregs(int state)
 {
-	struct vreg *vreg_analog = NULL;
-	struct vreg *vreg_io = NULL;
-	int rc;
-
-	vreg_analog = vreg_get(NULL, "gp4");
-	if (IS_ERR(vreg_analog)) {
-		pr_err("%s: gp4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_analog));
-		return -EFAULT;
-	}
-	vreg_io = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_io)) {
-		pr_err("%s: s3 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_io));
-		return -EFAULT;
-	}
-	if (state) {
-		rc = vreg_set_level(vreg_analog, 2600);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_analog);
-		if (rc) {
-			pr_err("%s: analog vreg enable failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_set_level(vreg_io, 1800);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_io);
-		if (rc) {
-			pr_err("%s: io vreg enable failed (%d)",
-					__func__, rc);
-		}
-	} else {
-		rc = vreg_disable(vreg_analog);
-		if (rc) {
-			pr_err("%s: analog vreg disable failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_disable(vreg_io);
-		if (rc) {
-			pr_err("%s: io vreg disable failed (%d)",
-					__func__, rc);
-		}
-	}
-	return rc;
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_io), mbp_regs_io);
 }
 
 static int mbp_set_tcxo_en(int enable)
@@ -5875,16 +5641,6 @@
 			__func__, enable ? "" : "de-");
 		return -EIO;
 	}
-	if (!enable) {
-		vreg_analog = vreg_get(NULL, "gp4");
-		if (IS_ERR(vreg_analog)) {
-			pr_err("%s: gp4 vreg get failed (%ld)",
-					__func__, PTR_ERR(vreg_analog));
-			return -EFAULT;
-		}
-
-		(void) vreg_disable(vreg_analog);
-	}
 	return rc;
 }
 
@@ -5898,28 +5654,20 @@
 
 static int mbp_set_core_voltage_en(int enable)
 {
-	int rc;
-	struct vreg *vreg_core1p2 = NULL;
+	static bool is_enabled;
+	int rc = 0;
 
-	vreg_core1p2 = vreg_get(NULL, "gp16");
-	if (IS_ERR(vreg_core1p2)) {
-		pr_err("%s: gp16 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_core1p2));
-		return -EFAULT;
-	}
-	if (enable) {
-		rc = vreg_set_level(vreg_core1p2, 1200);
+	if (enable && !is_enabled) {
+		rc = regulator_bulk_enable(ARRAY_SIZE(mbp_regs_core),
+				mbp_regs_core);
 		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
+			pr_err("%s: could not enable regulators: %d\n",
 					__func__, rc);
+		} else {
+			is_enabled = true;
 		}
-		(void) vreg_enable(vreg_core1p2);
-
-		return 80;
-	} else {
-		gpio_set_value(85, 1);
-		return 0;
 	}
+
 	return rc;
 }
 
@@ -5950,34 +5698,9 @@
 
 static int mbp_setup_adc_vregs(int state)
 {
-	struct vreg *vreg_adc = NULL;
-	int rc;
-
-	vreg_adc = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_adc)) {
-		pr_err("%s: s4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_adc));
-		return -EFAULT;
-	}
-	if (state) {
-		rc = vreg_set_level(vreg_adc, 2200);
-		if (rc) {
-			pr_err("%s: vreg_set_level failed (%d)",
-					__func__, rc);
-		}
-		rc = vreg_enable(vreg_adc);
-		if (rc) {
-			pr_err("%s: enable vreg adc failed (%d)",
-					__func__, rc);
-		}
-	} else {
-		rc = vreg_disable(vreg_adc);
-		if (rc) {
-			pr_err("%s: disable vreg adc failed (%d)",
-					__func__, rc);
-		}
-	}
-	return rc;
+	return state ?
+		regulator_bulk_enable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc) :
+		regulator_bulk_disable(ARRAY_SIZE(mbp_regs_adc), mbp_regs_adc);
 }
 
 static int mbp_power_up(void)
@@ -6042,14 +5765,6 @@
 static int mbp_power_down(void)
 {
 	int rc;
-	struct vreg *vreg_adc = NULL;
-
-	vreg_adc = vreg_get(NULL, "s4");
-	if (IS_ERR(vreg_adc)) {
-		pr_err("%s: s4 vreg get failed (%ld)",
-				__func__, PTR_ERR(vreg_adc));
-		return -EFAULT;
-	}
 
 	mbp_set_reset(MBP_ON);
 	pr_debug("%s: mbp_set_reset(MBP_ON) done\n", __func__);
@@ -6079,13 +5794,16 @@
 		goto exit;
 	pr_debug("%s: mbp_set_core_voltage_en(MBP_OFF) done\n", __func__);
 
-	gpio_set_value(85, 1);
-
 	rc = mbp_set_tcxo_en(MBP_OFF);
 	if (rc)
 		goto exit;
 	pr_debug("%s: mbp_set_tcxo_en(MBP_OFF) done\n", __func__);
 
+	rc = mbp_setup_vregs(MBP_OFF);
+	if (rc)
+		goto exit;
+	pr_debug("%s: mbp_setup_vregs(MBP_OFF) done\n", __func__);
+
 	rc = mbp_config_gpios_pre_init(MBP_OFF);
 	if (rc)
 		goto exit;
@@ -6147,6 +5865,12 @@
 		goto out;
 	}
 	if (!mbp_power_init_done) {
+		rc = mbp_init_regs(dv);
+		if (rc) {
+			dev_err(dv, "%s: regulator init failed: %d\n",
+					__func__, rc);
+			goto out;
+		}
 		mbp_setup_power(dv, 1);
 		mbp_setup_power(dv, 0);
 		mbp_power_init_done = 1;
@@ -6285,18 +6009,32 @@
 #endif
 
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-static void msm_sdc1_lvlshft_enable(void)
+static int msm_sdc1_lvlshft_enable(void)
 {
+	static struct regulator *ldo5;
 	int rc;
 
 	/* Enable LDO5, an input to the FET that powers slot 1 */
-	rc = vreg_set_level(vreg_mmc, 2850);
-	if (rc)
-		printk(KERN_ERR "%s: vreg_set_level() = %d \n",	__func__, rc);
 
-	rc = vreg_enable(vreg_mmc);
-	if (rc)
-		printk(KERN_ERR "%s: vreg_enable() = %d \n", __func__, rc);
+	ldo5 = regulator_get(NULL, "ldo5");
+
+	if (IS_ERR(ldo5)) {
+		rc = PTR_ERR(ldo5);
+		pr_err("%s: could not get ldo5: %d\n", __func__, rc);
+		goto out;
+	}
+
+	rc = regulator_set_voltage(ldo5, 2850000, 2850000);
+	if (rc) {
+		pr_err("%s: could not set ldo5 voltage: %d\n", __func__, rc);
+		goto ldo5_free;
+	}
+
+	rc = regulator_enable(ldo5);
+	if (rc) {
+		pr_err("%s: could not enable ldo5: %d\n", __func__, rc);
+		goto ldo5_free;
+	}
 
 	/* Enable GPIO 35, to turn on the FET that powers slot 1 */
 	rc = msm_gpios_request_enable(sdc1_lvlshft_cfg_data,
@@ -6308,35 +6046,72 @@
 				1);
 	if (rc)
 		printk(KERN_ERR "%s: Failed to turn on GPIO 35\n", __func__);
+
+	return 0;
+
+ldo5_free:
+	regulator_put(ldo5);
+out:
+	ldo5 = NULL;
+	return rc;
 }
 #endif
 
+static int mmc_regulator_init(int sdcc_no, const char *supply, int uV)
+{
+	int rc;
+
+	BUG_ON(sdcc_no < 1 || sdcc_no > 4);
+
+	sdcc_no--;
+
+	sdcc_vreg_data[sdcc_no] = regulator_get(NULL, supply);
+
+	if (IS_ERR(sdcc_vreg_data[sdcc_no])) {
+		rc = PTR_ERR(sdcc_vreg_data[sdcc_no]);
+		pr_err("%s: could not get regulator \"%s\": %d\n",
+				__func__, supply, rc);
+		goto out;
+	}
+
+	rc = regulator_set_voltage(sdcc_vreg_data[sdcc_no], uV, uV);
+
+	if (rc) {
+		pr_err("%s: could not set voltage for \"%s\" to %d uV: %d\n",
+				__func__, supply, uV, rc);
+		goto reg_free;
+	}
+
+	return rc;
+
+reg_free:
+	regulator_put(sdcc_vreg_data[sdcc_no]);
+out:
+	sdcc_vreg_data[sdcc_no] = NULL;
+	return rc;
+}
+
 static void __init msm7x30_init_mmc(void)
 {
-	vreg_s3 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_s3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_s3));
-		return;
-	}
-
-	vreg_mmc = vreg_get(NULL, "mmc");
-	if (IS_ERR(vreg_mmc)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_mmc));
-		return;
-	}
-
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+	if (mmc_regulator_init(1, "s3", 1800000))
+		goto out1;
+
 	if (machine_is_msm7x30_fluid()) {
 		msm7x30_sdc1_data.ocr_mask =  MMC_VDD_27_28 | MMC_VDD_28_29;
-		msm_sdc1_lvlshft_enable();
+		if (msm_sdc1_lvlshft_enable()) {
+			pr_err("%s: could not enable level shift\n");
+			goto out1;
+		}
 	}
-	sdcc_vreg_data[0].vreg_data = vreg_s3;
-	sdcc_vreg_data[0].level = 1800;
+
 	msm_add_sdcc(1, &msm7x30_sdc1_data);
+out1:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
+	if (mmc_regulator_init(2, "s3", 1800000))
+		goto out2;
+
 	if (machine_is_msm8x55_svlte_surf())
 		msm7x30_sdc2_data.msmsdcc_fmax =  24576000;
 	if (machine_is_msm8x55_svlte_surf() ||
@@ -6344,19 +6119,22 @@
 		msm7x30_sdc2_data.sdiowakeup_irq = MSM_GPIO_TO_INT(68);
 		msm7x30_sdc2_data.is_sdio_al_client = 1;
 	}
-	sdcc_vreg_data[1].vreg_data = vreg_s3;
-	sdcc_vreg_data[1].level = 1800;
+
 	msm_add_sdcc(2, &msm7x30_sdc2_data);
+out2:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-	sdcc_vreg_data[2].vreg_data = vreg_s3;
-	sdcc_vreg_data[2].level = 1800;
+	if (mmc_regulator_init(3, "s3", 1800000))
+		goto out3;
+
 	msm_sdcc_setup_gpio(3, 1);
 	msm_add_sdcc(3, &msm7x30_sdc3_data);
+out3:
 #endif
 #ifdef CONFIG_MMC_MSM_SDC4_SUPPORT
-	sdcc_vreg_data[3].vreg_data = vreg_mmc;
-	sdcc_vreg_data[3].level = 2850;
+	if (mmc_regulator_init(4, "mmc", 2850000))
+		return;
+
 	msm_add_sdcc(4, &msm7x30_sdc4_data);
 #endif
 
@@ -6468,68 +6246,50 @@
 	"tsc2007_irq" },
 };
 
-static struct vreg *vreg_tsc_s3;
-static struct vreg *vreg_tsc_s2;
+static struct regulator_bulk_data tsc2007_regs[] = {
+	{ .supply = "s3", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "s2", .min_uV = 1300000, .max_uV = 1300000 },
+};
 
 static int tsc2007_init(void)
 {
 	int rc;
 
-	vreg_tsc_s3 = vreg_get(NULL, "s3");
-	if (IS_ERR(vreg_tsc_s3)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_tsc_s3));
-		return -ENODEV;
-	}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
-	rc = vreg_set_level(vreg_tsc_s3, 1800);
 	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_set_level;
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		goto out;
 	}
 
-	rc = vreg_enable(vreg_tsc_s3);
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
 	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_set_level;
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
-	vreg_tsc_s2 = vreg_get(NULL, "s2");
-	if (IS_ERR(vreg_tsc_s2)) {
-		printk(KERN_ERR "%s: vreg get failed (%ld)\n",
-		       __func__, PTR_ERR(vreg_tsc_s2));
-		goto fail_vreg_get;
-	}
+	rc = regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
-	rc = vreg_set_level(vreg_tsc_s2, 1300);
 	if (rc) {
-		pr_err("%s: vreg_set_level failed \n", __func__);
-		goto fail_vreg_s2_level;
-	}
-
-	rc = vreg_enable(vreg_tsc_s2);
-	if (rc) {
-		pr_err("%s: vreg_enable failed \n", __func__);
-		goto fail_vreg_s2_level;
+		pr_err("%s: could not enable regulators: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	rc = msm_gpios_request_enable(tsc2007_config_data,
 			ARRAY_SIZE(tsc2007_config_data));
 	if (rc) {
 		pr_err("%s: Unable to request gpios\n", __func__);
-		goto fail_gpio_req;
+		goto reg_disable;
 	}
 
 	return 0;
 
-fail_gpio_req:
-	vreg_disable(vreg_tsc_s2);
-fail_vreg_s2_level:
-	vreg_put(vreg_tsc_s2);
-fail_vreg_get:
-	vreg_disable(vreg_tsc_s3);
-fail_vreg_set_level:
-	vreg_put(vreg_tsc_s3);
+reg_disable:
+	regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+out:
 	return rc;
 }
 
@@ -6549,10 +6309,9 @@
 
 static void tsc2007_exit(void)
 {
-	vreg_disable(vreg_tsc_s3);
-	vreg_put(vreg_tsc_s3);
-	vreg_disable(vreg_tsc_s2);
-	vreg_put(vreg_tsc_s2);
+
+	regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+	regulator_bulk_free(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
 
 	msm_gpios_disable_free(tsc2007_config_data,
 		ARRAY_SIZE(tsc2007_config_data));
@@ -6562,35 +6321,20 @@
 {
 	int rc;
 
-	if (enable == false) {
-		rc = vreg_enable(vreg_tsc_s2);
-		if (rc) {
-			pr_err("%s: vreg_enable failed\n", __func__);
-			return rc;
-		}
-		rc = vreg_enable(vreg_tsc_s3);
-		if (rc) {
-			pr_err("%s: vreg_enable failed\n", __func__);
-			vreg_disable(vreg_tsc_s2);
-			return rc;
-		}
-		/* Voltage settling delay */
-		msleep(20);
-	} else {
-		rc = vreg_disable(vreg_tsc_s2);
-		if (rc) {
-			pr_err("%s: vreg_disable failed\n", __func__);
-			return rc;
-		}
-		rc = vreg_disable(vreg_tsc_s3);
-		if (rc) {
-			pr_err("%s: vreg_disable failed\n", __func__);
-			vreg_enable(vreg_tsc_s2);
-			return rc;
-		}
+	rc = (enable == false) ?
+		regulator_bulk_enable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs) :
+		regulator_bulk_disable(ARRAY_SIZE(tsc2007_regs), tsc2007_regs);
+
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, enable ? "dis" : "en", rc);
+		return rc;
 	}
 
-	return rc;
+	if (enable == false)
+		msleep(20);
+
+	return 0;
 }
 
 static struct tsc2007_platform_data tsc2007_ts_data = {
@@ -6617,36 +6361,23 @@
 };
 #endif
 
-static const char *vregs_isa1200_name[] = {
-	"gp7",
-	"gp10",
+static struct regulator_bulk_data regs_isa1200[] = {
+	{ .supply = "gp7",  .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp10", .min_uV = 2600000, .max_uV = 2600000 },
 };
 
-static const int vregs_isa1200_val[] = {
-	1800,
-	2600,
-};
-static struct vreg *vregs_isa1200[ARRAY_SIZE(vregs_isa1200_name)];
-
 static int isa1200_power(int vreg_on)
 {
-	int i, rc = 0;
+	int rc = 0;
 
-	for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
-		if (!vregs_isa1200[i]) {
-			pr_err("%s: vreg_get %s failed (%d)\n",
-				__func__, vregs_isa1200_name[i], rc);
-			goto vreg_fail;
-		}
+	rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
 
-		rc = vreg_on ? vreg_enable(vregs_isa1200[i]) :
-			  vreg_disable(vregs_isa1200[i]);
-		if (rc < 0) {
-			pr_err("%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_isa1200_name[i],
-			       vreg_on ? "enable" : "disable", rc);
-			goto vreg_fail;
-		}
+	if (rc) {
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_on ? "en" : "dis", rc);
+		goto out;
 	}
 
 	/* vote for DO buffer */
@@ -6661,33 +6392,34 @@
 	return 0;
 
 vreg_fail:
-	while (i)
-		vreg_disable(vregs_isa1200[--i]);
+	if (vreg_on)
+		regulator_bulk_disable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+	else
+		regulator_bulk_enable(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
 	return rc;
 }
 
 static int isa1200_dev_setup(bool enable)
 {
-	int i, rc;
+	int rc;
 
 	if (enable == true) {
-		for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++) {
-			vregs_isa1200[i] = vreg_get(NULL,
-						vregs_isa1200_name[i]);
-			if (IS_ERR(vregs_isa1200[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-					__func__, vregs_isa1200_name[i],
-					PTR_ERR(vregs_isa1200[i]));
-				rc = PTR_ERR(vregs_isa1200[i]);
-				goto vreg_get_fail;
-			}
-			rc = vreg_set_level(vregs_isa1200[i],
-					vregs_isa1200_val[i]);
-			if (rc) {
-				pr_err("%s: vreg_set_level() = %d\n",
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_isa1200),
+				regs_isa1200);
+
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
 					__func__, rc);
-				goto vreg_get_fail;
-			}
+			goto out;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_isa1200),
+				regs_isa1200);
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto reg_free;
 		}
 
 		rc = gpio_tlmm_config(GPIO_CFG(HAP_LVL_SHFT_MSM_GPIO, 0,
@@ -6696,28 +6428,27 @@
 		if (rc) {
 			pr_err("%s: Could not configure gpio %d\n",
 					__func__, HAP_LVL_SHFT_MSM_GPIO);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		rc = gpio_request(HAP_LVL_SHFT_MSM_GPIO, "haptics_shft_lvl_oe");
 		if (rc) {
 			pr_err("%s: unable to request gpio %d (%d)\n",
 					__func__, HAP_LVL_SHFT_MSM_GPIO, rc);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		gpio_set_value(HAP_LVL_SHFT_MSM_GPIO, 1);
 	} else {
-		for (i = 0; i < ARRAY_SIZE(vregs_isa1200_name); i++)
-			vreg_put(vregs_isa1200[i]);
-
+		regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
 		gpio_free(HAP_LVL_SHFT_MSM_GPIO);
 	}
 
 	return 0;
-vreg_get_fail:
-	while (i)
-		vreg_put(vregs_isa1200[--i]);
+
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs_isa1200), regs_isa1200);
+out:
 	return rc;
 }
 static struct isa1200_platform_data isa1200_1_pdata = {
@@ -6777,69 +6508,48 @@
 	}
 };
 
-static const char *vregs_tma300_name[] = {
-	"gp6",
-	"gp7",
+static struct regulator_bulk_data regs_tma300[] = {
+	{ .supply = "gp6", .min_uV = 3050000, .max_uV = 3100000 },
+	{ .supply = "gp7", .min_uV = 1800000, .max_uV = 1800000 },
 };
 
-static const int vregs_tma300_val[] = {
-	3050,
-	1800,
-};
-static struct vreg *vregs_tma300[ARRAY_SIZE(vregs_tma300_name)];
-
 static int tma300_power(int vreg_on)
 {
-	int i, rc = -EINVAL;
+	int rc;
 
-	for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
-		/* Never disable gp6 for fluid as lcd has a problem with it */
-		if (!i && !vreg_on)
-			continue;
-		if (!vregs_tma300[i]) {
-			printk(KERN_ERR "%s: vreg_get %s failed (%d)\n",
-				__func__, vregs_tma300_name[i], rc);
-			return rc;
-		}
+	rc = vreg_on ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_tma300), regs_tma300) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_tma300), regs_tma300);
 
-		rc = vreg_on ? vreg_enable(vregs_tma300[i]) :
-			  vreg_disable(vregs_tma300[i]);
-		if (rc < 0) {
-			printk(KERN_ERR "%s: vreg %s %s failed (%d)\n",
-				__func__, vregs_tma300_name[i],
-			       vreg_on ? "enable" : "disable", rc);
-			return rc;
-		}
-	}
-
-	return 0;
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_on ? "en" : "dis", rc);
+	return rc;
 }
 
 #define TS_GPIO_IRQ 150
 
 static int tma300_dev_setup(bool enable)
 {
-	int i, rc;
+	int rc;
 
 	if (enable) {
-		/* get voltage sources */
-		for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++) {
-			vregs_tma300[i] = vreg_get(NULL, vregs_tma300_name[i]);
-			if (IS_ERR(vregs_tma300[i])) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-					__func__, vregs_tma300_name[i],
-					PTR_ERR(vregs_tma300[i]));
-				rc = PTR_ERR(vregs_tma300[i]);
-				goto vreg_get_fail;
-			}
-			rc = vreg_set_level(vregs_tma300[i],
-					vregs_tma300_val[i]);
-			if (rc) {
-				pr_err("%s: vreg_set_level() = %d\n",
+		rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_tma300),
+				regs_tma300);
+
+		if (rc) {
+			pr_err("%s: could not get regulators: %d\n",
 					__func__, rc);
-				i++;
-				goto vreg_get_fail;
-			}
+			goto out;
+		}
+
+		rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_tma300),
+				regs_tma300);
+
+		if (rc) {
+			pr_err("%s: could not set voltages: %d\n",
+					__func__, rc);
+			goto reg_free;
 		}
 
 		/* enable interrupt gpio */
@@ -6848,7 +6558,7 @@
 		if (rc) {
 			pr_err("%s: Could not configure gpio %d\n",
 					__func__, TS_GPIO_IRQ);
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 
 		/* virtual keys */
@@ -6856,23 +6566,20 @@
 		properties_kobj = kobject_create_and_add("board_properties",
 					NULL);
 		if (!properties_kobj) {
-			pr_err("%s: failed to create a kobject"
-					"for board_properites\n", __func__);
+			pr_err("%s: failed to create a kobject "
+					"for board_properties\n", __func__);
 			rc = -ENOMEM;
-			goto vreg_get_fail;
+			goto reg_free;
 		}
 		rc = sysfs_create_group(properties_kobj,
 				&tma300_properties_attr_group);
 		if (rc) {
 			pr_err("%s: failed to create a sysfs entry %s\n",
 					__func__, tma300_vkeys_attr.attr.name);
-			kobject_put(properties_kobj);
-			goto vreg_get_fail;
+			goto kobj_free;
 		}
 	} else {
-		/* put voltage sources */
-		for (i = 0; i < ARRAY_SIZE(vregs_tma300_name); i++)
-			vreg_put(vregs_tma300[i]);
+		regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
 		/* destroy virtual keys */
 		if (properties_kobj) {
 			sysfs_remove_group(properties_kobj,
@@ -6882,9 +6589,12 @@
 	}
 	return 0;
 
-vreg_get_fail:
-	while (i)
-		vreg_put(vregs_tma300[--i]);
+kobj_free:
+	kobject_put(properties_kobj);
+	properties_kobj = NULL;
+reg_free:
+	regulator_bulk_free(ARRAY_SIZE(regs_tma300), regs_tma300);
+out:
 	return rc;
 }
 
@@ -6995,6 +6705,9 @@
 			ARRAY_SIZE(lcdc_toshiba_spi_board_info));
 #endif
 
+	atv_dac_power_init();
+	sensors_ldo_init();
+	hdmi_init_regs();
 	msm_fb_add_devices();
 	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
 	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_RESET_VECTOR,
@@ -7005,6 +6718,7 @@
 	msm7x30_init_marimba();
 #ifdef CONFIG_MSM7KV2_AUDIO
 	snddev_poweramp_gpio_init();
+	snddev_hsed_voltage_init();
 	aux_pcm_gpio_init();
 #endif
 
diff --git a/arch/arm/mach-msm/board-msm8960-regulator.c b/arch/arm/mach-msm/board-msm8960-regulator.c
index 6aee8e7..559312c 100644
--- a/arch/arm/mach-msm/board-msm8960-regulator.c
+++ b/arch/arm/mach-msm/board-msm8960-regulator.c
@@ -79,7 +79,7 @@
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8921_l14",		NULL),
-	REGULATOR_SUPPLY("pa_therm",		"pm8921-adc"),
+	REGULATOR_SUPPLY("pa_therm",		"pm8xxx-adc"),
 };
 VREG_CONSUMERS(L15) = {
 	REGULATOR_SUPPLY("8921_l15",		NULL),
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index a0a7d79..61423a6 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -21,7 +21,7 @@
 #include <linux/msm_ssbi.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/mfd/pm8xxx/pm8921.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spi/spi.h>
 #include <linux/slimbus/slimbus.h>
@@ -76,6 +76,7 @@
 
 #include <linux/ion.h>
 #include <mach/ion.h>
+#include <mach/mdm2.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -92,6 +93,11 @@
 #include "pm-boot.h"
 #include "msm_watchdog.h"
 
+#define PLATFORM_IS_CHARM25() \
+	(machine_is_msm8960_cdp() && \
+		(socinfo_get_platform_subtype() == 1) \
+	)
+
 static struct platform_device msm_fm_platform_init = {
 	.name = "iris_fm",
 	.id   = -1,
@@ -181,7 +187,7 @@
 static struct pm8xxx_mpp_init pm8921_mpps[] __initdata = {
 	/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
 	PM8XXX_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
-	PM8XXX_MPP_INIT(PM8921_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
+	PM8XXX_MPP_INIT(PM8XXX_AMUX_MPP_8, A_INPUT, PM8XXX_MPP_AIN_AMUX_CH8,
 								DOUT_CTRL_LOW),
 };
 
@@ -2663,6 +2669,138 @@
 };
 #endif
 
+#define MDM2AP_ERRFATAL			70
+#define AP2MDM_ERRFATAL			95
+#define MDM2AP_STATUS			69
+#define AP2MDM_STATUS			94
+#define AP2MDM_PMIC_RESET_N		80
+#define AP2MDM_KPDPWR_N			81
+
+static struct gpiomux_setting ap2mdm_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mdm2ap_status_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting mdm2ap_errfatal_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_16MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config mdm_configs[] __initdata = {
+	/* AP2MDM_STATUS */
+	{
+		.gpio = AP2MDM_STATUS,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* MDM2AP_STATUS */
+	{
+		.gpio = MDM2AP_STATUS,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_status_cfg,
+		}
+	},
+	/* MDM2AP_ERRFATAL */
+	{
+		.gpio = MDM2AP_ERRFATAL,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &mdm2ap_errfatal_cfg,
+		}
+	},
+	/* AP2MDM_ERRFATAL */
+	{
+		.gpio = AP2MDM_ERRFATAL,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_cfg,
+		}
+	},
+	/* AP2MDM_KPDPWR_N */
+	{
+		.gpio = AP2MDM_KPDPWR_N,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+		}
+	},
+	/* AP2MDM_PMIC_RESET_N */
+	{
+		.gpio = AP2MDM_PMIC_RESET_N,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_kpdpwr_n_cfg,
+		}
+	}
+};
+
+static struct resource mdm_resources[] = {
+	{
+		.start	= MDM2AP_ERRFATAL,
+		.end	= MDM2AP_ERRFATAL,
+		.name	= "MDM2AP_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_ERRFATAL,
+		.end	= AP2MDM_ERRFATAL,
+		.name	= "AP2MDM_ERRFATAL",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= MDM2AP_STATUS,
+		.end	= MDM2AP_STATUS,
+		.name	= "MDM2AP_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_STATUS,
+		.end	= AP2MDM_STATUS,
+		.name	= "AP2MDM_STATUS",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_PMIC_RESET_N,
+		.end	= AP2MDM_PMIC_RESET_N,
+		.name	= "AP2MDM_PMIC_RESET_N",
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= AP2MDM_KPDPWR_N,
+		.end	= AP2MDM_KPDPWR_N,
+		.name	= "AP2MDM_KPDPWR_N",
+		.flags	= IORESOURCE_IO,
+	},
+};
+
+static struct mdm_platform_data mdm_platform_data = {
+	.mdm_version = "2.5",
+};
+
+struct platform_device mdm_device = {
+	.name		= "mdm2_modem",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(mdm_resources),
+	.resource	= mdm_resources,
+	.dev		= {
+		.platform_data = &mdm_platform_data,
+	},
+};
+
+static struct platform_device *mdm_devices[] __initdata = {
+	&mdm_device,
+};
 
 static int __init gpiomux_init(void)
 {
@@ -2710,12 +2848,17 @@
 		machine_is_msm8960_liquid() || machine_is_msm8960_cdp())
 		msm_gpiomux_install(hap_lvl_shft_config,
 			ARRAY_SIZE(hap_lvl_shft_config));
+
+	if (PLATFORM_IS_CHARM25())
+		msm_gpiomux_install(mdm_configs,
+			ARRAY_SIZE(mdm_configs));
+
 	return 0;
 }
 
 #define MSM_SHARED_RAM_PHYS 0x80000000
 
-static struct pm8921_adc_amux pm8921_adc_channels_data[] = {
+static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
 	{"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
 		ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
 	{"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
@@ -2750,16 +2893,16 @@
 		ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
 };
 
-static struct pm8921_adc_properties pm8921_adc_data = {
+static struct pm8xxx_adc_properties pm8xxx_adc_data = {
 	.adc_vdd_reference	= 1800, /* milli-voltage for this adc */
 	.bitresolution		= 15,
 	.bipolar                = 0,
 };
 
-static struct pm8921_adc_platform_data pm8921_adc_pdata = {
-	.adc_channel		= pm8921_adc_channels_data,
-	.adc_num_board_channel	= ARRAY_SIZE(pm8921_adc_channels_data),
-	.adc_prop		= &pm8921_adc_data,
+static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
+	.adc_channel		= pm8xxx_adc_channels_data,
+	.adc_num_board_channel	= ARRAY_SIZE(pm8xxx_adc_channels_data),
+	.adc_prop		= &pm8xxx_adc_data,
 	.adc_mpp_base		= PM8921_MPP_PM_TO_SYS(1),
 };
 
@@ -4058,10 +4201,8 @@
 	if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
 		struct kgsl_device_platform_data *kgsl_3d0_pdata =
 				msm_kgsl_3d0.dev.platform_data;
-		kgsl_3d0_pdata->pwr_data.pwrlevel[0].gpu_freq =
-				320000000;
-		kgsl_3d0_pdata->pwr_data.pwrlevel[1].gpu_freq =
-				266667000;
+		kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
 	}
 }
 
@@ -4396,7 +4537,7 @@
 	.regulator_pdatas	= msm_pm8921_regulator_pdata,
 	.charger_pdata		= &pm8921_chg_pdata,
 	.bms_pdata		= &pm8921_bms_pdata,
-	.adc_pdata		= &pm8921_adc_pdata,
+	.adc_pdata		= &pm8xxx_adc_pdata,
 	.leds_pdata		= &pm8xxx_leds_pdata,
 	.ccadc_pdata		= &pm8xxx_ccadc_pdata,
 };
@@ -4840,6 +4981,9 @@
 				msm_pm_data);
 	change_memory_power = &msm8960_change_memory_power;
 	BUG_ON(msm_pm_boot_init(MSM_PM_BOOT_CONFIG_TZ, NULL));
+
+	if (PLATFORM_IS_CHARM25())
+		platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
 }
 
 MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 8f733a9..c22d54c 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1085,8 +1085,8 @@
 		return -ENOTSUPP;
 	}
 
-	if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) &&
-			!pmic_id_notif_supported) {
+	if ((machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa() ||
+			machine_is_msm8x60_ffa()) && !pmic_id_notif_supported) {
 		pr_debug("%s: USB_ID is not routed to PMIC"
 			"on V2 ffa\n", __func__);
 		return -ENOTSUPP;
@@ -9292,7 +9292,7 @@
 			goto out;
 	} else {
 		/* set ldo0 to LPM */
-		rc = regulator_set_optimum_mode(ldo0, 9000);
+		rc = regulator_set_optimum_mode(ldo0, 1000);
 		if (rc < 0)
 			goto out;
 	}
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 85de532..d192faf 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -36,10 +36,8 @@
 #include <mach/rpc_hsusb.h>
 #include <mach/rpc_pmapp.h>
 #include <mach/usbdiag.h>
-#include <mach/usb_gadget_fserial.h>
 #include <mach/msm_memtypes.h>
 #include <mach/msm_serial_hs.h>
-#include <mach/vreg.h>
 #include <mach/pmic.h>
 #include <mach/socinfo.h>
 #include <mach/vreg.h>
@@ -47,7 +45,7 @@
 #include <mach/msm_battery.h>
 #include <mach/rpc_server_handset.h>
 #include <mach/socinfo.h>
-
+#include "board-msm7x27a-regulator.h"
 #include "devices.h"
 #include "devices-msm7x2xa.h"
 #include "pm.h"
@@ -279,7 +277,7 @@
 
 	return rc;
 }
-static struct vreg *fm_regulator;
+static struct regulator *fm_regulator;
 static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
 {
 	int rc = 0;
@@ -289,27 +287,25 @@
 	u8 value;
 
 	/* Voting for 1.8V Regulator */
-	fm_regulator = vreg_get(NULL , "msme1");
+	fm_regulator = regulator_get(NULL , "msme1");
 	if (IS_ERR(fm_regulator)) {
-		pr_err("%s: vreg get failed with : (%ld)\n",
-			__func__, PTR_ERR(fm_regulator));
-		return -EINVAL;
+		rc = PTR_ERR(fm_regulator);
+		pr_err("%s: could not get regulator: %d\n", __func__, rc);
+		goto out;
 	}
 
 	/* Set the voltage level to 1.8V */
-	rc = vreg_set_level(fm_regulator, 1800);
+	rc = regulator_set_voltage(fm_regulator, 1800000, 1800000);
 	if (rc < 0) {
-		pr_err("%s: set regulator level failed with :(%d)\n",
-			__func__, rc);
-		goto fm_vreg_fail;
+		pr_err("%s: could not set voltage: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	/* Enabling the 1.8V regulator */
-	rc = vreg_enable(fm_regulator);
+	rc = regulator_enable(fm_regulator);
 	if (rc) {
-		pr_err("%s: enable regulator failed with :(%d)\n",
-			__func__, rc);
-		goto fm_vreg_fail;
+		pr_err("%s: could not enable regulator: %d\n", __func__, rc);
+		goto reg_free;
 	}
 
 	/* Voting for 19.2MHz clock */
@@ -318,13 +314,13 @@
 	if (rc < 0) {
 		pr_err("%s: clock vote failed with :(%d)\n",
 			 __func__, rc);
-		goto fm_clock_vote_fail;
+		goto reg_disable;
 	}
 
 	rc = bt_set_gpio(1);
 	if (rc) {
 		pr_err("%s: bt_set_gpio = %d", __func__, rc);
-		goto fm_gpio_config_fail;
+		goto gpio_deconfig;
 	}
 	/*re-write FM Slave Id, after reset*/
 	value = BAHAMA_SLAVE_ID_FM_ADDR;
@@ -332,7 +328,7 @@
 			BAHAMA_SLAVE_ID_FM_REG, &value, 1, 0xFF);
 	if (rc < 0) {
 		pr_err("%s: FM Slave ID rewrite Failed = %d", __func__, rc);
-		goto fm_gpio_config_fail;
+		goto gpio_deconfig;
 	}
 	/* Configuring the FM GPIO */
 	irqcfg = GPIO_CFG(FM_GPIO, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
@@ -342,21 +338,21 @@
 	if (rc) {
 		pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
 			 __func__, irqcfg, rc);
-		goto fm_gpio_config_fail;
+		goto gpio_deconfig;
 	}
 
 	return 0;
 
-fm_gpio_config_fail:
+gpio_deconfig:
 	pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
 		PMAPP_CLOCK_VOTE_OFF);
 	bt_set_gpio(0);
-fm_clock_vote_fail:
-	vreg_disable(fm_regulator);
-
-fm_vreg_fail:
-	vreg_put(fm_regulator);
-
+reg_disable:
+	regulator_disable(fm_regulator);
+reg_free:
+	regulator_put(fm_regulator);
+	fm_regulator = NULL;
+out:
 	return rc;
 };
 
@@ -375,11 +371,12 @@
 			 __func__, irqcfg, rc);
 
 	/* Releasing the 1.8V Regulator */
-	if (fm_regulator != NULL) {
-		rc = vreg_disable(fm_regulator);
+	if (!IS_ERR_OR_NULL(fm_regulator)) {
+		rc = regulator_disable(fm_regulator);
 		if (rc)
-			pr_err("%s: disable regulator failed:(%d)\n",
-				__func__, rc);
+			pr_err("%s: could not disable regulator: %d\n",
+					__func__, rc);
+		regulator_put(fm_regulator);
 		fm_regulator = NULL;
 	}
 
@@ -423,18 +420,18 @@
 struct bt_vreg_info {
 	const char *name;
 	unsigned int pmapp_id;
-	unsigned int level;
+	unsigned int min_level;
+	unsigned int max_level;
 	unsigned int is_pin_controlled;
-	struct vreg *vregs;
+	struct regulator *reg;
 };
 static struct bt_vreg_info bt_vregs[] = {
-	{"msme1", 2, 1800, 0, NULL},
-	{"bt", 21, 2900, 1, NULL}
+	{"msme1", 2, 1800000, 1800000, 0, NULL},
+	{"bt", 21, 2900000, 3050000, 1, NULL}
 };
 
 static int bahama_bt(int on)
 {
-
 	int rc = 0;
 	int i;
 
@@ -587,73 +584,94 @@
 	const char *id = "BTPW";
 
 	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
-		if (!bt_vregs[i].vregs) {
-			pr_err("%s: vreg_get %s failed(%d)\n",
-			__func__, bt_vregs[i].name, rc);
-			goto vreg_fail;
+		if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
+			rc = bt_vregs[i].reg ?
+				PTR_ERR(bt_vregs[i].reg) :
+				-ENODEV;
+			dev_err(&msm_bt_power_device.dev,
+				"%s: invalid regulator handle for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_disable;
 		}
-		rc = on ? vreg_set_level(bt_vregs[i].vregs,
-				bt_vregs[i].level) : 0;
 
-		if (rc < 0) {
-			pr_err("%s: vreg set level failed (%d)\n",
-					__func__, rc);
-			goto vreg_set_level_fail;
+		rc = on ? regulator_set_voltage(bt_vregs[i].reg,
+					bt_vregs[i].min_level,
+						bt_vregs[i].max_level) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not set voltage for %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_disable;
 		}
-		if (bt_vregs[i].is_pin_controlled == 1) {
-			rc = pmapp_vreg_pincntrl_vote(id,
-					bt_vregs[i].pmapp_id,
+
+		rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "en", bt_vregs[i].name, rc);
+			goto reg_disable;
+		}
+
+		if (bt_vregs[i].is_pin_controlled) {
+			rc = pmapp_vreg_lpm_pincntrl_vote(id,
+				bt_vregs[i].pmapp_id,
 					PMAPP_CLOCK_ID_D1,
 					on ? PMAPP_CLOCK_VOTE_ON :
-					PMAPP_CLOCK_VOTE_OFF);
-		} else {
-		rc = on ? vreg_enable(bt_vregs[i].vregs) :
-			  vreg_disable(bt_vregs[i].vregs);
+						PMAPP_CLOCK_VOTE_OFF);
+			if (rc) {
+				dev_err(&msm_bt_power_device.dev,
+					"%s: pin control failed for %s: %d\n",
+						__func__, bt_vregs[i].name, rc);
+				goto pin_cnt_fail;
+			}
 		}
+		rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
 
-		if (rc < 0) {
-			pr_err("%s: vreg %s %s failed(%d)\n",
-					__func__, bt_vregs[i].name,
-					on ? "enable" : "disable", rc);
-			goto vreg_fail;
+		if (rc) {
+			dev_err(&msm_bt_power_device.dev,
+				"%s: could not %sable regulator %s: %d\n",
+					__func__, "dis", bt_vregs[i].name, rc);
+			goto reg_disable;
 		}
 	}
 
 	return rc;
-
-vreg_fail:
+pin_cnt_fail:
+	if (on)
+		regulator_disable(bt_vregs[i].reg);
+reg_disable:
 	while (i) {
-		if (on)
-			vreg_disable(bt_vregs[--i].vregs);
+		if (on) {
+			i--;
+			regulator_disable(bt_vregs[i].reg);
+			regulator_put(bt_vregs[i].reg);
 		}
-vreg_set_level_fail:
-	vreg_put(bt_vregs[0].vregs);
-	vreg_put(bt_vregs[1].vregs);
+	}
 	return rc;
 }
 
+static struct regulator *reg_s3;
 static unsigned int msm_bahama_setup_power(void)
 {
 	int rc = 0;
-	struct vreg *vreg_s3 = NULL;
 
-	vreg_s3 = vreg_get(NULL, "msme1");
-	if (IS_ERR(vreg_s3)) {
-		pr_err("%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_s3));
-		return PTR_ERR(vreg_s3);
+	reg_s3 = regulator_get(NULL, "msme1");
+	if (IS_ERR(reg_s3)) {
+		rc = PTR_ERR(reg_s3);
+		pr_err("%s: could not get regulator: %d\n", __func__, rc);
+		goto out;
 	}
-	rc = vreg_set_level(vreg_s3, 1800);
+
+	rc = regulator_set_voltage(reg_s3, 1800000, 1800000);
 	if (rc < 0) {
-		pr_err("%s: vreg set level failed (%d)\n",
-				__func__, rc);
-		goto vreg_fail;
+		pr_err("%s: could not set voltage: %d\n", __func__, rc);
+		goto reg_fail;
 	}
-	rc = vreg_enable(vreg_s3);
+
+	rc = regulator_enable(reg_s3);
 	if (rc < 0) {
-		pr_err("%s: vreg enable failed (%d)\n",
-		       __func__, rc);
-		goto vreg_fail;
+		pr_err("%s: could not enable regulator: %d\n", __func__, rc);
+		goto reg_fail;
 	}
 
 	/*setup Bahama_sys_reset_n*/
@@ -661,48 +679,62 @@
 	if (rc < 0) {
 		pr_err("%s: gpio_request %d = %d\n", __func__,
 			GPIO_BT_SYS_REST_EN, rc);
-		goto vreg_fail;
+		goto reg_disable;
 	}
+
 	rc = bt_set_gpio(1);
 	if (rc < 0) {
 		pr_err("%s: bt_set_gpio %d = %d\n", __func__,
 			GPIO_BT_SYS_REST_EN, rc);
 		goto gpio_fail;
 	}
+
 	return rc;
 
 gpio_fail:
 	gpio_free(GPIO_BT_SYS_REST_EN);
-vreg_fail:
-	vreg_put(vreg_s3);
+reg_disable:
+	regulator_disable(reg_s3);
+reg_fail:
+	regulator_put(reg_s3);
+out:
+	reg_s3 = NULL;
 	return rc;
 }
 
 static unsigned int msm_bahama_shutdown_power(int value)
 {
 	int rc = 0;
-	struct vreg *vreg_s3 = NULL;
 
-	vreg_s3 = vreg_get(NULL, "msme1");
-	if (IS_ERR(vreg_s3)) {
-		pr_err("%s: vreg get failed (%ld)\n",
-			__func__, PTR_ERR(vreg_s3));
-		return PTR_ERR(vreg_s3);
+	if (IS_ERR_OR_NULL(reg_s3)) {
+		rc = reg_s3 ? PTR_ERR(reg_s3) : -ENODEV;
+		goto out;
 	}
-	rc = vreg_disable(vreg_s3);
+
+	rc = regulator_disable(reg_s3);
 	if (rc) {
-		pr_err("%s: vreg disable failed (%d)\n",
-		       __func__, rc);
-		vreg_put(vreg_s3);
-		return rc;
+		pr_err("%s: could not disable regulator: %d\n", __func__, rc);
+		goto out;
 	}
+
 	if (value == BAHAMA_ID) {
 		rc = bt_set_gpio(0);
 		if (rc) {
 			pr_err("%s: bt_set_gpio = %d\n",
 					__func__, rc);
+			goto reg_enable;
 		}
+		gpio_free(GPIO_BT_SYS_REST_EN);
 	}
+
+	regulator_put(reg_s3);
+	reg_s3 = NULL;
+
+	return 0;
+
+reg_enable:
+	regulator_enable(reg_s3);
+out:
 	return rc;
 }
 
@@ -863,25 +895,27 @@
 static int __init bt_power_init(void)
 {
 	int i, rc = 0;
-	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
-			bt_vregs[i].vregs = vreg_get(NULL,
-					bt_vregs[i].name);
-			if (IS_ERR(bt_vregs[i].vregs)) {
-				pr_err("%s: vreg get %s failed (%ld)\n",
-				       __func__, bt_vregs[i].name,
-				       PTR_ERR(bt_vregs[i].vregs));
-				rc = PTR_ERR(bt_vregs[i].vregs);
-				goto vreg_get_fail;
-			}
-		}
+	struct device *dev = &msm_bt_power_device.dev;
 
-	msm_bt_power_device.dev.platform_data = &bluetooth_power;
+	for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
+		bt_vregs[i].reg = regulator_get(dev, bt_vregs[i].name);
+		if (IS_ERR(bt_vregs[i].reg)) {
+			rc = PTR_ERR(bt_vregs[i].reg);
+			dev_err(dev, "%s: could not get regulator %s: %d\n",
+					__func__, bt_vregs[i].name, rc);
+			goto reg_get_fail;
+		}
+	}
+
+	dev->platform_data = &bluetooth_power;
 
 	return rc;
 
-vreg_get_fail:
-	while (i)
-		vreg_put(bt_vregs[--i].vregs);
+reg_get_fail:
+	while (i--) {
+		regulator_put(bt_vregs[i].reg);
+		bt_vregs[i].reg = NULL;
+	}
 	return rc;
 }
 
@@ -1144,35 +1178,52 @@
 		return msm_hsusb_rpc_close();
 }
 
-static struct vreg *vreg_3p3;
+static struct regulator *reg_hsusb;
 static int msm_hsusb_ldo_init(int init)
 {
-	if (init) {
-		vreg_3p3 = vreg_get(NULL, "usb");
-		if (IS_ERR(vreg_3p3))
-			return PTR_ERR(vreg_3p3);
-	} else
-		vreg_put(vreg_3p3);
+	int rc = 0;
 
-	return 0;
+	if (init) {
+		reg_hsusb = regulator_get(NULL, "usb");
+		if (IS_ERR(reg_hsusb)) {
+			rc = PTR_ERR(reg_hsusb);
+			pr_err("%s: could not get regulator: %d\n",
+					__func__, rc);
+			goto out;
+		}
+
+		rc = regulator_set_voltage(reg_hsusb, 3300000, 3300000);
+		if (rc) {
+			pr_err("%s: could not set voltage: %d\n",
+					__func__, rc);
+			goto reg_free;
+		}
+
+		return 0;
+	}
+	/* else fall through */
+reg_free:
+	regulator_put(reg_hsusb);
+out:
+	reg_hsusb = NULL;
+	return rc;
 }
 
 static int msm_hsusb_ldo_enable(int enable)
 {
 	static int ldo_status;
 
-	if (!vreg_3p3 || IS_ERR(vreg_3p3))
-		return -ENODEV;
+	if (IS_ERR_OR_NULL(reg_hsusb))
+		return reg_hsusb ? PTR_ERR(reg_hsusb) : -ENODEV;
 
 	if (ldo_status == enable)
 		return 0;
 
 	ldo_status = enable;
 
-	if (enable)
-		return vreg_enable(vreg_3p3);
-
-	return vreg_disable(vreg_3p3);
+	return enable ?
+		regulator_enable(reg_hsusb) :
+		regulator_disable(reg_hsusb);
 }
 
 #ifndef CONFIG_USB_EHCI_MSM_72K
@@ -1219,15 +1270,6 @@
 	|| defined(CONFIG_MMC_MSM_SDC4_SUPPORT))
 
 static unsigned long vreg_sts, gpio_sts;
-static struct vreg *vreg_mmc;
-static struct vreg *vreg_emmc;
-
-struct sdcc_vreg {
-	struct vreg *vreg_data;
-	unsigned level;
-};
-
-static struct sdcc_vreg sdcc_vreg_data[4];
 
 struct sdcc_gpio {
 	struct msm_gpio *cfg_data;
@@ -1346,6 +1388,7 @@
 	},
 };
 
+static struct regulator *sdcc_vreg_data[ARRAY_SIZE(sdcc_cfg_data)];
 static int msm_sdcc_setup_gpio(int dev_id, unsigned int enable)
 {
 	int rc = 0;
@@ -1376,27 +1419,31 @@
 static int msm_sdcc_setup_vreg(int dev_id, unsigned int enable)
 {
 	int rc = 0;
-	struct sdcc_vreg *curr;
+	struct regulator *curr = sdcc_vreg_data[dev_id - 1];
 
-	curr = &sdcc_vreg_data[dev_id - 1];
+	if (test_bit(dev_id, &vreg_sts) == enable)
+		return 0;
 
-	if (!(test_bit(dev_id, &vreg_sts)^enable))
-		return rc;
+	if (!curr)
+		return -ENODEV;
+
+	if (IS_ERR(curr))
+		return PTR_ERR(curr);
 
 	if (enable) {
 		set_bit(dev_id, &vreg_sts);
-		rc = vreg_set_level(curr->vreg_data, curr->level);
-		if (rc)
-			pr_err("%s: vreg_set_level() = %d\n", __func__, rc);
 
-		rc = vreg_enable(curr->vreg_data);
+		rc = regulator_enable(curr);
 		if (rc)
-			pr_err("%s: vreg_enable() = %d\n", __func__, rc);
+			pr_err("%s: could not enable regulator: %d\n",
+						__func__, rc);
 	} else {
 		clear_bit(dev_id, &vreg_sts);
-		rc = vreg_disable(curr->vreg_data);
+
+		rc = regulator_disable(curr);
 		if (rc)
-			pr_err("%s: vreg_disable() = %d\n", __func__, rc);
+			pr_err("%s: could not disable regulator: %d\n",
+						__func__, rc);
 	}
 	return rc;
 }
@@ -1644,45 +1691,65 @@
 	}
 };
 
+static int __init mmc_regulator_init(int sdcc_no, const char *supply, int uV)
+{
+	int rc;
+
+	BUG_ON(sdcc_no < 1 || sdcc_no > 4);
+
+	sdcc_no--;
+
+	sdcc_vreg_data[sdcc_no] = regulator_get(NULL, supply);
+
+	if (IS_ERR(sdcc_vreg_data[sdcc_no])) {
+		rc = PTR_ERR(sdcc_vreg_data[sdcc_no]);
+		pr_err("%s: could not get regulator \"%s\": %d\n",
+				__func__, supply, rc);
+		goto out;
+	}
+
+	rc = regulator_set_voltage(sdcc_vreg_data[sdcc_no], uV, uV);
+
+	if (rc) {
+		pr_err("%s: could not set voltage for \"%s\" to %d uV: %d\n",
+				__func__, supply, uV, rc);
+		goto reg_free;
+	}
+
+	return rc;
+
+reg_free:
+	regulator_put(sdcc_vreg_data[sdcc_no]);
+out:
+	sdcc_vreg_data[sdcc_no] = NULL;
+	return rc;
+}
+
 static void __init msm7627a_init_mmc(void)
 {
-	vreg_emmc = vreg_get(NULL, "emmc");
-	if (IS_ERR(vreg_emmc)) {
-		pr_err("%s: vreg get failed (%ld)\n",
-				__func__, PTR_ERR(vreg_emmc));
-		return;
-	}
-
-	vreg_mmc = vreg_get(NULL, "mmc");
-	if (IS_ERR(vreg_mmc)) {
-		pr_err("%s: vreg get failed (%ld)\n",
-				__func__, PTR_ERR(vreg_mmc));
-		return;
-	}
-
 	/* eMMC slot */
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-	sdcc_vreg_data[2].vreg_data = vreg_emmc;
-	sdcc_vreg_data[2].level = 3000;
+	if (mmc_regulator_init(3, "emmc", 3000000))
+		return;
 	msm_add_sdcc(3, &sdc3_plat_data);
 #endif
 	/* Micro-SD slot */
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
-	sdcc_vreg_data[0].vreg_data = vreg_mmc;
-	sdcc_vreg_data[0].level = 2850;
+	if (mmc_regulator_init(1, "mmc", 2850000))
+		return;
 	msm_add_sdcc(1, &sdc1_plat_data);
 #endif
 	/* SDIO WLAN slot */
 #ifdef CONFIG_MMC_MSM_SDC2_SUPPORT
-	sdcc_vreg_data[1].vreg_data = vreg_mmc;
-	sdcc_vreg_data[1].level = 2850;
+	if (mmc_regulator_init(2, "mmc", 2850000))
+		return;
 	msm_add_sdcc(2, &sdc2_plat_data);
 #endif
 	/* Not Used */
 #if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
 		&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
-	sdcc_vreg_data[3].vreg_data = vreg_mmc;
-	sdcc_vreg_data[3].level = 2850;
+	if (mmc_regulator_init(4, "mmc", 2850000))
+		return;
 	msm_add_sdcc(4, &sdc4_plat_data);
 #endif
 }
@@ -1945,98 +2012,39 @@
 }
 
 #endif
-static struct vreg *vreg_gp1;
-static struct vreg *vreg_gp2;
-static struct vreg *vreg_gp3;
-static void msm_camera_vreg_config(int vreg_en)
+static struct regulator_bulk_data regs_camera[] = {
+	{ .supply = "msme1", .min_uV = 1800000, .max_uV = 1800000 },
+	{ .supply = "gp2",   .min_uV = 2850000, .max_uV = 2850000 },
+	{ .supply = "usb2",  .min_uV = 1800000, .max_uV = 1800000 },
+};
+
+static void __init msm_camera_vreg_init(void)
 {
 	int rc;
 
-	if (vreg_gp1 == NULL) {
-		vreg_gp1 = vreg_get(NULL, "msme1");
-		if (IS_ERR(vreg_gp1)) {
-			pr_err("%s: vreg_get(%s) failed (%ld)\n",
-				__func__, "msme1", PTR_ERR(vreg_gp1));
-			return;
-		}
-
-		rc = vreg_set_level(vreg_gp1, 1800);
-		if (rc) {
-			pr_err("%s: GP1 set_level failed (%d)\n",
-				__func__, rc);
-			return;
-		}
+	rc = regulator_bulk_get(NULL, ARRAY_SIZE(regs_camera), regs_camera);
+	if (rc) {
+		pr_err("%s: could not get regulators: %d\n", __func__, rc);
+		return;
 	}
 
-	if (vreg_gp2 == NULL) {
-		vreg_gp2 = vreg_get(NULL, "gp2");
-		if (IS_ERR(vreg_gp2)) {
-			pr_err("%s: vreg_get(%s) failed (%ld)\n",
-				__func__, "gp2", PTR_ERR(vreg_gp2));
-			return;
-		}
-
-		rc = vreg_set_level(vreg_gp2, 2850);
-		if (rc) {
-			pr_err("%s: GP2 set_level failed (%d)\n",
-				__func__, rc);
-		}
-	}
-
-	if (vreg_gp3 == NULL) {
-		vreg_gp3 = vreg_get(NULL, "usb2");
-		if (IS_ERR(vreg_gp3)) {
-			pr_err("%s: vreg_get(%s) failed (%ld)\n",
-				__func__, "gp3", PTR_ERR(vreg_gp3));
-			return;
-		}
-
-		rc = vreg_set_level(vreg_gp3, 1800);
-		if (rc) {
-			pr_err("%s: GP3 set level failed (%d)\n",
-				__func__, rc);
-		}
-	}
-
-	if (vreg_en) {
-		rc = vreg_enable(vreg_gp1);
-		if (rc) {
-			pr_err("%s: GP1 enable failed (%d)\n",
-				__func__, rc);
-			return;
-		}
-
-		rc = vreg_enable(vreg_gp2);
-		if (rc) {
-			pr_err("%s: GP2 enable failed (%d)\n",
-				__func__, rc);
-		}
-
-		rc = vreg_enable(vreg_gp3);
-		if (rc) {
-			pr_err("%s: GP3 enable failed (%d)\n",
-				__func__, rc);
-		}
-	} else {
-		rc = vreg_disable(vreg_gp1);
-		if (rc)
-			pr_err("%s: GP1 disable failed (%d)\n",
-				__func__, rc);
-
-		rc = vreg_disable(vreg_gp2);
-		if (rc) {
-			pr_err("%s: GP2 disable failed (%d)\n",
-				__func__, rc);
-		}
-
-		rc = vreg_disable(vreg_gp3);
-		if (rc) {
-			pr_err("%s: GP3 disable failed (%d)\n",
-				__func__, rc);
-		}
+	rc = regulator_bulk_set_voltage(ARRAY_SIZE(regs_camera), regs_camera);
+	if (rc) {
+		pr_err("%s: could not set voltages: %d\n", __func__, rc);
+		return;
 	}
 }
 
+static void msm_camera_vreg_config(int vreg_en)
+{
+	int rc = vreg_en ?
+		regulator_bulk_enable(ARRAY_SIZE(regs_camera), regs_camera) :
+		regulator_bulk_disable(ARRAY_SIZE(regs_camera), regs_camera);
+
+	if (rc)
+		pr_err("%s: could not %sable regulators: %d\n",
+				__func__, vreg_en ? "en" : "dis", rc);
+}
 static int config_gpio_table(uint32_t *table, int len)
 {
 	int rc = 0, i = 0;
@@ -2563,6 +2571,7 @@
 	bt_power_init();
 #endif
 
+	msm_camera_vreg_init();
 	i2c_register_board_info(MSM_GSBI0_QUP_I2C_BUS_ID, i2c_camera_devices,
 			ARRAY_SIZE(i2c_camera_devices));
 
diff --git a/arch/arm/mach-msm/board-sapphire-keypad.c b/arch/arm/mach-msm/board-sapphire-keypad.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/board-sapphire-mmc.c b/arch/arm/mach-msm/board-sapphire-mmc.c
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index c16c2ee..a4c8b2a2 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1791,6 +1791,7 @@
 	F_SDC( 48000000, pll8,  4, 1,   2),
 	F_SDC( 64000000, pll8,  3, 1,   2),
 	F_SDC( 96000000, pll8,  4, 0,   0),
+	F_SDC(192000000, pll8,  2, 0,   0),
 	F_END
 };
 
@@ -4920,9 +4921,9 @@
 
 	{ TEST_LPA_HS(0x00), &q6_func_clk },
 
-	{ TEST_CPUL2(0x1), &l2_m_clk },
-	{ TEST_CPUL2(0x2), &krait0_m_clk },
-	{ TEST_CPUL2(0x3), &krait1_m_clk },
+	{ TEST_CPUL2(0x2), &l2_m_clk },
+	{ TEST_CPUL2(0x0), &krait0_m_clk },
+	{ TEST_CPUL2(0x1), &krait1_m_clk },
 };
 
 static struct measure_sel *find_measure_sel(struct clk *clk)
@@ -5244,7 +5245,7 @@
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("core_clk",		rot_clk.c,	"footswitch-8x60.6"),
 	CLK_DUMMY("tv_src_clk",		TV_SRC_CLK,		NULL, OFF),
-	CLK_LOOKUP("core_clk",		vcodec_clk.c,		NULL),
+	CLK_LOOKUP("core_clk",		vcodec_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("core_clk",		vcodec_clk.c,	"footswitch-8x60.7"),
 	CLK_DUMMY("mdp_tv_clk",		MDP_TV_CLK,		NULL, OFF),
 	CLK_DUMMY("hdmi_clk",		HDMI_TV_CLK,		NULL, OFF),
@@ -5280,7 +5281,7 @@
 	CLK_LOOKUP("iface_clk",		smmu_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"msm_rotator.0"),
 	CLK_LOOKUP("iface_clk",		rot_p_clk.c,	"footswitch-8x60.6"),
-	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		NULL),
+	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,		"msm_vidc.0"),
 	CLK_LOOKUP("iface_clk",		vcodec_p_clk.c,	"footswitch-8x60.7"),
 	CLK_LOOKUP("vfe_pclk",		vfe_p_clk.c,		NULL),
 	CLK_LOOKUP("iface_clk",		vfe_p_clk.c,	"footswitch-8x60.8"),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 78da29c..c8212a3 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1766,7 +1766,7 @@
 
 	/* Program bias count */
 	regval &= ~BM(19, 14);
-	regval |= BVAL(19, 14, 0x4);
+	regval |= BVAL(19, 14, 0x1);
 	writel_relaxed(regval, mode_reg);
 
 	/* Program lock count */
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 2391f84..8aee414 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -911,3 +911,97 @@
 {
 	return branch_reset(&to_branch_clk(clk)->b, action);
 }
+
+static int cdiv_clk_enable(struct clk *c)
+{
+	unsigned long flags;
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	__branch_clk_enable_reg(&clk->b, clk->c.dbg_name);
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+	return 0;
+}
+
+static void cdiv_clk_disable(struct clk *c)
+{
+	unsigned long flags;
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+
+	spin_lock_irqsave(&local_clock_reg_lock, flags);
+	__branch_clk_disable_reg(&clk->b, clk->c.dbg_name);
+	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+static int cdiv_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+	u32 reg_val;
+
+	if (rate > clk->max_div)
+		return -EINVAL;
+	/* Check if frequency is actually changed. */
+	if (rate == clk->cur_div)
+		return 0;
+
+	spin_lock(&local_clock_reg_lock);
+	reg_val = readl_relaxed(clk->ns_reg);
+	reg_val &= ~(clk->ext_mask | (clk->max_div - 1) << clk->div_offset);
+	/* Non-zero rates mean set a divider, zero means use external input */
+	if (rate)
+		reg_val |= (rate - 1) << clk->div_offset;
+	else
+		reg_val |= clk->ext_mask;
+	writel_relaxed(reg_val, clk->ns_reg);
+	spin_unlock(&local_clock_reg_lock);
+
+	clk->cur_div = rate;
+	return 0;
+}
+
+static unsigned long cdiv_clk_get_rate(struct clk *c)
+{
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+	return clk->cur_div;
+}
+
+static long cdiv_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+	return rate > clk->max_div ? -EPERM : rate;
+}
+
+static int cdiv_clk_list_rate(struct clk *c, unsigned n)
+{
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+	return n > clk->max_div ? -ENXIO : n;
+}
+
+static int cdiv_clk_handoff(struct clk *c)
+{
+	struct cdiv_clk *clk = to_cdiv_clk(c);
+	u32 reg_val;
+
+	reg_val = readl_relaxed(clk->ns_reg);
+	if (reg_val & clk->ext_mask) {
+		clk->cur_div = 0;
+	} else {
+		reg_val >>= clk->div_offset;
+		clk->cur_div = (reg_val & (clk->max_div - 1)) + 1;
+	}
+
+	return 0;
+}
+
+struct clk_ops clk_ops_cdiv = {
+	.enable = cdiv_clk_enable,
+	.disable = cdiv_clk_disable,
+	.auto_off = cdiv_clk_disable,
+	.handoff = cdiv_clk_handoff,
+	.set_rate = cdiv_clk_set_rate,
+	.get_rate = cdiv_clk_get_rate,
+	.list_rate = cdiv_clk_list_rate,
+	.round_rate = cdiv_clk_round_rate,
+	.is_local = local_clk_is_local,
+};
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 2107567..e651d47 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -153,6 +153,35 @@
 int rcg_clk_handoff(struct clk *c);
 
 /**
+ * struct cdiv_clk - integer divider clock with external source selection
+ * @ns_reg: source select and divider settings register
+ * @ext_mask: bit to set to select an external source
+ * @cur_div: current divider setting (or 0 for external source)
+ * @max_div: maximum divider value supported (must be power of 2)
+ * @div_offset: number of bits to shift divider left by in @ns_reg
+ * @b: branch
+ * @c: clock
+ */
+struct cdiv_clk {
+	void __iomem *const ns_reg;
+	u32 ext_mask;
+
+	unsigned long cur_div;
+	u8 div_offset;
+	u32 max_div;
+
+	struct branch b;
+	struct clk c;
+};
+
+static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
+{
+	return container_of(clk, struct cdiv_clk, c);
+}
+
+extern struct clk_ops clk_ops_cdiv;
+
+/**
  * struct fixed_clk - fixed rate clock (used for crystal oscillators)
  * @rate: output rate
  * @c: clk
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 0a300ad..2add8f9 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2052,52 +2052,41 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 400000000,
-				.bus_freq = 4,
-				.io_fraction = 0,
-			},
-			{
-				.gpu_freq = 300000000,
-				.bus_freq = 3,
-				.io_fraction = 33,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 2,
-				.io_fraction = 100,
-			},
-			{
-				.gpu_freq = 128000000,
-				.bus_freq = 1,
-				.io_fraction = 100,
-			},
-			{
-				.gpu_freq = 27000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 400000000,
+			.bus_freq = 4,
+			.io_fraction = 0,
 		},
-		.init_level = 0,
-		.num_levels = 5,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/5,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 300000000,
+			.bus_freq = 3,
+			.io_fraction = 33,
+		},
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
+		},
+		{
+			.gpu_freq = 128000000,
+			.bus_freq = 1,
+			.io_fraction = 100,
+		},
+		{
+			.gpu_freq = 27000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
-		},
+	.init_level = 0,
+	.num_levels = 5,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/5,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp3d_bus_scale_pdata,
+	.bus_scale_table = &grp3d_bus_scale_pdata,
 #endif
-	},
-	.imem_clk_name = {
-		.clk = NULL,
-		.pclk = "mem_iface_clk",
-	},
 	.iommu_user_ctx_name = "gfx3d_user",
 	.iommu_priv_ctx_name = NULL,
 };
@@ -2128,33 +2117,25 @@
 };
 
 static struct kgsl_device_platform_data kgsl_2d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 1,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 1,
 		},
-		.init_level = 0,
-		.num_levels = 2,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/10,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			/* note: 2d clocks disabled on v1 */
-			.clk = "core_clk",
-			.pclk = "iface_clk",
-		},
+	.init_level = 0,
+	.num_levels = 2,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/10,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp2d0_bus_scale_pdata,
+	.bus_scale_table = &grp2d0_bus_scale_pdata,
 #endif
-	},
 	.iommu_user_ctx_name = "gfx2d0_2d0",
 	.iommu_priv_ctx_name = NULL,
 };
@@ -2185,32 +2166,25 @@
 };
 
 static struct kgsl_device_platform_data kgsl_2d1_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 1,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 1,
 		},
-		.init_level = 0,
-		.num_levels = 2,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/10,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
-		},
+	.init_level = 0,
+	.num_levels = 2,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/10,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp2d1_bus_scale_pdata,
+	.bus_scale_table = &grp2d1_bus_scale_pdata,
 #endif
-	},
 	.iommu_user_ctx_name = "gfx2d1_2d1",
 	.iommu_priv_ctx_name = NULL,
 };
diff --git a/arch/arm/mach-msm/devices-msm7x25.c b/arch/arm/mach-msm/devices-msm7x25.c
index d918315..71b57b4 100644
--- a/arch/arm/mach-msm/devices-msm7x25.c
+++ b/arch/arm/mach-msm/devices-msm7x25.c
@@ -31,7 +31,6 @@
 #include <asm/mach/mmc.h>
 #include <mach/msm_hsusb.h>
 #include <mach/usbdiag.h>
-#include <mach/usb_gadget_fserial.h>
 #include <mach/rpc_hsusb.h>
 
 #include "clock-pcom.h"
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 1bb9a21..0fb64dc 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -807,32 +807,22 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		/* bus_freq has been set to 160000 for power savings.
-		 * OEMs may modify the value at their discretion for performance
-		 * The appropriate maximum replacement for 160000 is:
-		 * msm7x2x_clock_data.max_axi_khz
-		 */
-		.pwrlevel = {
-			{
-				.gpu_freq = 0,
-				.bus_freq = 160000000,
-			},
-		},
-		.init_level = 0,
-		.num_levels = 1,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/5,
-	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
+	/* bus_freq has been set to 160000 for power savings.
+	* OEMs may modify the value at their discretion for performance
+	* The appropriate maximum replacement for 160000 is:
+	* msm7x2x_clock_data.max_axi_khz
+	*/
+	.pwrlevel = {
+		{
+			.gpu_freq = 0,
+			.bus_freq = 160000000,
 		},
 	},
-	.imem_clk_name = {
-		.clk = "mem_clk",
-	},
+	.init_level = 0,
+	.num_levels = 1,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/5,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
 
 struct platform_device msm_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 7008bd5..2b08098 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -588,34 +588,22 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 245760000,
-				.bus_freq = 200000000,
-			},
-			{
-				.gpu_freq = 133330000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 245760000,
+			.bus_freq = 200000000,
 		},
-		.init_level = 0,
-		.num_levels = 2,
-		.set_grp_async = set_grp_xbar_async,
-		.idle_timeout = HZ/5,
-		.nap_allowed = false,
-	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
+		{
+			.gpu_freq = 133330000,
+			.bus_freq = 0,
 		},
 	},
-	.imem_clk_name = {
-		.clk = "mem_clk",
-		.pclk = NULL,
-	},
-
+	.init_level = 0,
+	.num_levels = 2,
+	.set_grp_async = set_grp_xbar_async,
+	.idle_timeout = HZ/5,
+	.nap_allowed = false,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
 
 struct platform_device msm_kgsl_3d0 = {
@@ -631,10 +619,10 @@
 void __init msm7x25a_kgsl_3d0_init(void)
 {
 	if (cpu_is_msm7x25a() || cpu_is_msm7x25aa()) {
-		kgsl_3d0_pdata.pwr_data.pwrlevel[0].gpu_freq = 133330000;
-		kgsl_3d0_pdata.pwr_data.pwrlevel[0].bus_freq = 160000000;
-		kgsl_3d0_pdata.pwr_data.pwrlevel[1].gpu_freq = 96000000;
-		kgsl_3d0_pdata.pwr_data.pwrlevel[1].bus_freq = 0;
+		kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 133330000;
+		kgsl_3d0_pdata.pwrlevel[0].bus_freq = 160000000;
+		kgsl_3d0_pdata.pwrlevel[1].gpu_freq = 96000000;
+		kgsl_3d0_pdata.pwrlevel[1].bus_freq = 0;
 	}
 }
 
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 017eed9..41136d2 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1102,37 +1102,27 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 245760000,
-				.bus_freq = 192000000,
-			},
-			{
-				.gpu_freq = 192000000,
-				.bus_freq = 152000000,
-			},
-			{
-				.gpu_freq = 192000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 245760000,
+			.bus_freq = 192000000,
 		},
-		.init_level = 0,
-		.num_levels = 3,
-		.set_grp_async = set_grp3d_async,
-		.idle_timeout = HZ/20,
-		.nap_allowed = true,
-	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
+		{
+			.gpu_freq = 192000000,
+			.bus_freq = 152000000,
+		},
+		{
+			.gpu_freq = 192000000,
+			.bus_freq = 0,
 		},
 	},
-	.imem_clk_name = {
-		.clk = "mem_clk",
-		.pclk = NULL,
-	},
+	.init_level = 0,
+	.num_levels = 3,
+	.set_grp_async = set_grp3d_async,
+	.idle_timeout = HZ/20,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE |
+		KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
 
 struct platform_device msm_kgsl_3d0 = {
@@ -1161,26 +1151,19 @@
 };
 
 static struct kgsl_device_platform_data kgsl_2d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 0,
-				.bus_freq = 192000000,
-			},
-		},
-		.init_level = 0,
-		.num_levels = 1,
-		/* HW workaround, run Z180 SYNC @ 192 MHZ */
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/10,
-		.nap_allowed = true,
-	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
+	.pwrlevel = {
+		{
+			.gpu_freq = 0,
+			.bus_freq = 192000000,
 		},
 	},
+	.init_level = 0,
+	.num_levels = 1,
+	/* HW workaround, run Z180 SYNC @ 192 MHZ */
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/10,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 };
 
 struct platform_device msm_kgsl_2d0 = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 43c13bc..d89c9d7 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -653,52 +653,41 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 266667000,
-				.bus_freq = 4,
-				.io_fraction = 0,
-			},
-			{
-				.gpu_freq = 228571000,
-				.bus_freq = 3,
-				.io_fraction = 33,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 2,
-				.io_fraction = 100,
-			},
-			{
-				.gpu_freq = 177778000,
-				.bus_freq = 1,
-				.io_fraction = 100,
-			},
-			{
-				.gpu_freq = 27000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 266667000,
+			.bus_freq = 4,
+			.io_fraction = 0,
 		},
-		.init_level = 0,
-		.num_levels = 5,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/5,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 228571000,
+			.bus_freq = 3,
+			.io_fraction = 33,
+		},
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 2,
+			.io_fraction = 100,
+		},
+		{
+			.gpu_freq = 177778000,
+			.bus_freq = 1,
+			.io_fraction = 100,
+		},
+		{
+			.gpu_freq = 27000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
-			.pclk = "iface_clk",
-		},
+	.init_level = 0,
+	.num_levels = 5,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/5,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp3d_bus_scale_pdata,
+	.bus_scale_table = &grp3d_bus_scale_pdata,
 #endif
-	},
-	.imem_clk_name = {
-		.clk = NULL,
-		.pclk = "mem_iface_clk",
-	},
 };
 
 struct platform_device msm_kgsl_3d0 = {
@@ -727,33 +716,25 @@
 };
 
 static struct kgsl_device_platform_data kgsl_2d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 1,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 1,
 		},
-		.init_level = 0,
-		.num_levels = 2,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/10,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			/* note: 2d clocks disabled on v1 */
-			.clk = "core_clk",
-			.pclk = "iface_clk",
-		},
+	.init_level = 0,
+	.num_levels = 2,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/10,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp2d0_bus_scale_pdata,
+	.bus_scale_table = &grp2d0_bus_scale_pdata,
 #endif
-	},
 };
 
 struct platform_device msm_kgsl_2d0 = {
@@ -782,32 +763,25 @@
 };
 
 static struct kgsl_device_platform_data kgsl_2d1_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 1,
-			},
-			{
-				.gpu_freq = 200000000,
-				.bus_freq = 0,
-			},
+	.pwrlevel = {
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 1,
 		},
-		.init_level = 0,
-		.num_levels = 2,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/10,
-		.nap_allowed = true,
+		{
+			.gpu_freq = 200000000,
+			.bus_freq = 0,
+		},
 	},
-	.clk = {
-		.name = {
-			.clk = "gfx2d1_clk",
-			.pclk = "gfx2d1_pclk",
-		},
+	.init_level = 0,
+	.num_levels = 2,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/10,
+	.nap_allowed = true,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE,
 #ifdef CONFIG_MSM_BUS_SCALING
-		.bus_scale_table = &grp2d1_bus_scale_pdata,
+	.bus_scale_table = &grp2d1_bus_scale_pdata,
 #endif
-	},
 };
 
 struct platform_device msm_kgsl_2d1 = {
@@ -831,8 +805,7 @@
 	if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 1) &&
 	    (SOCINFO_VERSION_MINOR(socinfo_get_version()) == 0)) {
 		printk(KERN_WARNING "kgsl: 2D cores disabled on 8660v1\n");
-		kgsl_2d0_pdata.clk.name.clk = NULL;
-		kgsl_2d1_pdata.clk.name.clk = NULL;
+		kgsl_2d0_pdata.clk_map = 0;
 	}
 }
 
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 2367719..05efcdf 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -32,7 +32,6 @@
 #include <asm/mach/mmc.h>
 #include <mach/msm_hsusb.h>
 #include <mach/usbdiag.h>
-#include <mach/usb_gadget_fserial.h>
 #include <mach/rpc_hsusb.h>
 
 static struct resource resources_uart1[] = {
@@ -911,26 +910,17 @@
 };
 
 static struct kgsl_device_platform_data kgsl_3d0_pdata = {
-	.pwr_data = {
-		.pwrlevel = {
-			{
-				.gpu_freq = 0,
-				.bus_freq = 128000000,
-			},
-		},
-		.init_level = 0,
-		.num_levels = 1,
-		.set_grp_async = NULL,
-		.idle_timeout = HZ/5,
-	},
-	.clk = {
-		.name = {
-			.clk = "core_clk",
+	.pwrlevel = {
+		{
+			.gpu_freq = 0,
+			.bus_freq = 128000000,
 		},
 	},
-	.imem_clk_name = {
-		.clk = "mem_clk",
-	},
+	.init_level = 0,
+	.num_levels = 1,
+	.set_grp_async = NULL,
+	.idle_timeout = HZ/5,
+	.clk_map = KGSL_CLK_CORE | KGSL_CLK_MEM,
 };
 
 struct platform_device msm_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 8f57f88..40e13fa 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -93,6 +93,7 @@
 	ldr	r0, [r0]
 	mov	r1, #0
 	mcr	p15, 2, r1, c0, c0, 0 /*CCSELR*/
+	isb
 	mrc	p15, 1, r1, c0, c0, 0 /*CCSIDR*/
 	mov	r2, #1
 	and	r1, r2, r1, ASR #30 /* Check if the cache is write back */
diff --git a/include/linux/platform_data/usb_rmnet.h b/arch/arm/mach-msm/include/mach/mdm2.h
similarity index 76%
rename from include/linux/platform_data/usb_rmnet.h
rename to arch/arm/mach-msm/include/mach/mdm2.h
index 68c0db7..acfa38a 100644
--- a/include/linux/platform_data/usb_rmnet.h
+++ b/arch/arm/mach-msm/include/mach/mdm2.h
@@ -10,14 +10,12 @@
  * GNU General Public License for more details.
  */
 
+#ifndef _ARCH_ARM_MACH_MSM_MDM2_H
+#define _ARCH_ARM_MACH_MSM_MDM2_H
 
-#ifndef __LINUX_USB_GADGET_RMNET_H__
-#define __LINUX_USB_GADGET_RMNET_H__
-
-#include <linux/platform_device.h>
-
-struct usb_rmnet_pdata {
-	unsigned	num_instances;
+struct mdm_platform_data {
+	char *mdm_version;
 };
 
 #endif
+
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 3965a75..562a305 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -13,7 +13,19 @@
 #ifndef __MSM_HDMI_AUDIO_H
 #define __MSM_HDMI_AUDIO_H
 
+enum hdmi_supported_sample_rates {
+	HDMI_SAMPLE_RATE_32KHZ,
+	HDMI_SAMPLE_RATE_44_1KHZ,
+	HDMI_SAMPLE_RATE_48KHZ,
+	HDMI_SAMPLE_RATE_88_2KHZ,
+	HDMI_SAMPLE_RATE_96KHZ,
+	HDMI_SAMPLE_RATE_176_4KHZ,
+	HDMI_SAMPLE_RATE_192KHZ
+};
+
 int hdmi_audio_enable(bool on , u32 fifo_water_mark);
 int hdmi_audio_packet_enable(bool on);
+void hdmi_msm_audio_sample_rate_reset(int rate);
+int hdmi_msm_audio_get_sample_rate(void);
 
 #endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/usb_bridge.h b/arch/arm/mach-msm/include/mach/usb_bridge.h
new file mode 100644
index 0000000..2b7e754
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/usb_bridge.h
@@ -0,0 +1,122 @@
+/* Copyright (c) 2011, 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 __LINUX_USB_BRIDGE_H__
+#define __LINUX_USB_BRIDGE_H__
+
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+/* bridge device 0: DUN
+ * bridge device 1 : Tethered RMNET
+ */
+#define MAX_BRIDGE_DEVICES 2
+
+/*PID 9001*/
+#define DUN_IFACE_NUM 2
+#define TETHERED_RMNET_IFACE_NUM 3
+
+struct bridge_ops {
+	int (*send_pkt)(void *, void *, size_t actual);
+	void (*send_cbits)(void *, unsigned int);
+
+	/* flow control */
+	void (*unthrottle_tx)(void *);
+};
+
+#define TX_THROTTLED BIT(0)
+#define RX_THROTTLED BIT(1)
+
+struct bridge {
+	/* context of the gadget port using bridge driver */
+	void *ctx;
+
+	/* bridge device array index mapped to the gadget port array index.
+	 * data bridge[ch_id] <-- bridge --> gadget port[ch_id]
+	 */
+	unsigned int ch_id;
+
+	/* flow control bits */
+	unsigned long flags;
+
+	/* data/ctrl bridge callbacks */
+	struct bridge_ops ops;
+};
+
+#if defined(CONFIG_USB_QCOM_MDM_BRIDGE) ||	\
+	defined(CONFIG_USB_QCOM_MDM_BRIDGE_MODULE)
+
+/* Bridge APIs called by gadget driver */
+int ctrl_bridge_open(struct bridge *);
+void ctrl_bridge_close(unsigned int);
+int ctrl_bridge_write(unsigned int, char *, size_t);
+int ctrl_bridge_set_cbits(unsigned int, unsigned int);
+unsigned int ctrl_bridge_get_cbits_tohost(unsigned int);
+int data_bridge_open(struct bridge *brdg);
+void data_bridge_close(unsigned int);
+int data_bridge_write(unsigned int , struct sk_buff *);
+int data_bridge_unthrottle_rx(unsigned int);
+
+/* defined in control bridge */
+int ctrl_bridge_probe(struct usb_interface *, struct usb_host_endpoint *, int);
+void ctrl_bridge_disconnect(unsigned int);
+int ctrl_bridge_resume(unsigned int);
+int ctrl_bridge_suspend(unsigned int);
+
+#else
+
+static inline int __maybe_unused ctrl_bridge_open(struct bridge *brdg)
+{
+	return -ENODEV;
+}
+
+static inline void __maybe_unused ctrl_bridge_close(unsigned int id) { }
+
+static inline int __maybe_unused ctrl_bridge_write(unsigned int id,
+						char *data, size_t size)
+{
+	return -ENODEV;
+}
+
+static inline int __maybe_unused ctrl_bridge_set_cbits(unsigned int id,
+					unsigned int cbits)
+{
+	return -ENODEV;
+}
+
+static inline unsigned int __maybe_unused
+ctrl_bridge_get_cbits_tohost(unsigned int id)
+{
+	return -ENODEV;
+}
+
+static inline int __maybe_unused data_bridge_open(struct bridge *brdg)
+{
+	return -ENODEV;
+}
+
+static inline void __maybe_unused data_bridge_close(unsigned int id) { }
+
+static inline int __maybe_unused data_bridge_write(unsigned int id,
+					    struct sk_buff *skb)
+{
+	return -ENODEV;
+}
+
+static inline int __maybe_unused data_bridge_unthrottle_rx(unsigned int id)
+{
+	return -ENODEV;
+}
+
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/usb_dun_bridge.h b/arch/arm/mach-msm/include/mach/usb_dun_bridge.h
deleted file mode 100644
index b4a8eef..0000000
--- a/arch/arm/mach-msm/include/mach/usb_dun_bridge.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Copyright (c) 2011, 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 __USB_DUN_BRIDGE_H
-#define __USB_DUN_BRIDGE_H
-
-/**
- * struct dun_bridge_ops - context and callbacks for DUN bridge
- *
- * @ctxt: caller private context
- * @read_complete: called when read is completed. buf and len correspond
- *	to original passed-in values. actual length of buffer returned, or
- *	negative error value.
- * @write_complete: called when write is completed. buf and len correspond
- *	to original passed-in values. actual length of buffer returned, or
- *	negative error value.
- * @ctrl_status: asynchronous notification of control status. ctrl_bits
- *	is a bitfield of CDC ACM control status bits.
- */
-struct dun_bridge_ops {
-	void *ctxt;
-	void (*read_complete)(void *ctxt, char *buf, size_t len, size_t actual);
-	void (*write_complete)(void *ctxt, char *buf,
-				size_t len, size_t actual);
-	void (*ctrl_status)(void *ctxt, unsigned int ctrl_bits);
-};
-
-#ifdef CONFIG_USB_QCOM_DUN_BRIDGE
-
-/**
- * dun_bridge_open - Open the DUN bridge
- *
- * @ops: pointer to ops struct containing private context and callback
- *	pointers
- */
-int dun_bridge_open(struct dun_bridge_ops *ops);
-
-/**
- * dun_bridge_close - Closes the DUN bridge
- */
-int dun_bridge_close(void);
-
-/**
- * dun_bridge_read - Request to read data from the DUN bridge. This call is
- *	asynchronous: user's read callback (ops->read_complete) will be called
- *	when data is returned.
- *
- * @data: pointer to caller-allocated buffer to fill in
- * @len: size of the buffer
- */
-int dun_bridge_read(void *data, int len);
-
-/**
- * dun_bridge_write - Request to write data to the DUN bridge. This call is
- *	asynchronous: user's write callback (ops->write_complete) will be called
- *	upon completion of the write indicating status and number of bytes
- *	written.
- *
- * @data: pointer to caller-allocated buffer to write
- * @len: length of the data in buffer
- */
-int dun_bridge_write(void *data, int len);
-
-/**
- * dun_bridge_send_ctrl_bits - Request to write line control data to the DUN
- *	bridge.  This call is asynchronous, however no callback will be issued
- *	upon completion.
- *
- * @ctrl_bits: CDC ACM line control bits
- */
-int dun_bridge_send_ctrl_bits(unsigned ctrl_bits);
-
-#else
-
-#include <linux/errno.h>
-
-static int __maybe_unused dun_bridge_open(struct dun_bridge_ops *ops)
-{
-	return -ENODEV;
-}
-
-static int __maybe_unused dun_bridge_close(void)
-{
-	return -ENODEV;
-}
-
-static int __maybe_unused dun_bridge_read(void *data, int len)
-{
-	return -ENODEV;
-}
-
-static int __maybe_unused dun_bridge_write(void *data, int len)
-{
-	return -ENODEV;
-}
-
-static int __maybe_unused dun_bridge_send_ctrl_bits(unsigned ctrl_bits)
-{
-	return -ENODEV;
-}
-
-#endif
-
-#endif
diff --git a/arch/arm/mach-msm/include/mach/usb_gadget_fserial.h b/arch/arm/mach-msm/include/mach/usb_gadget_fserial.h
deleted file mode 100644
index 4112885..0000000
--- a/arch/arm/mach-msm/include/mach/usb_gadget_fserial.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (c) 2011, 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 __LINUX_USB_GADGET_FSERIAL_H__
-#define __LINUX_USB_GADGET_FSERIAL_H__
-
-#include <linux/platform_device.h>
-
-enum transport_type {
-	USB_GADGET_FSERIAL_TRANSPORT_TTY,
-	USB_GADGET_FSERIAL_TRANSPORT_SDIO,
-	USB_GADGET_FSERIAL_TRANSPORT_SMD,
-};
-
-#define GSERIAL_NO_PORTS 2
-#endif
diff --git a/arch/arm/mach-msm/include/mach/usb_gadget_xport.h b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
new file mode 100644
index 0000000..54566dc
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/usb_gadget_xport.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2011, 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 __LINUX_USB_GADGET_XPORT_H__
+#define __LINUX_USB_GADGET_XPORT_H__
+
+enum transport_type {
+	USB_GADGET_XPORT_UNDEF,
+	USB_GADGET_XPORT_TTY,
+	USB_GADGET_XPORT_SDIO,
+	USB_GADGET_XPORT_SMD,
+	USB_GADGET_XPORT_BAM,
+	USB_GADGET_XPORT_HSIC,
+	USB_GADGET_XPORT_NONE,
+};
+
+#define XPORT_STR_LEN	10
+
+static char *xport_to_str(enum transport_type t)
+{
+	switch (t) {
+	case USB_GADGET_XPORT_TTY:
+		return "TTY";
+	case USB_GADGET_XPORT_SDIO:
+		return "SDIO";
+	case USB_GADGET_XPORT_SMD:
+		return "SMD";
+	case USB_GADGET_XPORT_BAM:
+		return "BAM";
+	case USB_GADGET_XPORT_HSIC:
+		return "HSIC";
+	case USB_GADGET_XPORT_NONE:
+		return "NONE";
+	default:
+		return "UNDEFINED";
+	}
+}
+
+static enum transport_type str_to_xport(const char *name)
+{
+	if (!strncasecmp("TTY", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_TTY;
+	if (!strncasecmp("SDIO", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_SDIO;
+	if (!strncasecmp("SMD", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_SMD;
+	if (!strncasecmp("BAM", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_BAM;
+	if (!strncasecmp("HSIC", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_HSIC;
+	if (!strncasecmp("", name, XPORT_STR_LEN))
+		return USB_GADGET_XPORT_NONE;
+
+	return USB_GADGET_XPORT_UNDEF;
+}
+
+enum gadget_type {
+	USB_GADGET_SERIAL,
+	USB_GADGET_RMNET,
+};
+
+#define NUM_RMNET_HSIC_PORTS 1
+#define NUM_DUN_HSIC_PORTS 1
+#define NUM_PORTS (NUM_RMNET_HSIC_PORTS \
+	+ NUM_DUN_HSIC_PORTS)
+
+int ghsic_ctrl_connect(void *, int);
+void ghsic_ctrl_disconnect(void *, int);
+int ghsic_ctrl_setup(unsigned int, enum gadget_type);
+int ghsic_data_connect(void *, int);
+void ghsic_data_disconnect(void *, int);
+int ghsic_data_setup(unsigned int, enum gadget_type);
+
+#endif
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
new file mode 100644
index 0000000..0737a81
--- /dev/null
+++ b/arch/arm/mach-msm/mdm2.c
@@ -0,0 +1,176 @@
+/* Copyright (c) 2011, 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/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/debugfs.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/mfd/pmic8058.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <mach/mdm2.h>
+#include <mach/restart.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <linux/msm_charm.h>
+#include "msm_watchdog.h"
+#include "devices.h"
+#include "clock.h"
+#include "mdm_private.h"
+
+#define MDM_MODEM_TIMEOUT	6000
+#define MDM_HOLD_TIME		4000
+#define MDM_MODEM_DELTA		100
+#define IFLINE_UP			1
+#define IFLINE_DOWN			0
+
+static int mdm_debug_on;
+static int ifline_status = IFLINE_UP;
+static struct mdm_callbacks mdm_cb;
+
+#define MDM_DBG(...)	do { if (mdm_debug_on) \
+					pr_info(__VA_ARGS__); \
+			} while (0);
+
+static void power_on_mdm(struct mdm_modem_drv *mdm_drv)
+{
+	/* Remove hsic driver before powering on the modem. */
+	if (ifline_status == IFLINE_UP) {
+		MDM_DBG("%s: Removing hsic device\n", __func__);
+		platform_device_del(&msm_device_hsic_host);
+		ifline_status = IFLINE_DOWN;
+	}
+
+	/* Pull both ERR_FATAL and RESET low */
+	MDM_DBG("Pulling PWR and RESET gpio's low\n");
+	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
+	/* Wait for them to settle. */
+	usleep(1000);
+
+	/* Deassert RESET first and wait for ir to settle. */
+	MDM_DBG("%s: Pulling RESET gpio high\n", __func__);
+	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
+	usleep(1000);
+
+	/* Pull PWR gpio high and wait for it to settle. */
+	MDM_DBG("%s: Powering on mdm modem\n", __func__);
+	gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+	usleep(1000);
+
+	/* Add back hsic device after modem power up */
+	MDM_DBG("%s: Adding hsic device\n", __func__);
+	platform_device_add(&msm_device_hsic_host);
+	ifline_status = IFLINE_UP;
+
+	msleep(200);
+}
+
+static void power_down_mdm(struct mdm_modem_drv *mdm_drv)
+{
+	int i;
+
+	for (i = MDM_MODEM_TIMEOUT; i > 0; i -= MDM_MODEM_DELTA) {
+		pet_watchdog();
+		msleep(MDM_MODEM_DELTA);
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			break;
+	}
+
+	if (i <= 0) {
+		pr_err("%s: MDM2AP_STATUS never went low.\n",
+			 __func__);
+		gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 0);
+
+		for (i = MDM_HOLD_TIME; i > 0; i -= MDM_MODEM_DELTA) {
+			pet_watchdog();
+			msleep(MDM_MODEM_DELTA);
+		}
+	}
+	/* Also remove the hsic device on 9k power down. */
+	MDM_DBG("%s: Removing hsic device\n", __func__);
+	if (ifline_status == IFLINE_UP) {
+		platform_device_del(&msm_device_hsic_host);
+		ifline_status = IFLINE_DOWN;
+	}
+}
+
+static void normal_boot_done(struct mdm_modem_drv *mdm_drv)
+{
+}
+
+static void debug_state_changed(int value)
+{
+	mdm_debug_on = value;
+}
+
+static int __init mdm_modem_probe(struct platform_device *pdev)
+{
+	/* Instantiate driver object. */
+	mdm_cb.power_on_mdm_cb = power_on_mdm;
+	mdm_cb.power_down_mdm_cb = power_down_mdm;
+	mdm_cb.normal_boot_done_cb = normal_boot_done;
+	mdm_cb.debug_state_changed_cb = debug_state_changed;
+	return mdm_common_create(pdev, &mdm_cb);
+}
+
+static int __devexit mdm_modem_remove(struct platform_device *pdev)
+{
+	return mdm_common_modem_remove(pdev);
+}
+
+static void mdm_modem_shutdown(struct platform_device *pdev)
+{
+	mdm_common_modem_shutdown(pdev);
+}
+
+static struct platform_driver mdm_modem_driver = {
+	.remove         = mdm_modem_remove,
+	.shutdown	= mdm_modem_shutdown,
+	.driver         = {
+		.name = "mdm2_modem",
+		.owner = THIS_MODULE
+	},
+};
+
+static int __init mdm_modem_init(void)
+{
+	return platform_driver_probe(&mdm_modem_driver, mdm_modem_probe);
+}
+
+static void __exit mdm_modem_exit(void)
+{
+	platform_driver_unregister(&mdm_modem_driver);
+}
+
+module_init(mdm_modem_init);
+module_exit(mdm_modem_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("mdm modem driver");
+MODULE_VERSION("2.0");
+MODULE_ALIAS("mdm_modem");
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
new file mode 100644
index 0000000..1262ce3
--- /dev/null
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -0,0 +1,505 @@
+/* Copyright (c) 2011, 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/platform_device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/ioctl.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/debugfs.h>
+#include <linux/completion.h>
+#include <linux/workqueue.h>
+#include <linux/clk.h>
+#include <linux/mfd/pmic8058.h>
+#include <asm/mach-types.h>
+#include <asm/uaccess.h>
+#include <mach/mdm2.h>
+#include <mach/restart.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <linux/msm_charm.h>
+#include "msm_watchdog.h"
+#include "mdm_private.h"
+
+#define MDM_MODEM_TIMEOUT	6000
+#define MDM_MODEM_DELTA	100
+
+static int mdm_debug_on;
+static struct workqueue_struct *mdm_queue;
+
+#define EXTERNAL_MODEM "external_modem"
+
+#define MDM_DBG(...)	do { if (mdm_debug_on) \
+					pr_info(__VA_ARGS__); \
+			} while (0);
+
+static struct mdm_modem_drv *mdm_drv;
+
+DECLARE_COMPLETION(mdm_needs_reload);
+DECLARE_COMPLETION(mdm_boot);
+DECLARE_COMPLETION(mdm_ram_dumps);
+
+static int first_boot = 1;
+
+long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
+				unsigned long arg)
+{
+	int status, ret = 0;
+
+	if (_IOC_TYPE(cmd) != CHARM_CODE) {
+		pr_err("%s: invalid ioctl code\n", __func__);
+		return -EINVAL;
+	}
+
+	MDM_DBG("%s: Entering ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+	switch (cmd) {
+	case WAKE_CHARM:
+		MDM_DBG("%s: Powering on\n", __func__);
+		mdm_drv->power_on_mdm_cb(mdm_drv);
+		break;
+	case CHECK_FOR_BOOT:
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			put_user(1, (unsigned long __user *) arg);
+		else
+			put_user(0, (unsigned long __user *) arg);
+		break;
+	case NORMAL_BOOT_DONE:
+		MDM_DBG("%s: check if mdm is booted up\n", __func__);
+		get_user(status, (unsigned long __user *) arg);
+		if (status)
+			mdm_drv->mdm_boot_status = -EIO;
+		else
+			mdm_drv->mdm_boot_status = 0;
+		mdm_drv->mdm_ready = 1;
+
+		if (mdm_drv->normal_boot_done_cb != NULL)
+			mdm_drv->normal_boot_done_cb(mdm_drv);
+
+		if (!first_boot)
+			complete(&mdm_boot);
+		else
+			first_boot = 0;
+		break;
+	case RAM_DUMP_DONE:
+		MDM_DBG("%s: mdm done collecting RAM dumps\n", __func__);
+		get_user(status, (unsigned long __user *) arg);
+		if (status)
+			mdm_drv->mdm_ram_dump_status = -EIO;
+		else
+			mdm_drv->mdm_ram_dump_status = 0;
+		complete(&mdm_ram_dumps);
+		break;
+	case WAIT_FOR_RESTART:
+		MDM_DBG("%s: wait for mdm to need images reloaded\n",
+				__func__);
+		ret = wait_for_completion_interruptible(&mdm_needs_reload);
+		if (!ret)
+			put_user(mdm_drv->boot_type,
+					 (unsigned long __user *) arg);
+		INIT_COMPLETION(mdm_needs_reload);
+		break;
+	default:
+		pr_err("%s: invalid ioctl cmd = %d\n", __func__, _IOC_NR(cmd));
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static void mdm_fatal_fn(struct work_struct *work)
+{
+	MDM_DBG("%s: Reseting the mdm due to an errfatal\n", __func__);
+	subsystem_restart(EXTERNAL_MODEM);
+}
+
+static DECLARE_WORK(mdm_fatal_work, mdm_fatal_fn);
+
+static void mdm_status_fn(struct work_struct *work)
+{
+	MDM_DBG("%s: Reseting the mdm because status changed\n", __func__);
+	subsystem_restart(EXTERNAL_MODEM);
+}
+
+static DECLARE_WORK(mdm_status_work, mdm_status_fn);
+
+static void mdm_disable_irqs(void)
+{
+	disable_irq_nosync(mdm_drv->mdm_errfatal_irq);
+	disable_irq_nosync(mdm_drv->mdm_status_irq);
+
+}
+
+static irqreturn_t mdm_errfatal(int irq, void *dev_id)
+{
+	MDM_DBG("%s: mdm got errfatal interrupt\n", __func__);
+	if (mdm_drv->mdm_ready &&
+		(gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1)) {
+		MDM_DBG("%s: scheduling work now\n", __func__);
+		queue_work(mdm_queue, &mdm_fatal_work);
+	}
+	return IRQ_HANDLED;
+}
+
+static int mdm_modem_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static const struct file_operations mdm_modem_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mdm_modem_open,
+	.unlocked_ioctl	= mdm_modem_ioctl,
+};
+
+
+static struct miscdevice mdm_modem_misc = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "mdm",
+	.fops	= &mdm_modem_fops
+};
+
+static int mdm_panic_prep(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	int i;
+
+	MDM_DBG("%s: setting AP2MDM_ERRFATAL high for a non graceful reset\n",
+			 __func__);
+	mdm_disable_irqs();
+	gpio_set_value(mdm_drv->ap2mdm_errfatal_gpio, 1);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
+
+	for (i = MDM_MODEM_TIMEOUT; i > 0; i -= MDM_MODEM_DELTA) {
+		pet_watchdog();
+		mdelay(MDM_MODEM_DELTA);
+		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+			break;
+	}
+	if (i <= 0)
+		pr_err("%s: MDM2AP_STATUS never went low\n", __func__);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mdm_panic_blk = {
+	.notifier_call  = mdm_panic_prep,
+};
+
+static irqreturn_t mdm_status_change(int irq, void *dev_id)
+{
+	MDM_DBG("%s: mdm sent status change interrupt\n", __func__);
+	if ((gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
+		 && mdm_drv->mdm_ready) {
+		MDM_DBG("%s: scheduling work now\n", __func__);
+		queue_work(mdm_queue, &mdm_status_work);
+	} else if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 1) {
+		MDM_DBG("%s: mdm is now ready\n", __func__);
+	}
+	return IRQ_HANDLED;
+}
+
+static int mdm_subsys_shutdown(const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->mdm_ready = 0;
+	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
+	mdm_drv->power_down_mdm_cb(mdm_drv);
+	return 0;
+}
+
+static int mdm_subsys_powerup(const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->power_on_mdm_cb(mdm_drv);
+	mdm_drv->boot_type = CHARM_NORMAL_BOOT;
+	complete(&mdm_needs_reload);
+	wait_for_completion(&mdm_boot);
+	pr_info("%s: mdm modem has been restarted\n", __func__);
+	INIT_COMPLETION(mdm_boot);
+	return mdm_drv->mdm_boot_status;
+}
+
+static int mdm_subsys_ramdumps(int want_dumps,
+				const struct subsys_data *crashed_subsys)
+{
+	mdm_drv->mdm_ram_dump_status = 0;
+	if (want_dumps) {
+		mdm_drv->boot_type = CHARM_RAM_DUMPS;
+		complete(&mdm_needs_reload);
+		wait_for_completion(&mdm_ram_dumps);
+		INIT_COMPLETION(mdm_ram_dumps);
+		gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 1);
+		mdm_drv->power_down_mdm_cb(mdm_drv);
+	}
+	return mdm_drv->mdm_ram_dump_status;
+}
+
+static struct subsys_data mdm_subsystem = {
+	.shutdown = mdm_subsys_shutdown,
+	.ramdump = mdm_subsys_ramdumps,
+	.powerup = mdm_subsys_powerup,
+	.name = EXTERNAL_MODEM,
+};
+
+static int mdm_debug_on_set(void *data, u64 val)
+{
+	mdm_debug_on = val;
+	if (mdm_drv->debug_state_changed_cb)
+		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+	return 0;
+}
+
+static int mdm_debug_on_get(void *data, u64 *val)
+{
+	*val = mdm_debug_on;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(mdm_debug_on_fops,
+			mdm_debug_on_get,
+			mdm_debug_on_set, "%llu\n");
+
+static int mdm_debugfs_init(void)
+{
+	struct dentry *dent;
+
+	dent = debugfs_create_dir("mdm_dbg", 0);
+	if (IS_ERR(dent))
+		return PTR_ERR(dent);
+
+	debugfs_create_file("debug_on", 0644, dent, NULL,
+			&mdm_debug_on_fops);
+	return 0;
+}
+
+static void mdm_modem_initialize_data(struct platform_device  *pdev,
+				struct mdm_callbacks *p_mdm_cb)
+{
+	struct resource *pres;
+
+	/* MDM2AP_ERRFATAL */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_ERRFATAL");
+	if (pres)
+		mdm_drv->mdm2ap_errfatal_gpio = pres->start;
+
+	/* AP2MDM_ERRFATAL */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_ERRFATAL");
+	if (pres)
+		mdm_drv->ap2mdm_errfatal_gpio = pres->start;
+
+	/* MDM2AP_STATUS */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_STATUS");
+	if (pres)
+		mdm_drv->mdm2ap_status_gpio = pres->start;
+
+	/* AP2MDM_STATUS */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_STATUS");
+	if (pres)
+		mdm_drv->ap2mdm_status_gpio = pres->start;
+
+	/* MDM2AP_WAKEUP */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"MDM2AP_WAKEUP");
+	if (pres)
+		mdm_drv->mdm2ap_wakeup_gpio = pres->start;
+
+	/* AP2MDM_WAKEUP */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_WAKEUP");
+	if (pres)
+		mdm_drv->ap2mdm_wakeup_gpio = pres->start;
+
+	/* AP2MDM_PMIC_RESET_N */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_PMIC_RESET_N");
+	if (pres)
+		mdm_drv->ap2mdm_pmic_reset_n_gpio = pres->start;
+
+	/* AP2MDM_KPDPWR_N */
+	pres = platform_get_resource_byname(pdev, IORESOURCE_IO,
+							"AP2MDM_KPDPWR_N");
+	if (pres)
+		mdm_drv->ap2mdm_kpdpwr_n_gpio = pres->start;
+
+	mdm_drv->boot_type                  = CHARM_NORMAL_BOOT;
+
+	mdm_drv->power_on_mdm_cb            = p_mdm_cb->power_on_mdm_cb;
+	mdm_drv->power_down_mdm_cb          = p_mdm_cb->power_down_mdm_cb;
+	mdm_drv->normal_boot_done_cb        = p_mdm_cb->normal_boot_done_cb;
+	mdm_drv->debug_state_changed_cb     = p_mdm_cb->debug_state_changed_cb;
+}
+
+int mdm_common_create(struct platform_device  *pdev,
+					  struct mdm_callbacks *p_mdm_cb)
+{
+	int ret = -1, irq;
+
+	mdm_drv = kzalloc(sizeof(struct mdm_modem_drv), GFP_KERNEL);
+	if (mdm_drv == NULL) {
+		pr_err("%s: kzalloc fail.\n", __func__);
+		goto alloc_err;
+	}
+
+	mdm_modem_initialize_data(pdev, p_mdm_cb);
+	if (mdm_drv->debug_state_changed_cb)
+		mdm_drv->debug_state_changed_cb(mdm_debug_on);
+
+	gpio_request(mdm_drv->ap2mdm_status_gpio, "AP2MDM_STATUS");
+	gpio_request(mdm_drv->ap2mdm_errfatal_gpio, "AP2MDM_ERRFATAL");
+	gpio_request(mdm_drv->ap2mdm_kpdpwr_n_gpio, "AP2MDM_KPDPWR_N");
+	gpio_request(mdm_drv->ap2mdm_pmic_reset_n_gpio, "AP2MDM_PMIC_RESET_N");
+	gpio_request(mdm_drv->mdm2ap_status_gpio, "MDM2AP_STATUS");
+	gpio_request(mdm_drv->mdm2ap_errfatal_gpio, "MDM2AP_ERRFATAL");
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_request(mdm_drv->ap2mdm_wakeup_gpio, "AP2MDM_WAKEUP");
+
+	gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
+	gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_direction_output(mdm_drv->ap2mdm_wakeup_gpio, 0);
+
+	gpio_direction_input(mdm_drv->mdm2ap_status_gpio);
+	gpio_direction_input(mdm_drv->mdm2ap_errfatal_gpio);
+
+	mdm_queue = create_singlethread_workqueue("mdm_queue");
+	if (!mdm_queue) {
+		pr_err("%s: could not create workqueue. All mdm "
+				"functionality will be disabled\n",
+			__func__);
+		ret = -ENOMEM;
+		goto fatal_err;
+	}
+
+	atomic_notifier_chain_register(&panic_notifier_list, &mdm_panic_blk);
+	mdm_debugfs_init();
+
+	/* Register subsystem handlers */
+	ssr_register_subsystem(&mdm_subsystem);
+
+	/* ERR_FATAL irq. */
+	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_errfatal_gpio);
+	if (irq < 0) {
+		pr_err("%s: could not get MDM2AP_ERRFATAL IRQ resource. "
+			"error=%d No IRQ will be generated on errfatal.",
+			__func__, irq);
+		goto errfatal_err;
+	}
+	ret = request_irq(irq, mdm_errfatal,
+		IRQF_TRIGGER_RISING , "mdm errfatal", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: MDM2AP_ERRFATAL IRQ#%d request failed with error=%d"
+			". No IRQ will be generated on errfatal.",
+			__func__, irq, ret);
+		goto errfatal_err;
+	}
+	mdm_drv->mdm_errfatal_irq = irq;
+
+errfatal_err:
+
+	/* status irq */
+	irq = MSM_GPIO_TO_INT(mdm_drv->mdm2ap_status_gpio);
+	if (irq < 0) {
+		pr_err("%s: could not get MDM2AP_STATUS IRQ resource. "
+			"error=%d No IRQ will be generated on status change.",
+			__func__, irq);
+		goto status_err;
+	}
+
+	ret = request_threaded_irq(irq, NULL, mdm_status_change,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"mdm status", NULL);
+
+	if (ret < 0) {
+		pr_err("%s: MDM2AP_STATUS IRQ#%d request failed with error=%d"
+			". No IRQ will be generated on status change.",
+			__func__, irq, ret);
+		goto status_err;
+	}
+	mdm_drv->mdm_status_irq = irq;
+
+status_err:
+	pr_info("%s: Registering mdm modem\n", __func__);
+	return misc_register(&mdm_modem_misc);
+
+fatal_err:
+	gpio_free(mdm_drv->ap2mdm_status_gpio);
+	gpio_free(mdm_drv->ap2mdm_errfatal_gpio);
+	gpio_free(mdm_drv->ap2mdm_kpdpwr_n_gpio);
+	gpio_free(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	gpio_free(mdm_drv->mdm2ap_status_gpio);
+	gpio_free(mdm_drv->mdm2ap_errfatal_gpio);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_free(mdm_drv->ap2mdm_wakeup_gpio);
+
+	kfree(mdm_drv);
+	ret = -ENODEV;
+
+alloc_err:
+	return ret;
+}
+
+int mdm_common_modem_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	gpio_free(mdm_drv->ap2mdm_status_gpio);
+	gpio_free(mdm_drv->ap2mdm_errfatal_gpio);
+	gpio_free(mdm_drv->ap2mdm_kpdpwr_n_gpio);
+	gpio_free(mdm_drv->ap2mdm_pmic_reset_n_gpio);
+	gpio_free(mdm_drv->mdm2ap_status_gpio);
+	gpio_free(mdm_drv->mdm2ap_errfatal_gpio);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_free(mdm_drv->ap2mdm_wakeup_gpio);
+
+	kfree(mdm_drv);
+
+	ret = misc_deregister(&mdm_modem_misc);
+	return ret;
+}
+
+void mdm_common_modem_shutdown(struct platform_device *pdev)
+{
+	MDM_DBG("%s: setting AP2MDM_STATUS low for a graceful restart\n",
+		__func__);
+
+	mdm_disable_irqs();
+
+	gpio_set_value(mdm_drv->ap2mdm_status_gpio, 0);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
+
+	mdm_drv->power_down_mdm_cb(mdm_drv);
+
+	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
+		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 0);
+}
+
diff --git a/arch/arm/mach-msm/mdm_private.h b/arch/arm/mach-msm/mdm_private.h
new file mode 100644
index 0000000..701eb7a
--- /dev/null
+++ b/arch/arm/mach-msm/mdm_private.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2011, 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 _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
+#define _ARCH_ARM_MACH_MSM_MDM_PRIVATE_H
+
+struct mdm_modem_drv;
+
+/* Private mdm2 data structure */
+struct mdm_modem_drv {
+	unsigned mdm2ap_errfatal_gpio;
+	unsigned ap2mdm_errfatal_gpio;
+	unsigned mdm2ap_status_gpio;
+	unsigned ap2mdm_status_gpio;
+	unsigned mdm2ap_wakeup_gpio;
+	unsigned ap2mdm_wakeup_gpio;
+	unsigned ap2mdm_pmic_reset_n_gpio;
+	unsigned ap2mdm_kpdpwr_n_gpio;
+
+	int mdm_errfatal_irq;
+	int mdm_status_irq;
+	int mdm_ready;
+	int mdm_boot_status;
+	int mdm_ram_dump_status;
+	enum charm_boot_type boot_type;
+	int mdm_debug_on;
+
+	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*debug_state_changed_cb)(int value);
+};
+
+struct mdm_callbacks {
+	void (*power_on_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*normal_boot_done_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*power_down_mdm_cb)(struct mdm_modem_drv *mdm_drv);
+	void (*debug_state_changed_cb)(int value);
+};
+
+int mdm_common_create(struct platform_device  *pdev,
+					  struct mdm_callbacks *mdm_cb);
+int mdm_common_modem_remove(struct platform_device *pdev);
+void mdm_common_modem_shutdown(struct platform_device *pdev);
+void mdm_common_set_debug_state(int value);
+
+#endif
+
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index b9d9d3b..7a75bc1 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.c
@@ -14,8 +14,11 @@
 #include <asm/setup.h>
 #include <asm/errno.h>
 #include <asm/sizes.h>
+#include <asm/pgtable.h>
 #include <linux/mutex.h>
+#include <linux/memory.h>
 #include <mach/msm_memtypes.h>
+#include <mach/socinfo.h>
 #include "smd_private.h"
 
 #if defined(CONFIG_ARCH_MSM8960)
@@ -40,6 +43,14 @@
 	STATE_DEFAULT = STATE_ACTIVE
 };
 
+enum {
+	MEM_NO_CHANGE = 0x0,
+	MEM_DEEP_POWER_DOWN,
+	MEM_SELF_REFRESH,
+};
+
+static unsigned int dmm_mode;
+
 static int default_mask = ~0x0;
 
 /* Return the number of chipselects populated with a memory bank */
@@ -103,27 +114,40 @@
 static int switch_memory_state(int id, int new_state)
 {
 	int mask;
-	int disable_masks[MAX_NR_REGIONS] = { 0xFFFFFF00, 0xFFFF00FF,
+	int power_down_masks[MAX_NR_REGIONS] = { 0xFFFFFF00, 0xFFFF00FF,
 						0xFF00FFFF, 0x00FFFFFF };
+	int self_refresh_masks[MAX_NR_REGIONS] = { 0xFFFFFFF0, 0xFFFFFF0F,
+						0xFFFFF0FF, 0xFFFF0FFF };
 	mutex_lock(&mem_regions[id].state_mutex);
 
 	if (new_state == mem_regions[id].state)
 		goto no_change;
 
-	if (new_state == STATE_POWER_DOWN)
-		mask = mem_regions[id].mask & disable_masks[id];
-	else if (new_state == STATE_ACTIVE)
-		mask = mem_regions[id].mask | (~disable_masks[id]);
+	pr_info("request memory %d state switch (%d->%d) mode %d\n", id,
+			mem_regions[id].state, new_state, dmm_mode);
+	if (new_state == STATE_POWER_DOWN) {
+		if (dmm_mode == MEM_DEEP_POWER_DOWN)
+			mask = mem_regions[id].mask & power_down_masks[id];
+		else
+			mask = mem_regions[id].mask & self_refresh_masks[id];
+	} else if (new_state == STATE_ACTIVE) {
+		if (dmm_mode == MEM_DEEP_POWER_DOWN)
+			mask = mem_regions[id].mask | (~power_down_masks[id]);
+		else
+			mask = mem_regions[id].mask | (~self_refresh_masks[id]);
+	}
 
-	/* For now we only support Deep Power Down */
-	/* So set the active and retention states as the same */
 	if (rpm_change_memory_state(mask, mask) == 0) {
 		mem_regions[id].state = new_state;
 		mem_regions[id].mask = mask;
+		pr_info("completed memory %d state switch to %d mode %d\n",
+				id, new_state, dmm_mode);
 		mutex_unlock(&mem_regions[id].state_mutex);
 		return 0;
 	}
 
+	pr_err("failed memory %d state switch (%d->%d) mode %d\n", id,
+			mem_regions[id].state, new_state, dmm_mode);
 no_change:
 	mutex_unlock(&mem_regions[id].state_mutex);
 	return -EINVAL;
@@ -189,7 +213,12 @@
 int __init meminfo_init(unsigned int type, unsigned int min_bank_size)
 {
 	unsigned int i;
+	unsigned long bank_size;
+	unsigned long bank_start;
 	struct smem_ram_ptable *ram_ptable;
+	/* physical memory banks */
+	unsigned int nr_mem_banks = 0;
+	/* logical memory regions for dmm */
 	nr_mem_regions = 0;
 
 	ram_ptable = smem_alloc(SMEM_USABLE_RAM_PARTITION_TABLE,
@@ -200,22 +229,41 @@
 		return -EINVAL;
 	}
 
+	/* Determine power control mode based on the hw version */
+	/* This check will be removed when PASR is fully supported */
+	if (cpu_is_msm8960() &&
+		SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
+		dmm_mode = MEM_DEEP_POWER_DOWN;
+	else
+		dmm_mode = MEM_SELF_REFRESH;
+
 	pr_info("meminfo_init: smem ram ptable found: ver: %d len: %d\n",
 			ram_ptable->version, ram_ptable->len);
 
 	for (i = 0; i < ram_ptable->len; i++) {
 		if (ram_ptable->parts[i].type == type &&
 			ram_ptable->parts[i].size >= min_bank_size) {
-			mem_regions[nr_mem_regions].start =
-				ram_ptable->parts[i].start;
-			mem_regions[nr_mem_regions].size =
-				ram_ptable->parts[i].size;
-			mutex_init(&mem_regions[nr_mem_regions].state_mutex);
-			mem_regions[nr_mem_regions].state = STATE_DEFAULT;
-			mem_regions[nr_mem_regions].mask = default_mask;
-			nr_mem_regions++;
+			bank_start = ram_ptable->parts[i].start;
+			bank_size = ram_ptable->parts[i].size;
+			/* Divide into logical memory regions of same size */
+			while (bank_size) {
+				mem_regions[nr_mem_regions].start =
+					bank_start;
+				mem_regions[nr_mem_regions].size =
+					MIN_MEMORY_BLOCK_SIZE;
+				mutex_init(&mem_regions[nr_mem_regions]
+							.state_mutex);
+				mem_regions[nr_mem_regions].state =
+							STATE_DEFAULT;
+				mem_regions[nr_mem_regions].mask = default_mask;
+				bank_start += MIN_MEMORY_BLOCK_SIZE;
+				bank_size -= MIN_MEMORY_BLOCK_SIZE;
+				nr_mem_regions++;
+			}
+			nr_mem_banks++;
 		}
 	}
-	pr_info("Found %d memory banks\n", nr_mem_regions);
+	pr_info("Found %d memory banks grouped into %d memory regions\n",
+			nr_mem_banks, nr_mem_regions);
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index 6becc61..bcc4c64 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index b1d2ee8..492fa0e 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -82,7 +82,8 @@
 	unsigned long subframe_pkt_addr;
 	unsigned long subframe_pkt_size;
 	unsigned short *frame_header_pkt;
-	int i, num_addr, skip, start_pos = 0, xdim_pos = 1, ydim_pos = 2;
+	int i, num_addr, col_addr = 0, skip;
+	int start_pos = 0, xdim_pos = 1, ydim_pos = 2;
 	unsigned short *frame_buffer_high, *frame_buffer_low;
 	unsigned long frame_buffer_size;
 	unsigned short frame_buffer_size_high, frame_buffer_size_low;
@@ -133,9 +134,10 @@
 		skip = 0;
 		start_pos = 5;
 	   } else {
-	       num_addr = 33;
+	       num_addr = 16;
 	       skip = 0;
 	       start_pos = 6;
+	       col_addr = 17;
 	   }
 		break;
 	case 0x8201: /* h.264 vld in arm */
@@ -216,6 +218,29 @@
 					NULL, NULL, NULL, NULL))
 			return -EINVAL;
 	}
+	if (col_addr) {
+		frame_buffer_high += 2;
+		frame_buffer_low += 2;
+		/* Patch the Co-located buffers.*/
+		frame_buffer_size =  (72 * frame_header_pkt[xdim_pos] *
+					frame_header_pkt[ydim_pos]) >> 16;
+		ptr_to_high_low_short((void *)frame_buffer_size,
+					&frame_buffer_size_high,
+					&frame_buffer_size_low);
+		for (i = 0; i < col_addr; i++) {
+			if (frame_buffer_high && frame_buffer_low) {
+				if (pmem_fixup_high_low(frame_buffer_high,
+						frame_buffer_low,
+						frame_buffer_size_high,
+						frame_buffer_size_low,
+						module,
+						NULL, NULL, NULL, NULL))
+					return -EINVAL;
+			}
+			frame_buffer_high += 2;
+			frame_buffer_low += 2;
+		}
+	}
 	/*Flush the cached pmem subframe packet before sending to DSP*/
 	if (filp) {
 		pmem_addr.vaddr = subframe_pkt_addr;
diff --git a/arch/arm/mach-msm/qdsp5v2/Makefile b/arch/arm/mach-msm/qdsp5v2/Makefile
old mode 100755
new mode 100644
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index f978554..64344ef 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -184,13 +184,18 @@
 			rc = -EFAULT;
 		}
 		break;
-	case AUDIO_SET_CONFIG:
+	case AUDIO_SET_CONFIG: {
+		/*  Setting default rate as 48khz */
+		unsigned int cur_sample_rate =
+			HDMI_SAMPLE_RATE_48KHZ;
+		struct msm_audio_config config;
+
 		pr_debug("AUDIO_SET_CONFIG\n");
-		if (copy_from_user(&lpa_if->dma_period_sz, (void *) arg,
-				sizeof(unsigned int))) {
-			pr_debug("%s:failed to copy from user\n", __func__);
+		if (copy_from_user(&config, (void *)arg, sizeof(config))) {
 			rc = -EFAULT;
+			break;
 		}
+		lpa_if->dma_period_sz = config.buffer_size;
 		if ((lpa_if->dma_period_sz * lpa_if->num_periods) >
 			DMA_ALLOC_BUF_SZ) {
 			pr_err("Dma buffer size greater than allocated size\n");
@@ -213,7 +218,40 @@
 			lpa_if->audio_buf[i].size = lpa_if->dma_period_sz;
 			lpa_if->audio_buf[i].used = 0;
 		}
+
+		pr_debug("Sample rate %d\n", config.sample_rate);
+		switch (config.sample_rate) {
+		case 48000:
+			cur_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+			break;
+		case 44100:
+			cur_sample_rate = HDMI_SAMPLE_RATE_44_1KHZ;
+			break;
+		case 32000:
+			cur_sample_rate = HDMI_SAMPLE_RATE_32KHZ;
+			break;
+		case 88200:
+			cur_sample_rate = HDMI_SAMPLE_RATE_88_2KHZ;
+			break;
+		case 96000:
+			cur_sample_rate = HDMI_SAMPLE_RATE_96KHZ;
+			break;
+		case 176400:
+			cur_sample_rate = HDMI_SAMPLE_RATE_176_4KHZ;
+			break;
+		case 192000:
+			cur_sample_rate = HDMI_SAMPLE_RATE_192KHZ;
+			break;
+		default:
+			cur_sample_rate = HDMI_SAMPLE_RATE_48KHZ;
+		}
+		if (cur_sample_rate != hdmi_msm_audio_get_sample_rate())
+			hdmi_msm_audio_sample_rate_reset(cur_sample_rate);
+		else
+			pr_debug("Previous sample rate and current"
+				"sample rate are same\n");
 		break;
+	}
 	default:
 		pr_err("UnKnown Ioctl\n");
 		rc = -EINVAL;
diff --git a/arch/arm/mach-msm/qdss-ptm.c b/arch/arm/mach-msm/qdss-ptm.c
index 0d971d7..205e2b8 100644
--- a/arch/arm/mach-msm/qdss-ptm.c
+++ b/arch/arm/mach-msm/qdss-ptm.c
@@ -357,6 +357,7 @@
 		ptm_writel(ptm, cpu, ptm.cfg.extnd_ext_input_sel, ETMEXTINSELR);
 		ptm_writel(ptm, cpu, ptm.cfg.ts_event, ETMTSEVR);
 		ptm_writel(ptm, cpu, ptm.cfg.aux_control, ETMAUXCR);
+		ptm_writel(ptm, cpu, cpu+1, ETMTRACEIDR);
 		ptm_writel(ptm, cpu, ptm.cfg.vmid_comp_value, ETMVMIDCVR);
 
 		ptm_clear_prog(cpu);
@@ -640,6 +641,7 @@
 	ptm.state[i++] = ptm_readl(ptm, cpu, ETMEXTINSELR);
 	ptm.state[i++] = ptm_readl(ptm, cpu, ETMTSEVR);
 	ptm.state[i++] = ptm_readl(ptm, cpu, ETMAUXCR);
+	ptm.state[i++] = ptm_readl(ptm, cpu, ETMTRACEIDR);
 	ptm.state[i++] = ptm_readl(ptm, cpu, ETMVMIDCVR);
 	ptm.state[i++] = ptm_readl(ptm, cpu, CS_CLAIMSET);
 	ptm.state[i++] = ptm_readl(ptm, cpu, CS_CLAIMCLR);
@@ -696,6 +698,7 @@
 	ptm_writel(ptm, cpu, ptm.state[i++], ETMEXTINSELR);
 	ptm_writel(ptm, cpu, ptm.state[i++], ETMTSEVR);
 	ptm_writel(ptm, cpu, ptm.state[i++], ETMAUXCR);
+	ptm_writel(ptm, cpu, ptm.state[i++], ETMTRACEIDR);
 	ptm_writel(ptm, cpu, ptm.state[i++], ETMVMIDCVR);
 	ptm_writel(ptm, cpu, ptm.state[i++], CS_CLAIMSET);
 	ptm_writel(ptm, cpu, ptm.state[i++], CS_CLAIMCLR);
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 6f151cb..dc6ba5c 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -98,7 +98,15 @@
 static void buf_req_retry(unsigned long param)
 {
 	struct smd_tty_info *info = (struct smd_tty_info *)param;
-	tasklet_hi_schedule(&info->tty_tsklt);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->reset_lock, flags);
+	if (info->is_open) {
+		spin_unlock_irqrestore(&info->reset_lock, flags);
+		tasklet_hi_schedule(&info->tty_tsklt);
+		return;
+	}
+	spin_unlock_irqrestore(&info->reset_lock, flags);
 }
 
 static void smd_tty_read(unsigned long param)
@@ -163,6 +171,12 @@
 
 	switch (event) {
 	case SMD_EVENT_DATA:
+		spin_lock_irqsave(&info->reset_lock, flags);
+		if (!info->is_open) {
+			spin_unlock_irqrestore(&info->reset_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(&info->reset_lock, flags);
 		/* There may be clients (tty framework) that are blocked
 		 * waiting for space to write data, so if a possible read
 		 * interrupt came in wake anyone waiting and disable the
@@ -323,12 +337,16 @@
 static void smd_tty_close(struct tty_struct *tty, struct file *f)
 {
 	struct smd_tty_info *info = tty->driver_data;
+	unsigned long flags;
 
 	if (info == 0)
 		return;
 
 	mutex_lock(&smd_tty_lock);
 	if (--info->open_count == 0) {
+		spin_lock_irqsave(&info->reset_lock, flags);
+		info->is_open = 0;
+		spin_unlock_irqrestore(&info->reset_lock, flags);
 		if (info->tty) {
 			tasklet_kill(&info->tty_tsklt);
 			wake_lock_destroy(&info->wake_lock);
@@ -386,8 +404,15 @@
 static void smd_tty_unthrottle(struct tty_struct *tty)
 {
 	struct smd_tty_info *info = tty->driver_data;
-	tasklet_hi_schedule(&info->tty_tsklt);
-	return;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->reset_lock, flags);
+	if (info->is_open) {
+		spin_unlock_irqrestore(&info->reset_lock, flags);
+		tasklet_hi_schedule(&info->tty_tsklt);
+		return;
+	}
+	spin_unlock_irqrestore(&info->reset_lock, flags);
 }
 
 /*
@@ -542,8 +567,6 @@
 	 * Only register the platform driver for targets older than that.
 	 */
 	if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() ||
-			cpu_is_msm7x27a() || cpu_is_msm7x27aa() ||
-			cpu_is_msm7x25a() || cpu_is_msm7x25aa() ||
 			cpu_is_msm7x30() || cpu_is_qsd8x50() ||
 			cpu_is_msm8x55() ||  (cpu_is_msm8x60() &&
 			socinfo_get_platform_subtype() == 0x1)) {
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
index db9ab30..b5ff244 100644
--- a/arch/arm/mach-msm/subsystem_map.c
+++ b/arch/arm/mach-msm/subsystem_map.c
@@ -440,6 +440,9 @@
 	int i, j, ret;
 	unsigned long temp_va;
 
+	if (IS_ERR_OR_NULL(buf))
+		goto out;
+
 	if (buf->vaddr)
 		node = find_buffer(buf->vaddr);
 	else
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9beef12..84a7e5c 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -796,14 +796,9 @@
 	int i, j, highmem = 0;
 
 #if (defined CONFIG_HIGHMEM) && (defined CONFIG_FIX_MOVABLE_ZONE)
-
-/* For now, we must ensure that a small highmem zone exists
- * after most of it is transformed into the movable zone.
- */
-#define MIN_HIGHMEM_SIZE (5 * SECTION_SIZE)
 	void *v_movable_start;
 
-	v_movable_start = __va(movable_reserved_start) - MIN_HIGHMEM_SIZE;
+	v_movable_start = __va(movable_reserved_start);
 
 	if (vmalloc_min > v_movable_start)
 		vmalloc_min = v_movable_start;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index cac5c81..58c9b9a 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -43,7 +43,7 @@
 unsigned char diag_debug_buf[1024];
 static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
 struct diag_master_table entry;
-
+smd_channel_t *ch_temp;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
 
@@ -1149,8 +1149,12 @@
 	if (event == SMD_EVENT_CLOSE) {
 		pr_info("diag: clean modem registration\n");
 		diag_clear_reg(MODEM_PROC);
-	} else
-		queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
+		driver->ch = 0;
+		return;
+	} else if (event == SMD_EVENT_OPEN) {
+		driver->ch = ch_temp;
+	}
+	queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
 }
 
 #if defined(CONFIG_MSM_N_WAY_SMD)
@@ -1169,8 +1173,10 @@
 {
 	int r = 0;
 
-	if (pdev->id == SMD_APPS_MODEM)
+	if (pdev->id == SMD_APPS_MODEM) {
 		r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
+		ch_temp = driver->ch;
+	}
 #if defined(CONFIG_MSM_N_WAY_SMD)
 	if (pdev->id == SMD_APPS_QDSP)
 		r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 50420ba..48dc9c0 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1170,6 +1170,8 @@
 	{
 		struct ion_flush_data data;
 		unsigned long start, end;
+		struct ion_handle *handle = NULL;
+		int ret;
 
 		if (copy_from_user(&data, (void __user *)arg,
 				sizeof(struct ion_flush_data)))
@@ -1184,8 +1186,24 @@
 			return -EINVAL;
 		}
 
-		return ion_do_cache_op(client, data.handle, data.vaddr,
-					data.offset, data.length, cmd);
+		if (!data.handle) {
+			handle = ion_import_fd(client, data.fd);
+			if (IS_ERR_OR_NULL(handle)) {
+				pr_info("%s: Could not import handle: %d\n",
+					__func__, (int)handle);
+				return -EINVAL;
+			}
+		}
+
+		ret = ion_do_cache_op(client,
+					data.handle ? data.handle : handle,
+					data.vaddr, data.offset, data.length,
+					cmd);
+
+		if (!data.handle)
+			ion_free(client, handle);
+
+		break;
 
 	}
 	case ION_IOC_GET_FLAGS:
diff --git a/drivers/gpu/msm/a2xx_reg.h b/drivers/gpu/msm/a2xx_reg.h
index d859d61..5ffdea1 100644
--- a/drivers/gpu/msm/a2xx_reg.h
+++ b/drivers/gpu/msm/a2xx_reg.h
@@ -413,6 +413,7 @@
 #define REG_A225_RB_COLOR_INFO3          0x2005
 #define REG_A225_PC_MULTI_PRIM_IB_RESET_INDX 0x2103
 #define REG_A225_GRAS_UCP0X              0x2340
+#define REG_A225_GRAS_UCP5W              0x2357
 #define REG_A225_GRAS_UCP_ENABLED        0x2360
 
 #endif /* __A200_REG_H */
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d485cd2..23ecfb3 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -93,7 +93,6 @@
 		.pwrctrl = {
 			.regulator_name = "fs_gfx3d",
 			.irq_name = KGSL_3D0_IRQ,
-			.src_clk_name = "src_clk",
 		},
 		.mutex = __MUTEX_INITIALIZER(device_3d0.dev.mutex),
 		.state = KGSL_STATE_INIT,
@@ -1133,9 +1132,14 @@
 			mutex_lock(&device->mutex);
 
 			if (status > 0) {
+				/*completed before the wait finished */
 				status = 0;
 				goto done;
+			} else if (status < 0) {
+				/*an error occurred*/
+				goto done;
 			}
+			/*this wait timed out*/
 		}
 	}
 	if (!kgsl_check_timestamp(device, timestamp)) {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 6003846..7b27f61 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -408,7 +408,8 @@
 	REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
 	REG_A220_PC_VERTEX_REUSE_BLOCK_CNTL,
 	REG_RB_COPY_CONTROL, REG_RB_DEPTH_CLEAR,
-	REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP_ENABLED
+	REG_A225_GRAS_UCP0X, REG_A225_GRAS_UCP5W,
+	REG_A225_GRAS_UCP_ENABLED, REG_A225_GRAS_UCP_ENABLED
 };
 
 
@@ -1322,6 +1323,7 @@
 			struct adreno_context *context)
 {
 	struct kgsl_device *device = &adreno_dev->dev;
+	unsigned int cmd[22];
 
 	if (context == NULL)
 		return;
@@ -1363,6 +1365,30 @@
 			context->chicken_restore, 3);
 
 		context->flags |= CTXT_FLAGS_GMEM_RESTORE;
+	} else if (adreno_is_a225(adreno_dev)) {
+		unsigned int *cmds = &cmd[0];
+		/*
+		 * Issue an empty draw call to avoid possible hangs due to
+		 * repeated idles without intervening draw calls.
+		 * On adreno 225 the PC block has a cache that is only
+		 * flushed on draw calls and repeated idles can make it
+		 * overflow. The gmem save path contains draw calls so
+		 * this workaround isn't needed there.
+		 */
+		*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+		*cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
+		*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
+		*cmds++ = 0;
+		*cmds++ = 1<<14;
+		*cmds++ = 0;
+		*cmds++ = device->mmu.setstate_memory.gpuaddr;
+		*cmds++ = 0;
+		*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+		*cmds++ = 0x00000000;
+
+		adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+					    &cmd[0], 11);
 	}
 }
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 7034fd8..dd7b1d6 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -27,6 +27,34 @@
 #define UPDATE_BUSY_VAL		1000000
 #define UPDATE_BUSY		50
 
+struct clk_pair {
+	const char *name;
+	uint map;
+};
+
+struct clk_pair clks[KGSL_MAX_CLKS] = {
+	{
+		.name = "src_clk",
+		.map = KGSL_CLK_SRC,
+	},
+	{
+		.name = "core_clk",
+		.map = KGSL_CLK_CORE,
+	},
+	{
+		.name = "iface_clk",
+		.map = KGSL_CLK_IFACE,
+	},
+	{
+		.name = "mem_clk",
+		.map = KGSL_CLK_MEM,
+	},
+	{
+		.name = "mem_iface_clk",
+		.map = KGSL_CLK_MEM_IFACE,
+	},
+};
+
 void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
 				unsigned int new_level)
 {
@@ -434,49 +462,43 @@
 	struct platform_device *pdev =
 		container_of(device->parentdev, struct platform_device, dev);
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-	struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
-	struct kgsl_device_pwr_data *pdata_pwr = &pdata_dev->pwr_data;
-	const char *clk_names[KGSL_MAX_CLKS] = {pwr->src_clk_name,
-						pdata_dev->clk.name.clk,
-						pdata_dev->clk.name.pclk,
-						pdata_dev->imem_clk_name.clk,
-						pdata_dev->imem_clk_name.pclk};
+	struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
 
 	/*acquire clocks */
-	for (i = 1; i < KGSL_MAX_CLKS; i++) {
-		if (clk_names[i]) {
-			clk = clk_get(&pdev->dev, clk_names[i]);
+	for (i = 0; i < KGSL_MAX_CLKS; i++) {
+		if (pdata->clk_map & clks[i].map) {
+			clk = clk_get(&pdev->dev, clks[i].name);
 			if (IS_ERR(clk))
 				goto clk_err;
 			pwr->grp_clks[i] = clk;
 		}
 	}
 	/* Make sure we have a source clk for freq setting */
-	clk = clk_get(&pdev->dev, clk_names[0]);
-	pwr->grp_clks[0] = (IS_ERR(clk)) ? pwr->grp_clks[1] : clk;
+	if (pwr->grp_clks[0] == NULL)
+		pwr->grp_clks[0] = pwr->grp_clks[1];
 
 	/* put the AXI bus into asynchronous mode with the graphics cores */
-	if (pdata_pwr->set_grp_async != NULL)
-		pdata_pwr->set_grp_async();
+	if (pdata->set_grp_async != NULL)
+		pdata->set_grp_async();
 
-	if (pdata_pwr->num_levels > KGSL_MAX_PWRLEVELS) {
+	if (pdata->num_levels > KGSL_MAX_PWRLEVELS) {
 		KGSL_PWR_ERR(device, "invalid power level count: %d\n",
-					 pdata_pwr->num_levels);
+					 pdata->num_levels);
 		result = -EINVAL;
 		goto done;
 	}
-	pwr->num_pwrlevels = pdata_pwr->num_levels;
-	pwr->active_pwrlevel = pdata_pwr->init_level;
-	for (i = 0; i < pdata_pwr->num_levels; i++) {
+	pwr->num_pwrlevels = pdata->num_levels;
+	pwr->active_pwrlevel = pdata->init_level;
+	for (i = 0; i < pdata->num_levels; i++) {
 		pwr->pwrlevels[i].gpu_freq =
-		(pdata_pwr->pwrlevel[i].gpu_freq > 0) ?
+		(pdata->pwrlevel[i].gpu_freq > 0) ?
 		clk_round_rate(pwr->grp_clks[0],
-					   pdata_pwr->pwrlevel[i].
+					   pdata->pwrlevel[i].
 					   gpu_freq) : 0;
 		pwr->pwrlevels[i].bus_freq =
-			pdata_pwr->pwrlevel[i].bus_freq;
+			pdata->pwrlevel[i].bus_freq;
 		pwr->pwrlevels[i].io_fraction =
-			pdata_pwr->pwrlevel[i].io_fraction;
+			pdata->pwrlevel[i].io_fraction;
 	}
 	/* Do not set_rate for targets in sync with AXI */
 	if (pwr->pwrlevels[0].gpu_freq > 0)
@@ -489,8 +511,8 @@
 
 	pwr->power_flags = 0;
 
-	pwr->nap_allowed = pdata_pwr->nap_allowed;
-	pwr->interval_timeout = pdata_pwr->idle_timeout;
+	pwr->nap_allowed = pdata->nap_allowed;
+	pwr->interval_timeout = pdata->idle_timeout;
 	pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(pwr->ebi1_clk))
 		pwr->ebi1_clk = NULL;
@@ -498,15 +520,14 @@
 		clk_set_rate(pwr->ebi1_clk,
 					 pwr->pwrlevels[pwr->active_pwrlevel].
 						bus_freq);
-	if (pdata_dev->clk.bus_scale_table != NULL) {
-		pwr->pcl =
-			msm_bus_scale_register_client(pdata_dev->clk.
+	if (pdata->bus_scale_table != NULL) {
+		pwr->pcl = msm_bus_scale_register_client(pdata->
 							bus_scale_table);
 		if (!pwr->pcl) {
 			KGSL_PWR_ERR(device,
 					"msm_bus_scale_register_client failed: "
 					"id %d table %p", device->id,
-					pdata_dev->clk.bus_scale_table);
+					pdata->bus_scale_table);
 			result = -EINVAL;
 			goto done;
 		}
@@ -529,7 +550,7 @@
 clk_err:
 	result = PTR_ERR(clk);
 	KGSL_PWR_ERR(device, "clk_get(%s) failed: %d\n",
-				 clk_names[i], result);
+				 clks[i].name, result);
 
 done:
 	return result;
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 9bf3c0f..8b33fcd 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -52,7 +52,6 @@
 	unsigned int nap_allowed;
 	const char *regulator_name;
 	const char *irq_name;
-	const char *src_clk_name;
 	s64 time;
 	struct kgsl_busy busy;
 	unsigned int restore_slumber;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f3cd0ad..92fd1d78 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -788,18 +788,9 @@
 	  internally uses an array of LTC2499 and EPM ADCs in a differential
 	  configuration to provide a flat set of channels that can be addressed.
 
-config SENSORS_PM8921_ADC
-	tristate "Support for Qualcomm PM8921 ADC"
-	depends on MFD_PM8921_CORE
-	help
-	  This is the ADC arbiter driver for Qualcomm PM8921 Chip.
-
-	  The driver supports reading the HKADC, XOADC and support to set and receive
-	  temperature threshold notifications using the Battery temperature module.
-
 config SENSORS_PM8XXX_ADC
 	tristate "Support for Qualcomm PM8XXX ADC"
-	depends on MFD_PM8018_CORE
+	depends on MFD_PM8018_CORE || MFD_PM8921_CORE
 	help
 	  This is the ADC arbiter driver for Qualcomm PM8XXX Chip.
 
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 10d0699..137f469 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -120,7 +120,6 @@
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 obj-$(CONFIG_SENSORS_WPCE775X)	+= wpce775x.o
 obj-$(CONFIG_SENSORS_MSM_ADC)	+= msm_adc.o m_adcproc.o
-obj-$(CONFIG_SENSORS_PM8921_ADC)	+= pm8921-adc.o msmproc_adc.o
 obj-$(CONFIG_SENSORS_PM8XXX_ADC)	+= pm8xxx-adc.o pm8xxx-adc-scale.o
 
 # PMBus drivers
diff --git a/drivers/hwmon/msmproc_adc.c b/drivers/hwmon/msmproc_adc.c
deleted file mode 100644
index fa6949e..0000000
--- a/drivers/hwmon/msmproc_adc.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- * Copyright (c) 2011, 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/err.h>
-#include <linux/module.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
-#define KELVINMIL_DEGMIL	273160
-
-static const struct pm8921_adc_map_pt adcmap_batttherm[] = {
-	{41001,	-30},
-	{40017,	-20},
-	{38721,	-10},
-	{37186,	  0},
-	{35554,	 10},
-	{33980,	 20},
-	{33253,	 25},
-	{32580,	 30},
-	{31412,	 40},
-	{30481,	 50},
-	{29759,	 60},
-	{29209,	 70},
-	{28794,	 80}
-};
-
-static const struct pm8921_adc_map_pt adcmap_btm_threshold[] = {
-	{-30,	1642},
-	{-20,	1544},
-	{-10,	1414},
-	{0,	1260},
-	{1,	1244},
-	{2,	1228},
-	{3,	1212},
-	{4,	1195},
-	{5,	1179},
-	{6,	1162},
-	{7,	1146},
-	{8,	1129},
-	{9,	1113},
-	{10,	1097},
-	{11,	1080},
-	{12,	1064},
-	{13,	1048},
-	{14,	1032},
-	{15,	1016},
-	{16,	1000},
-	{17,	985},
-	{18,	969},
-	{19,	954},
-	{20,	939},
-	{21,	924},
-	{22,	909},
-	{23,	894},
-	{24,	880},
-	{25,	866},
-	{26,	852},
-	{27,	838},
-	{28,	824},
-	{29,	811},
-	{30,	798},
-	{31,	785},
-	{32,	773},
-	{33,	760},
-	{34,	748},
-	{35,	736},
-	{36,	725},
-	{37,	713},
-	{38,	702},
-	{39,	691},
-	{40,	681},
-	{41,	670},
-	{42,	660},
-	{43,	650},
-	{44,	640},
-	{45,	631},
-	{46,	622},
-	{47,	613},
-	{48,	604},
-	{49,	595},
-	{50,	587},
-	{51,	579},
-	{52,	571},
-	{53,	563},
-	{54,	556},
-	{55,	548},
-	{56,	541},
-	{57,	534},
-	{58,	527},
-	{59,	521},
-	{60,	514},
-	{61,	508},
-	{62,	502},
-	{63,	496},
-	{64,	490},
-	{65,	485},
-	{66,	281},
-	{67,	274},
-	{68,	267},
-	{69,	260},
-	{70,	254},
-	{71,	247},
-	{72,	241},
-	{73,	235},
-	{74,	229},
-	{75,	224},
-	{76,	218},
-	{77,	213},
-	{78,	208},
-	{79,	203}
-};
-
-static const struct pm8921_adc_map_pt adcmap_pa_therm[] = {
-	{41350,	-30},
-	{41282,	-29},
-	{41211,	-28},
-	{41137,	-27},
-	{41060,	-26},
-	{40980,	-25},
-	{40897,	-24},
-	{40811,	-23},
-	{40721,	-22},
-	{40629,	-21},
-	{40533,	-20},
-	{40434,	-19},
-	{40331,	-18},
-	{40226,	-17},
-	{40116,	-16},
-	{40004,	-15},
-	{39888,	-14},
-	{39769,	-13},
-	{39647,	-12},
-	{39521,	-11},
-	{39392,	-10},
-	{39260,	-9},
-	{39124,	-8},
-	{38986,	-7},
-	{38845,	-6},
-	{38700,	-5},
-	{38553,	-4},
-	{38403,	-3},
-	{38250,	-2},
-	{38094,	-1},
-	{37936,	0},
-	{37776,	1},
-	{37613,	2},
-	{37448,	3},
-	{37281,	4},
-	{37112,	5},
-	{36942,	6},
-	{36770,	7},
-	{36596,	8},
-	{36421,	9},
-	{36245,	10},
-	{36068,	11},
-	{35890,	12},
-	{35712,	13},
-	{35532,	14},
-	{35353,	15},
-	{35173,	16},
-	{34993,	17},
-	{34813,	18},
-	{34634,	19},
-	{34455,	20},
-	{34276,	21},
-	{34098,	22},
-	{33921,	23},
-	{33745,	24},
-	{33569,	25},
-	{33395,	26},
-	{33223,	27},
-	{33051,	28},
-	{32881,	29},
-	{32713,	30},
-	{32547,	31},
-	{32382,	32},
-	{32219,	33},
-	{32058,	34},
-	{31899,	35},
-	{31743,	36},
-	{31588,	37},
-	{31436,	38},
-	{31285,	39},
-	{31138,	40},
-	{30992,	41},
-	{30849,	42},
-	{30708,	43},
-	{30570,	44},
-	{30434,	45},
-	{30300,	46},
-	{30169,	47},
-	{30041,	48},
-	{29915,	49},
-	{29791,	50},
-	{29670,	51},
-	{29551,	52},
-	{29435,	53},
-	{29321,	54},
-	{29210,	55},
-	{29101,	56},
-	{28994,	57},
-	{28890,	58},
-	{28788,	59},
-	{28688,	60},
-	{28590,	61},
-	{28495,	62},
-	{28402,	63},
-	{28311,	64},
-	{28222,	65},
-	{28136,	66},
-	{28051,	67},
-	{27968,	68},
-	{27888,	69},
-	{27809,	70},
-	{27732,	71},
-	{27658,	72},
-	{27584,	73},
-	{27513,	74},
-	{27444,	75},
-	{27376,	76},
-	{27310,	77},
-	{27245,	78},
-	{27183,	79},
-	{27121,	80},
-	{27062,	81},
-	{27004,	82},
-	{26947,	83},
-	{26892,	84},
-	{26838,	85},
-	{26785,	86},
-	{26734,	87},
-	{26684,	88},
-	{26636,	89},
-	{26588,	90}
-};
-
-static const struct pm8921_adc_map_pt adcmap_ntcg_104ef_104fb[] = {
-	{696483,	-40960},
-	{649148,	-39936},
-	{605368,	-38912},
-	{564809,	-37888},
-	{527215,	-36864},
-	{492322,	-35840},
-	{460007,	-34816},
-	{429982,	-33792},
-	{402099,	-32768},
-	{376192,	-31744},
-	{352075,	-30720},
-	{329714,	-29696},
-	{308876,	-28672},
-	{289480,	-27648},
-	{271417,	-26624},
-	{254574,	-25600},
-	{238903,	-24576},
-	{224276,	-23552},
-	{210631,	-22528},
-	{197896,	-21504},
-	{186007,	-20480},
-	{174899,	-19456},
-	{164521,	-18432},
-	{154818,	-17408},
-	{145744,	-16384},
-	{137265,	-15360},
-	{129307,	-14336},
-	{121866,	-13312},
-	{114896,	-12288},
-	{108365,	-11264},
-	{102252,	-10240},
-	{96499,		-9216},
-	{91111,		-8192},
-	{86055,		-7168},
-	{81308,		-6144},
-	{76857,		-5120},
-	{72660,		-4096},
-	{68722,		-3072},
-	{65020,		-2048},
-	{61538,		-1024},
-	{58261,		0},
-	{55177,		1024},
-	{52274,		2048},
-	{49538,		3072},
-	{46962,		4096},
-	{44531,		5120},
-	{42243,		6144},
-	{40083,		7168},
-	{38045,		8192},
-	{36122,		9216},
-	{34308,		10240},
-	{32592,		11264},
-	{30972,		12288},
-	{29442,		13312},
-	{27995,		14336},
-	{26624,		15360},
-	{25333,		16384},
-	{24109,		17408},
-	{22951,		18432},
-	{21854,		19456},
-	{20807,		20480},
-	{19831,		21504},
-	{18899,		22528},
-	{18016,		23552},
-	{17178,		24576},
-	{16384,		25600},
-	{15631,		26624},
-	{14916,		27648},
-	{14237,		28672},
-	{13593,		29696},
-	{12976,		30720},
-	{12400,		31744},
-	{11848,		32768},
-	{11324,		33792},
-	{10825,		34816},
-	{10354,		35840},
-	{9900,		36864},
-	{9471,		37888},
-	{9062,		38912},
-	{8674,		39936},
-	{8306,		40960},
-	{7951,		41984},
-	{7616,		43008},
-	{7296,		44032},
-	{6991,		45056},
-	{6701,		46080},
-	{6424,		47104},
-	{6160,		48128},
-	{5908,		49152},
-	{5667,		50176},
-	{5439,		51200},
-	{5219,		52224},
-	{5010,		53248},
-	{4810,		54272},
-	{4619,		55296},
-	{4440,		56320},
-	{4263,		57344},
-	{4097,		58368},
-	{3938,		59392},
-	{3785,		60416},
-	{3637,		61440},
-	{3501,		62464},
-	{3368,		63488},
-	{3240,		64512},
-	{3118,		65536},
-	{2998,		66560},
-	{2889,		67584},
-	{2782,		68608},
-	{2680,		69632},
-	{2581,		70656},
-	{2490,		71680},
-	{2397,		72704},
-	{2310,		73728},
-	{2227,		74752},
-	{2147,		75776},
-	{2064,		76800},
-	{1998,		77824},
-	{1927,		78848},
-	{1860,		79872},
-	{1795,		80896},
-	{1736,		81920},
-	{1673,		82944},
-	{1615,		83968},
-	{1560,		84992},
-	{1507,		86016},
-	{1456,		87040},
-	{1407,		88064},
-	{1360,		89088},
-	{1314,		90112},
-	{1271,		91136},
-	{1228,		92160},
-	{1189,		93184},
-	{1150,		94208},
-	{1112,		95232},
-	{1076,		96256},
-	{1042,		97280},
-	{1008,		98304},
-	{976,		99328},
-	{945,		100352},
-	{915,		101376},
-	{886,		102400},
-	{859,		103424},
-	{832,		104448},
-	{807,		105472},
-	{782,		106496},
-	{756,		107520},
-	{735,		108544},
-	{712,		109568},
-	{691,		110592},
-	{670,		111616},
-	{650,		112640},
-	{631,		113664},
-	{612,		114688},
-	{594,		115712},
-	{577,		116736},
-	{560,		117760},
-	{544,		118784},
-	{528,		119808},
-	{513,		120832},
-	{498,		121856},
-	{483,		122880},
-	{470,		123904},
-	{457,		124928},
-	{444,		125952},
-	{431,		126976},
-	{419,		128000}
-};
-
-static int32_t pm8921_adc_map_linear(const struct pm8921_adc_map_pt *pts,
-		uint32_t tablesize, int32_t input, int64_t *output)
-{
-	bool descending = 1;
-	uint32_t i = 0;
-
-	if ((pts == NULL) || (output == NULL))
-		return -EINVAL;
-
-	/* Check if table is descending or ascending */
-	if (tablesize > 1) {
-		if (pts[0].x < pts[1].x)
-			descending = 0;
-	}
-
-	while (i < tablesize) {
-		if ((descending == 1) && (pts[i].x < input)) {
-			/* table entry is less than measured
-				value and table is descending, stop */
-			break;
-		} else if ((descending == 0) &&
-				(pts[i].x > input)) {
-			/* table entry is greater than measured
-				value and table is ascending, stop */
-			break;
-		} else {
-			i++;
-		}
-	}
-
-	if (i == 0)
-		*output = pts[0].y;
-	else if (i == tablesize)
-		*output = pts[tablesize-1].y;
-	else {
-		/* result is between search_index and search_index-1 */
-		/* interpolate linearly */
-		*output = (((int32_t) ((pts[i].y - pts[i-1].y)*
-			(input - pts[i-1].x))/
-			(pts[i].x - pts[i-1].x))+
-			pts[i-1].y);
-	}
-
-	return 0;
-}
-
-int32_t pm8921_adc_scale_default(int32_t adc_code,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties,
-		struct pm8921_adc_chan_result *adc_chan_result)
-{
-	bool negative_rawfromoffset = 0;
-	int32_t rawfromoffset = 0;
-
-	if (!chan_properties || !chan_properties->offset_gain_numerator ||
-		!chan_properties->offset_gain_denominator || !adc_properties
-		|| !adc_chan_result)
-		return -EINVAL;
-
-	rawfromoffset = adc_code -
-			chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].offset;
-
-	adc_chan_result->adc_code = adc_code;
-	if (rawfromoffset < 0) {
-		if (adc_properties->bipolar) {
-			rawfromoffset = -rawfromoffset;
-			negative_rawfromoffset = 1;
-		} else {
-			rawfromoffset = 0;
-		}
-	}
-
-	if (rawfromoffset >= 1 << adc_properties->bitresolution)
-		rawfromoffset = (1 << adc_properties->bitresolution) - 1;
-
-	adc_chan_result->measurement = (int64_t)rawfromoffset *
-		chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx *
-				chan_properties->offset_gain_denominator;
-
-	/* do_div only perform positive integer division! */
-	do_div(adc_chan_result->measurement,
-		chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy *
-				chan_properties->offset_gain_numerator);
-
-	if (negative_rawfromoffset)
-		adc_chan_result->measurement = -adc_chan_result->measurement;
-
-	/* Note: adc_chan_result->measurement is in the unit of
-	 * adc_properties.adc_reference. For generic channel processing,
-	 * channel measurement is a scale/ratio relative to the adc
-	 * reference input */
-	adc_chan_result->physical = (int32_t) adc_chan_result->measurement;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_scale_default);
-
-int32_t pm8921_adc_scale_batt_therm(int32_t adc_code,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties,
-		struct pm8921_adc_chan_result *adc_chan_result)
-{
-	/* convert mV ---> degC using the table */
-	return pm8921_adc_map_linear(
-			adcmap_batttherm,
-			ARRAY_SIZE(adcmap_batttherm),
-			adc_code,
-			&adc_chan_result->physical);
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_scale_batt_therm);
-
-int32_t pm8921_adc_scale_pa_therm(int32_t adc_code,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties,
-		struct pm8921_adc_chan_result *adc_chan_result)
-{
-	/* convert mV ---> degC using the table */
-	return pm8921_adc_map_linear(
-			adcmap_pa_therm,
-			ARRAY_SIZE(adcmap_pa_therm),
-			adc_code,
-			&adc_chan_result->physical);
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_scale_pa_therm);
-
-int32_t pm8921_adc_scale_pmic_therm(int32_t adc_code,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties,
-		struct pm8921_adc_chan_result *adc_chan_result)
-{
-	int32_t rawfromoffset;
-
-	if (!chan_properties || !chan_properties->offset_gain_numerator ||
-		!chan_properties->offset_gain_denominator || !adc_properties
-		|| !adc_chan_result)
-		return -EINVAL;
-
-	adc_chan_result->adc_code = adc_code;
-	rawfromoffset = adc_code -
-			chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].offset;
-	if (rawfromoffset > 0) {
-		if (rawfromoffset >= 1 << adc_properties->bitresolution)
-			rawfromoffset = (1 << adc_properties->bitresolution)
-									- 1;
-		/* 2mV/K */
-		adc_chan_result->measurement = (int64_t)rawfromoffset*
-			chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dx *
-			chan_properties->offset_gain_denominator * 1000;
-
-		do_div(adc_chan_result->measurement,
-			chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].dy *
-			chan_properties->offset_gain_numerator*2);
-	} else {
-		adc_chan_result->measurement = 0;
-	}
-	/* Note: adc_chan_result->measurement is in the unit of
-		adc_properties.adc_reference */
-	adc_chan_result->physical = (int32_t)adc_chan_result->measurement;
-	/* Change to .001 deg C */
-	adc_chan_result->physical -= KELVINMIL_DEGMIL;
-	adc_chan_result->measurement <<= 1;
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_scale_pmic_therm);
-
-/* Scales the ADC code to 0.001 degrees C using the map
- * table for the XO thermistor.
- */
-int32_t pm8921_adc_tdkntcg_therm(int32_t adc_code,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties,
-		struct pm8921_adc_chan_result *adc_chan_result)
-{
-	int32_t rt_r25;
-	int32_t offset = chan_properties->adc_graph[ADC_CALIB_ABSOLUTE].offset;
-
-	rt_r25 = adc_code - offset;
-
-	pm8921_adc_map_linear(adcmap_ntcg_104ef_104fb,
-		ARRAY_SIZE(adcmap_ntcg_104ef_104fb),
-		rt_r25, &adc_chan_result->physical);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_tdkntcg_therm);
-
-int32_t pm8921_adc_batt_scaler(struct pm8921_adc_arb_btm_param *btm_param,
-		const struct pm8921_adc_properties *adc_properties,
-		const struct pm8921_adc_chan_properties *chan_properties)
-{
-	int rc;
-
-	rc = pm8921_adc_map_linear(
-		adcmap_btm_threshold,
-		ARRAY_SIZE(adcmap_btm_threshold),
-		btm_param->low_thr_temp,
-		&btm_param->low_thr_voltage);
-	if (rc)
-		return rc;
-
-	btm_param->low_thr_voltage *=
-		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
-	do_div(btm_param->low_thr_voltage, adc_properties->adc_vdd_reference);
-	btm_param->low_thr_voltage +=
-		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
-
-	rc = pm8921_adc_map_linear(
-			adcmap_btm_threshold,
-			ARRAY_SIZE(adcmap_btm_threshold),
-			btm_param->high_thr_temp,
-			&btm_param->high_thr_voltage);
-	if (rc)
-		return rc;
-
-	btm_param->high_thr_voltage *=
-		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].dy;
-	do_div(btm_param->high_thr_voltage, adc_properties->adc_vdd_reference);
-	btm_param->high_thr_voltage +=
-		chan_properties->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd;
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_batt_scaler);
diff --git a/drivers/hwmon/pm8921-adc.c b/drivers/hwmon/pm8921-adc.c
deleted file mode 100644
index 38e18de..0000000
--- a/drivers/hwmon/pm8921-adc.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * Copyright (c) 2011, 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.
- *
- * Qualcomm's PM8921 ADC Arbiter driver
- */
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/completion.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/mpp.h>
-#include <linux/debugfs.h>
-#include <linux/regulator/consumer.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/wakelock.h>
-
-/* User Bank register set */
-#define PM8921_ADC_ARB_USRP_CNTRL1			0x197
-#define PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB		BIT(0)
-#define PM8921_ADC_ARB_USRP_CNTRL1_RSV1			BIT(1)
-#define PM8921_ADC_ARB_USRP_CNTRL1_RSV2			BIT(2)
-#define PM8921_ADC_ARB_USRP_CNTRL1_RSV3			BIT(3)
-#define PM8921_ADC_ARB_USRP_CNTRL1_RSV4			BIT(4)
-#define PM8921_ADC_ARB_USRP_CNTRL1_RSV5			BIT(5)
-#define PM8921_ADC_ARB_USRP_CNTRL1_EOC			BIT(6)
-#define PM8921_ADC_ARB_USRP_CNTRL1_REQ			BIT(7)
-
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL			0x198
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_RSV0		BIT(0)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_RSV1		BIT(1)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_PREMUX0		BIT(2)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_PREMUX1		BIT(3)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_SEL0		BIT(4)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_SEL1		BIT(5)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_SEL2		BIT(6)
-#define PM8921_ADC_ARB_USRP_AMUX_CNTRL_SEL3		BIT(7)
-
-#define PM8921_ADC_ARB_USRP_ANA_PARAM			0x199
-#define PM8921_ADC_ARB_USRP_DIG_PARAM			0x19A
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT0	BIT(0)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_SEL_SHIFT1	BIT(1)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_CLK_RATE0		BIT(2)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_CLK_RATE1		BIT(3)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_EOC		BIT(4)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0		BIT(5)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE1		BIT(6)
-#define PM8921_ADC_ARB_USRP_DIG_PARAM_EN		BIT(7)
-
-#define PM8921_ADC_ARB_USRP_RSV				0x19B
-#define PM8921_ADC_ARB_USRP_RSV_RST			BIT(0)
-#define PM8921_ADC_ARB_USRP_RSV_DTEST0			BIT(1)
-#define PM8921_ADC_ARB_USRP_RSV_DTEST1			BIT(2)
-#define PM8921_ADC_ARB_USRP_RSV_OP			BIT(3)
-#define PM8921_ADC_ARB_USRP_RSV_IP_SEL0			BIT(4)
-#define PM8921_ADC_ARB_USRP_RSV_IP_SEL1			BIT(5)
-#define PM8921_ADC_ARB_USRP_RSV_IP_SEL2			BIT(6)
-#define PM8921_ADC_ARB_USRP_RSV_TRM			BIT(7)
-
-#define PM8921_ADC_ARB_USRP_DATA0			0x19D
-#define PM8921_ADC_ARB_USRP_DATA1			0x19C
-
-#define PM8921_ADC_ARB_BTM_CNTRL1			0x17e
-#define PM8921_ADC_ARB_BTM_CNTRL1_EN_BTM		BIT(0)
-#define PM8921_ADC_ARB_BTM_CNTRL1_SEL_OP_MODE		BIT(1)
-#define PM8921_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL1	BIT(2)
-#define PM8921_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL2	BIT(3)
-#define PM8921_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL3	BIT(4)
-#define PM8921_ADC_ARB_BTM_CNTRL1_MEAS_INTERVAL4	BIT(5)
-#define PM8921_ADC_ARB_BTM_CNTRL1_EOC			BIT(6)
-#define PM8921_ADC_ARB_BTM_CNTRL1_REQ			BIT(7)
-
-#define PM8921_ADC_ARB_BTM_CNTRL2			0x18c
-#define PM8921_ADC_ARB_BTM_AMUX_CNTRL			0x17f
-#define PM8921_ADC_ARB_BTM_ANA_PARAM			0x180
-#define PM8921_ADC_ARB_BTM_DIG_PARAM			0x181
-#define PM8921_ADC_ARB_BTM_RSV				0x182
-#define PM8921_ADC_ARB_BTM_DATA1			0x183
-#define PM8921_ADC_ARB_BTM_DATA0			0x184
-#define PM8921_ADC_ARB_BTM_BAT_COOL_THR1		0x185
-#define PM8921_ADC_ARB_BTM_BAT_COOL_THR0		0x186
-#define PM8921_ADC_ARB_BTM_BAT_WARM_THR1		0x187
-#define PM8921_ADC_ARB_BTM_BAT_WARM_THR0		0x188
-
-#define PM8921_ADC_ARB_ANA_DIG				0xa0
-#define PM8921_ADC_BTM_RSV				0x10
-#define PM8921_ADC_AMUX_MPP_SEL				2
-#define PM8921_ADC_AMUX_SEL				4
-#define PM8921_ADC_RSV_IP_SEL				4
-#define PM8921_ADC_BTM_CHANNEL_SEL			4
-#define PM8921_MAX_CHANNEL_PROPERTIES			2
-#define PM8921_ADC_IRQ_0				0
-#define PM8921_ADC_IRQ_1				1
-#define PM8921_ADC_IRQ_2				2
-#define PM8921_ADC_BTM_INTERVAL_SEL_MASK		0xF
-#define PM8921_ADC_BTM_INTERVAL_SEL_SHIFT		2
-#define PM8921_ADC_BTM_DECIMATION_SEL			5
-#define PM8921_ADC_MUL					10
-#define PM8921_ADC_CONV_TIME_MIN			2000
-#define PM8921_ADC_CONV_TIME_MAX			2100
-#define PM8921_ADC_MPP_SETTLE_TIME_MIN			200
-#define PM8921_ADC_MPP_SETTLE_TIME_MAX			200
-#define PM8921_ADC_PA_THERM_VREG_UV_MIN			1800000
-#define PM8921_ADC_PA_THERM_VREG_UV_MAX			1800000
-#define PM8921_ADC_PA_THERM_VREG_UA_LOAD		100000
-
-struct pm8921_adc {
-	struct device				*dev;
-	struct pm8921_adc_properties		*adc_prop;
-	int					adc_irq;
-	struct mutex				adc_lock;
-	struct mutex				mpp_adc_lock;
-	spinlock_t				btm_lock;
-	uint32_t				adc_num_channel;
-	uint32_t				adc_num_board_channel;
-	struct completion			adc_rslt_completion;
-	struct pm8921_adc_amux			*adc_channel;
-	struct pm8921_adc_amux_properties	*conv;
-	struct pm8921_adc_arb_btm_param		*batt;
-	int					btm_warm_irq;
-	int					btm_cool_irq;
-	struct dentry				*dent;
-	struct work_struct			warm_work;
-	struct work_struct			cool_work;
-	uint32_t				mpp_base;
-	struct sensor_device_attribute		*sens_attr;
-	struct device				*hwmon;
-	struct wake_lock			adc_wakelock;
-	int					msm_suspend_check;
-};
-
-struct pm8921_adc_amux_properties {
-	uint32_t				amux_channel;
-	uint32_t				decimation;
-	uint32_t				amux_ip_rsv;
-	uint32_t				amux_mpp_channel;
-	struct pm8921_adc_chan_properties	*chan_prop;
-};
-
-static const struct pm8921_adc_scaling_ratio pm8921_amux_scaling_ratio[] = {
-	{1, 1},
-	{1, 3},
-	{1, 4},
-	{1, 6}
-};
-
-static struct pm8921_adc *pmic_adc;
-
-static struct pm8921_adc_scale_fn adc_scale_fn[] = {
-	[ADC_SCALE_DEFAULT] = {pm8921_adc_scale_default},
-	[ADC_SCALE_BATT_THERM] = {pm8921_adc_scale_batt_therm},
-	[ADC_SCALE_PA_THERM] = {pm8921_adc_scale_pa_therm},
-	[ADC_SCALE_PMIC_THERM] = {pm8921_adc_scale_pmic_therm},
-	[ADC_SCALE_XOTHERM] = {pm8921_adc_tdkntcg_therm},
-};
-
-/* MPP 8 is mapped to AMUX8 and is common between remote processor's */
-
-static struct pm8xxx_mpp_config_data pm8921_adc_mpp_config = {
-	.type		= PM8XXX_MPP_TYPE_A_INPUT,
-	/* AMUX6 is dedicated to be used for apps processor */
-	.level		= PM8XXX_MPP_AIN_AMUX_CH6,
-	.control	= PM8XXX_MPP_AOUT_CTRL_DISABLE,
-};
-
-/* MPP Configuration for default settings */
-static struct pm8xxx_mpp_config_data pm8921_adc_mpp_unconfig = {
-	.type		= PM8XXX_MPP_TYPE_SINK,
-	.level		= PM8XXX_MPP_AIN_AMUX_CH5,
-	.control	= PM8XXX_MPP_AOUT_CTRL_DISABLE,
-};
-
-static bool pm8921_adc_calib_first_adc;
-static bool pm8921_adc_initialized, pm8921_adc_calib_device_init;
-
-static int32_t pm8921_adc_arb_cntrl(uint32_t arb_cntrl, uint32_t channel)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int i, rc;
-	u8 data_arb_cntrl = 0;
-
-	if (arb_cntrl) {
-		if (adc_pmic->msm_suspend_check)
-			pr_err("PM8921 ADC request being made after suspend "
-				 "irq with channel id:%d\n", channel);
-		data_arb_cntrl |= PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB;
-	}
-
-	/* Write twice to the CNTRL register for the arbiter settings
-	   to take into effect */
-	for (i = 0; i < 2; i++) {
-		rc = pm8xxx_writeb(adc_pmic->dev->parent,
-				PM8921_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
-		if (rc < 0) {
-			pr_err("PM8921 arb cntrl write failed with %d\n", rc);
-			return rc;
-		}
-	}
-
-	if (arb_cntrl) {
-		data_arb_cntrl |= PM8921_ADC_ARB_USRP_CNTRL1_REQ;
-		rc = pm8xxx_writeb(adc_pmic->dev->parent,
-			PM8921_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
-		if (rc < 0) {
-			pr_err("PM8921 arb cntrl write failed with %d\n", rc);
-			return rc;
-		}
-		wake_lock(&adc_pmic->adc_wakelock);
-	} else {
-		wake_unlock(&adc_pmic->adc_wakelock);
-	}
-
-	return 0;
-}
-
-static int32_t pm8921_adc_patherm_power(bool on)
-{
-	static struct regulator *pa_therm;
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc = 0;
-	if (on) {
-		pa_therm = regulator_get(adc_pmic->dev,
-						"pa_therm");
-		if (IS_ERR(pa_therm)) {
-			rc = PTR_ERR(pa_therm);
-			pr_err("failed to request pa_therm vreg "
-					"with error %d\n", rc);
-			return rc;
-		}
-
-		rc = regulator_set_voltage(pa_therm,
-				PM8921_ADC_PA_THERM_VREG_UV_MIN,
-				PM8921_ADC_PA_THERM_VREG_UV_MAX);
-		if (rc < 0) {
-			pr_err("failed to set the voltage for "
-					"pa_therm with error %d\n", rc);
-			goto fail;
-		}
-
-		rc = regulator_set_optimum_mode(pa_therm,
-				PM8921_ADC_PA_THERM_VREG_UA_LOAD);
-		if (rc < 0) {
-			pr_err("failed to set optimum mode for "
-					"pa_therm with error %d\n", rc);
-			goto fail;
-		}
-
-		if (regulator_enable(pa_therm)) {
-			pr_err("failed to enable pa_therm vreg with "
-						"error %d\n", rc);
-			goto fail;
-		}
-	} else {
-		if (pa_therm != NULL) {
-			regulator_disable(pa_therm);
-			regulator_put(pa_therm);
-		}
-	}
-
-	return rc;
-fail:
-	regulator_put(pa_therm);
-	return rc;
-}
-
-static int32_t pm8921_adc_channel_power_enable(uint32_t channel,
-							bool power_cntrl)
-{
-	int rc = 0;
-
-	switch (channel)
-	case ADC_MPP_1_AMUX8:
-		pm8921_adc_patherm_power(power_cntrl);
-
-	return rc;
-}
-
-
-static uint32_t pm8921_adc_read_reg(uint32_t reg, u8 *data)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc;
-
-	rc = pm8xxx_readb(adc_pmic->dev->parent, reg, data);
-	if (rc < 0) {
-		pr_err("PM8921 adc read reg %d failed with %d\n", reg, rc);
-		return rc;
-	}
-
-	return 0;
-}
-
-static uint32_t pm8921_adc_write_reg(uint32_t reg, u8 data)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc;
-
-	rc = pm8xxx_writeb(adc_pmic->dev->parent, reg, data);
-	if (rc < 0) {
-		pr_err("PM8921 adc write reg %d failed with %d\n", reg, rc);
-		return rc;
-	}
-
-	return 0;
-}
-
-static int32_t pm8921_adc_configure(
-				struct pm8921_adc_amux_properties *chan_prop)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	u8 data_amux_chan = 0, data_arb_rsv = 0, data_dig_param = 0;
-	int rc;
-
-	data_amux_chan |= chan_prop->amux_channel << PM8921_ADC_AMUX_SEL;
-
-	if (chan_prop->amux_mpp_channel)
-		data_amux_chan |= chan_prop->amux_mpp_channel <<
-					PM8921_ADC_AMUX_MPP_SEL;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_USRP_AMUX_CNTRL,
-							data_amux_chan);
-	if (rc < 0)
-		return rc;
-
-	data_arb_rsv &= (PM8921_ADC_ARB_USRP_RSV_RST |
-		PM8921_ADC_ARB_USRP_RSV_DTEST0 |
-		PM8921_ADC_ARB_USRP_RSV_DTEST1 |
-		PM8921_ADC_ARB_USRP_RSV_OP |
-		PM8921_ADC_ARB_USRP_RSV_TRM);
-	data_arb_rsv |= chan_prop->amux_ip_rsv << PM8921_ADC_RSV_IP_SEL;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_USRP_RSV, data_arb_rsv);
-	if (rc < 0)
-		return rc;
-
-	rc = pm8921_adc_read_reg(PM8921_ADC_ARB_USRP_DIG_PARAM,
-							&data_dig_param);
-	if (rc < 0)
-		return rc;
-
-	/* Default 2.4Mhz clock rate */
-	/* Client chooses the decimation */
-	switch (chan_prop->decimation) {
-	case ADC_DECIMATION_TYPE1:
-		data_dig_param |= PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
-		break;
-	case ADC_DECIMATION_TYPE2:
-		data_dig_param |= (PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0
-				| PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE1);
-		break;
-	default:
-		data_dig_param |= PM8921_ADC_ARB_USRP_DIG_PARAM_DEC_RATE0;
-		break;
-	}
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_USRP_DIG_PARAM,
-						PM8921_ADC_ARB_ANA_DIG);
-	if (rc < 0)
-		return rc;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_USRP_ANA_PARAM,
-						PM8921_ADC_ARB_ANA_DIG);
-	if (rc < 0)
-		return rc;
-
-	if (!pm8921_adc_calib_first_adc)
-		enable_irq(adc_pmic->adc_irq);
-
-	rc = pm8921_adc_arb_cntrl(1, chan_prop->amux_mpp_channel);
-	if (rc < 0) {
-		pr_err("Configuring ADC Arbiter"
-				"enable failed with %d\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
-static uint32_t pm8921_adc_read_adc_code(int32_t *data)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	uint8_t rslt_lsb, rslt_msb;
-	int32_t rc, max_ideal_adc_code = 1 << adc_pmic->adc_prop->bitresolution;
-
-	rc = pm8xxx_readb(adc_pmic->dev->parent,
-				PM8921_ADC_ARB_USRP_DATA0, &rslt_lsb);
-	if (rc < 0) {
-		pr_err("PM8921 adc result read failed with %d\n", rc);
-		return rc;
-	}
-
-	rc = pm8xxx_readb(adc_pmic->dev->parent,
-				PM8921_ADC_ARB_USRP_DATA1, &rslt_msb);
-	if (rc < 0) {
-		pr_err("PM8921 adc result read failed with %d\n", rc);
-		return rc;
-	}
-
-	*data = (rslt_msb << 8) | rslt_lsb;
-
-	/* Use the midpoint to determine underflow or overflow */
-	if (*data > max_ideal_adc_code + (max_ideal_adc_code >> 1))
-		*data |= ((1 << (8 * sizeof(*data) -
-			adc_pmic->adc_prop->bitresolution)) - 1) <<
-			adc_pmic->adc_prop->bitresolution;
-
-	/* Default value for switching off the arbiter after reading
-	   the ADC value. Bit 0 set to 0. */
-	rc = pm8921_adc_arb_cntrl(0, CHANNEL_MUXOFF);
-	if (rc < 0) {
-		pr_err("%s: Configuring ADC Arbiter disable"
-					"failed\n", __func__);
-		return rc;
-	}
-
-	return 0;
-}
-
-static void pm8921_adc_btm_warm_scheduler_fn(struct work_struct *work)
-{
-	struct pm8921_adc *adc_pmic = container_of(work, struct pm8921_adc,
-					warm_work);
-	unsigned long flags = 0;
-	bool warm_status;
-
-	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-	warm_status = irq_read_line(adc_pmic->btm_warm_irq);
-	if (adc_pmic->batt->btm_warm_fn != NULL)
-		adc_pmic->batt->btm_warm_fn(warm_status);
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-}
-
-static void pm8921_adc_btm_cool_scheduler_fn(struct work_struct *work)
-{
-	struct pm8921_adc *adc_pmic = container_of(work, struct pm8921_adc,
-					cool_work);
-	unsigned long flags = 0;
-	bool cool_status;
-
-	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-	cool_status = irq_read_line(adc_pmic->btm_cool_irq);
-	if (adc_pmic->batt->btm_cool_fn != NULL)
-		adc_pmic->batt->btm_cool_fn(cool_status);
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-}
-
-static irqreturn_t pm8921_adc_isr(int irq, void *dev_id)
-{
-	struct pm8921_adc *adc_8921 = dev_id;
-
-	disable_irq_nosync(adc_8921->adc_irq);
-
-	if (pm8921_adc_calib_first_adc)
-		return IRQ_HANDLED;
-	/* TODO Handle spurius interrupt condition */
-	complete(&adc_8921->adc_rslt_completion);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t pm8921_btm_warm_isr(int irq, void *dev_id)
-{
-	struct pm8921_adc *btm_8921 = dev_id;
-
-	schedule_work(&btm_8921->warm_work);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t pm8921_btm_cool_isr(int irq, void *dev_id)
-{
-	struct pm8921_adc *btm_8921 = dev_id;
-
-	schedule_work(&btm_8921->cool_work);
-
-	return IRQ_HANDLED;
-}
-
-static uint32_t pm8921_adc_calib_device(void)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	struct pm8921_adc_amux_properties conv;
-	int rc, offset_adc, slope_adc, calib_read_1, calib_read_2;
-	u8 data_arb_usrp_cntrl1 = 0;
-
-	conv.amux_channel = CHANNEL_125V;
-	conv.decimation = ADC_DECIMATION_TYPE2;
-	conv.amux_ip_rsv = AMUX_RSV1;
-	conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
-	pm8921_adc_calib_first_adc = true;
-	rc = pm8921_adc_configure(&conv);
-	if (rc) {
-		pr_err("pm8921_adc configure failed with %d\n", rc);
-		goto calib_fail;
-	}
-
-	while (data_arb_usrp_cntrl1 != (PM8921_ADC_ARB_USRP_CNTRL1_EOC |
-					PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
-		rc = pm8921_adc_read_reg(PM8921_ADC_ARB_USRP_CNTRL1,
-					&data_arb_usrp_cntrl1);
-		if (rc < 0)
-			return rc;
-		usleep_range(PM8921_ADC_CONV_TIME_MIN,
-					PM8921_ADC_CONV_TIME_MAX);
-	}
-	data_arb_usrp_cntrl1 = 0;
-
-	rc = pm8921_adc_read_adc_code(&calib_read_1);
-	if (rc) {
-		pr_err("pm8921_adc read adc failed with %d\n", rc);
-		pm8921_adc_calib_first_adc = false;
-		goto calib_fail;
-	}
-	pm8921_adc_calib_first_adc = false;
-
-	conv.amux_channel = CHANNEL_625MV;
-	conv.decimation = ADC_DECIMATION_TYPE2;
-	conv.amux_ip_rsv = AMUX_RSV1;
-	conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
-	pm8921_adc_calib_first_adc = true;
-	rc = pm8921_adc_configure(&conv);
-	if (rc) {
-		pr_err("pm8921_adc configure failed with %d\n", rc);
-		goto calib_fail;
-	}
-
-	while (data_arb_usrp_cntrl1 != (PM8921_ADC_ARB_USRP_CNTRL1_EOC |
-					PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
-		rc = pm8921_adc_read_reg(PM8921_ADC_ARB_USRP_CNTRL1,
-					&data_arb_usrp_cntrl1);
-		if (rc < 0)
-			return rc;
-		usleep_range(PM8921_ADC_CONV_TIME_MIN,
-					PM8921_ADC_CONV_TIME_MAX);
-	}
-	data_arb_usrp_cntrl1 = 0;
-
-	rc = pm8921_adc_read_adc_code(&calib_read_2);
-	if (rc) {
-		pr_err("pm8921_adc read adc failed with %d\n", rc);
-		pm8921_adc_calib_first_adc = false;
-		goto calib_fail;
-	}
-	pm8921_adc_calib_first_adc = false;
-
-	slope_adc = (((calib_read_1 - calib_read_2) << PM8921_ADC_MUL)/
-					PM8921_CHANNEL_ADC_625_MV);
-	offset_adc = calib_read_2 -
-			((slope_adc * PM8921_CHANNEL_ADC_625_MV) >>
-							PM8921_ADC_MUL);
-
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].offset
-								= offset_adc;
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dy =
-					(calib_read_1 - calib_read_2);
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_ABSOLUTE].dx
-						= PM8921_CHANNEL_ADC_625_MV;
-	rc = pm8921_adc_arb_cntrl(0, CHANNEL_MUXOFF);
-	if (rc < 0) {
-		pr_err("%s: Configuring ADC Arbiter disable"
-					"failed\n", __func__);
-		return rc;
-	}
-	/* Ratiometric Calibration */
-	conv.amux_channel = CHANNEL_MUXOFF;
-	conv.decimation = ADC_DECIMATION_TYPE2;
-	conv.amux_ip_rsv = AMUX_RSV5;
-	conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
-	pm8921_adc_calib_first_adc = true;
-	rc = pm8921_adc_configure(&conv);
-	if (rc) {
-		pr_err("pm8921_adc configure failed with %d\n", rc);
-		goto calib_fail;
-	}
-
-	while (data_arb_usrp_cntrl1 != (PM8921_ADC_ARB_USRP_CNTRL1_EOC |
-					PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
-		rc = pm8921_adc_read_reg(PM8921_ADC_ARB_USRP_CNTRL1,
-					&data_arb_usrp_cntrl1);
-		if (rc < 0)
-			return rc;
-		usleep_range(PM8921_ADC_CONV_TIME_MIN,
-					PM8921_ADC_CONV_TIME_MAX);
-	}
-	data_arb_usrp_cntrl1 = 0;
-
-	rc = pm8921_adc_read_adc_code(&calib_read_1);
-	if (rc) {
-		pr_err("pm8921_adc read adc failed with %d\n", rc);
-		pm8921_adc_calib_first_adc = false;
-		goto calib_fail;
-	}
-	pm8921_adc_calib_first_adc = false;
-
-	conv.amux_channel = CHANNEL_MUXOFF;
-	conv.decimation = ADC_DECIMATION_TYPE2;
-	conv.amux_ip_rsv = AMUX_RSV4;
-	conv.amux_mpp_channel = PREMUX_MPP_SCALE_0;
-	pm8921_adc_calib_first_adc = true;
-	rc = pm8921_adc_configure(&conv);
-	if (rc) {
-		pr_err("pm8921_adc configure failed with %d\n", rc);
-		goto calib_fail;
-	}
-
-	while (data_arb_usrp_cntrl1 != (PM8921_ADC_ARB_USRP_CNTRL1_EOC |
-					PM8921_ADC_ARB_USRP_CNTRL1_EN_ARB)) {
-		rc = pm8921_adc_read_reg(PM8921_ADC_ARB_USRP_CNTRL1,
-					&data_arb_usrp_cntrl1);
-		if (rc < 0)
-			return rc;
-		usleep_range(PM8921_ADC_CONV_TIME_MIN,
-					PM8921_ADC_CONV_TIME_MAX);
-	}
-	data_arb_usrp_cntrl1 = 0;
-
-	rc = pm8921_adc_read_adc_code(&calib_read_2);
-	if (rc) {
-		pr_err("pm8921_adc read adc failed with %d\n", rc);
-		pm8921_adc_calib_first_adc = false;
-		goto calib_fail;
-	}
-	pm8921_adc_calib_first_adc = false;
-
-	slope_adc = (((calib_read_1 - calib_read_2) << PM8921_ADC_MUL)/
-				adc_pmic->adc_prop->adc_vdd_reference);
-	offset_adc = calib_read_2 -
-			((slope_adc * adc_pmic->adc_prop->adc_vdd_reference)
-							>> PM8921_ADC_MUL);
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].offset
-								= offset_adc;
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dy =
-					(calib_read_1 - calib_read_2);
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].dx =
-					adc_pmic->adc_prop->adc_vdd_reference;
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_vref =
-					calib_read_1;
-	adc_pmic->conv->chan_prop->adc_graph[ADC_CALIB_RATIOMETRIC].adc_gnd =
-					calib_read_2;
-calib_fail:
-	rc = pm8921_adc_arb_cntrl(0, CHANNEL_MUXOFF);
-	if (rc < 0) {
-		pr_err("%s: Configuring ADC Arbiter disable"
-					"failed\n", __func__);
-	}
-
-	return rc;
-}
-
-uint32_t pm8921_adc_read(enum pm8921_adc_channels channel,
-				struct pm8921_adc_chan_result *result)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int i = 0, rc = 0, rc_fail, amux_prescaling, scale_type;
-	enum pm8921_adc_premux_mpp_scale_type mpp_scale;
-
-	if (!pm8921_adc_initialized)
-		return -ENODEV;
-
-	if (!pm8921_adc_calib_device_init) {
-		if (pm8921_adc_calib_device() == 0)
-			pm8921_adc_calib_device_init = true;
-	}
-
-	mutex_lock(&adc_pmic->adc_lock);
-
-	for (i = 0; i < adc_pmic->adc_num_channel; i++) {
-		if (channel == adc_pmic->adc_channel[i].channel_name)
-			break;
-	}
-
-	if (i == adc_pmic->adc_num_channel) {
-		rc = -EBADF;
-		goto fail_unlock;
-	}
-
-	if (channel < PM8921_CHANNEL_MPP_SCALE1_IDX) {
-		mpp_scale = PREMUX_MPP_SCALE_0;
-		adc_pmic->conv->amux_channel = channel;
-	} else if (channel >= PM8921_CHANNEL_MPP_SCALE1_IDX) {
-		mpp_scale = PREMUX_MPP_SCALE_1;
-		adc_pmic->conv->amux_channel = channel %
-				PM8921_CHANNEL_MPP_SCALE1_IDX;
-	} else if (channel >= PM8921_CHANNEL_MPP_SCALE3_IDX) {
-		mpp_scale = PREMUX_MPP_SCALE_1_DIV3;
-		adc_pmic->conv->amux_channel = channel %
-				PM8921_CHANNEL_MPP_SCALE3_IDX;
-	}
-
-	adc_pmic->conv->amux_mpp_channel = mpp_scale;
-	adc_pmic->conv->amux_ip_rsv = adc_pmic->adc_channel[i].adc_rsv;
-	adc_pmic->conv->decimation = adc_pmic->adc_channel[i].adc_decimation;
-	amux_prescaling = adc_pmic->adc_channel[i].chan_path_prescaling;
-
-	adc_pmic->conv->chan_prop->offset_gain_numerator =
-		pm8921_amux_scaling_ratio[amux_prescaling].num;
-	adc_pmic->conv->chan_prop->offset_gain_denominator =
-		 pm8921_amux_scaling_ratio[amux_prescaling].den;
-
-	rc = pm8921_adc_channel_power_enable(channel, true);
-	if (rc) {
-		rc = -EINVAL;
-		goto fail_unlock;
-	}
-
-	rc = pm8921_adc_configure(adc_pmic->conv);
-	if (rc) {
-		rc = -EINVAL;
-		goto fail;
-	}
-
-	wait_for_completion(&adc_pmic->adc_rslt_completion);
-
-	rc = pm8921_adc_read_adc_code(&result->adc_code);
-	if (rc) {
-		rc = -EINVAL;
-		goto fail;
-	}
-
-	scale_type = adc_pmic->adc_channel[i].adc_scale_fn;
-	if (scale_type >= ADC_SCALE_NONE) {
-		rc = -EBADF;
-		goto fail;
-	}
-
-	adc_scale_fn[scale_type].chan(result->adc_code,
-			adc_pmic->adc_prop, adc_pmic->conv->chan_prop, result);
-
-	rc = pm8921_adc_channel_power_enable(channel, false);
-	if (rc) {
-		rc = -EINVAL;
-		goto fail_unlock;
-	}
-
-	mutex_unlock(&adc_pmic->adc_lock);
-
-	return 0;
-fail:
-	rc_fail = pm8921_adc_channel_power_enable(channel, false);
-	if (rc_fail)
-		pr_err("pm8921 adc power disable failed\n");
-fail_unlock:
-	mutex_unlock(&adc_pmic->adc_lock);
-	pr_err("pm8921 adc error with %d\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_read);
-
-uint32_t pm8921_adc_mpp_config_read(uint32_t mpp_num,
-			enum pm8921_adc_channels channel,
-			struct pm8921_adc_chan_result *result)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc = 0;
-
-	if (!adc_pmic->mpp_base) {
-		rc = -EINVAL;
-		pr_info("PM8921 MPP base invalid with error %d\n", rc);
-		return rc;
-	}
-
-	if (mpp_num == PM8921_AMUX_MPP_8) {
-		rc = -EINVAL;
-		pr_info("PM8921 MPP8 is already configured "
-			"to AMUX8. Use pm8921_adc_read() instead.\n");
-		return rc;
-	}
-
-	mutex_lock(&adc_pmic->mpp_adc_lock);
-
-	rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
-					&pm8921_adc_mpp_config);
-	if (rc < 0) {
-		pr_err("pm8921 adc mpp config error with %d\n", rc);
-		goto fail;
-	}
-
-	usleep_range(PM8921_ADC_MPP_SETTLE_TIME_MIN,
-					PM8921_ADC_MPP_SETTLE_TIME_MAX);
-
-	rc = pm8921_adc_read(channel, result);
-	if (rc < 0)
-		pr_err("pm8921 adc read error with %d\n", rc);
-
-	rc = pm8xxx_mpp_config(((mpp_num - 1) + adc_pmic->mpp_base),
-					&pm8921_adc_mpp_unconfig);
-	if (rc < 0)
-		pr_err("pm8921 adc mpp config error with %d\n", rc);
-fail:
-	mutex_unlock(&adc_pmic->mpp_adc_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_mpp_config_read);
-
-uint32_t pm8921_adc_btm_configure(struct pm8921_adc_arb_btm_param *btm_param)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	u8 data_btm_cool_thr0, data_btm_cool_thr1;
-	u8 data_btm_warm_thr0, data_btm_warm_thr1;
-	u8 arb_btm_cntrl1;
-	unsigned long flags = 0;
-	int rc;
-
-	if (adc_pmic == NULL) {
-		pr_err("PMIC ADC not valid\n");
-		return -EINVAL;
-	}
-
-	if ((btm_param->btm_cool_fn == NULL) &&
-		(btm_param->btm_warm_fn == NULL)) {
-		pr_err("No BTM warm/cool notification??\n");
-		return -EINVAL;
-	}
-
-	rc = pm8921_adc_batt_scaler(btm_param, adc_pmic->adc_prop,
-					adc_pmic->conv->chan_prop);
-	if (rc < 0) {
-		pr_err("Failed to lookup the BTM thresholds\n");
-		return rc;
-	}
-
-	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-
-	data_btm_cool_thr0 = ((btm_param->low_thr_voltage << 24) >> 24);
-	data_btm_cool_thr1 = ((btm_param->low_thr_voltage << 16) >> 24);
-	data_btm_warm_thr0 = ((btm_param->high_thr_voltage << 24) >> 24);
-	data_btm_warm_thr1 = ((btm_param->high_thr_voltage << 16) >> 24);
-
-	if (btm_param->btm_cool_fn != NULL) {
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_BAT_COOL_THR0,
-							data_btm_cool_thr0);
-		if (rc < 0)
-			goto write_err;
-
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_BAT_COOL_THR1,
-							data_btm_cool_thr1);
-		if (rc < 0)
-			goto write_err;
-
-		adc_pmic->batt->btm_cool_fn = btm_param->btm_cool_fn;
-	}
-
-	if (btm_param->btm_warm_fn != NULL) {
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_BAT_WARM_THR0,
-							data_btm_warm_thr0);
-		if (rc < 0)
-			goto write_err;
-
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_BAT_WARM_THR1,
-							data_btm_warm_thr1);
-		if (rc < 0)
-			goto write_err;
-
-		adc_pmic->batt->btm_warm_fn = btm_param->btm_warm_fn;
-	}
-
-	rc = pm8921_adc_read_reg(PM8921_ADC_ARB_BTM_CNTRL1, &arb_btm_cntrl1);
-	if (rc < 0)
-		goto bail_out;
-
-	btm_param->interval &= PM8921_ADC_BTM_INTERVAL_SEL_MASK;
-	arb_btm_cntrl1 |=
-		btm_param->interval << PM8921_ADC_BTM_INTERVAL_SEL_SHIFT;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_CNTRL1, arb_btm_cntrl1);
-	if (rc < 0)
-		goto write_err;
-
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-
-	return rc;
-bail_out:
-write_err:
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-	pr_debug("%s: with error code %d\n", __func__, rc);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_btm_configure);
-
-static uint32_t pm8921_adc_btm_read(uint32_t channel)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc, i;
-	u8 arb_btm_dig_param, arb_btm_ana_param, arb_btm_rsv;
-	u8 arb_btm_amux_cntrl, data_arb_btm_cntrl = 0;
-	unsigned long flags;
-
-	arb_btm_amux_cntrl = channel << PM8921_ADC_BTM_CHANNEL_SEL;
-	arb_btm_rsv = adc_pmic->adc_channel[channel].adc_rsv;
-	arb_btm_dig_param = arb_btm_ana_param = PM8921_ADC_ARB_ANA_DIG;
-
-	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_AMUX_CNTRL,
-						arb_btm_amux_cntrl);
-	if (rc < 0)
-		goto write_err;
-
-	arb_btm_rsv = PM8921_ADC_BTM_RSV;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_RSV, arb_btm_rsv);
-	if (rc < 0)
-		goto write_err;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_DIG_PARAM,
-						arb_btm_dig_param);
-	if (rc < 0)
-		goto write_err;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_ANA_PARAM,
-						arb_btm_ana_param);
-	if (rc < 0)
-		goto write_err;
-
-	data_arb_btm_cntrl |= PM8921_ADC_ARB_BTM_CNTRL1_EN_BTM;
-
-	for (i = 0; i < 2; i++) {
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_CNTRL1,
-						data_arb_btm_cntrl);
-		if (rc < 0)
-			goto write_err;
-	}
-
-	data_arb_btm_cntrl |= PM8921_ADC_ARB_BTM_CNTRL1_REQ
-				| PM8921_ADC_ARB_BTM_CNTRL1_SEL_OP_MODE;
-
-	rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_CNTRL1,
-					data_arb_btm_cntrl);
-	if (rc < 0)
-		goto write_err;
-
-	if (pmic_adc->batt->btm_warm_fn != NULL)
-		enable_irq(adc_pmic->btm_warm_irq);
-
-	if (pmic_adc->batt->btm_cool_fn != NULL)
-		enable_irq(adc_pmic->btm_cool_irq);
-
-write_err:
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-	return rc;
-}
-
-uint32_t pm8921_adc_btm_start(void)
-{
-	return pm8921_adc_btm_read(CHANNEL_BATT_THERM);
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_btm_start);
-
-uint32_t pm8921_adc_btm_end(void)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int i, rc;
-	u8 data_arb_btm_cntrl;
-	unsigned long flags;
-
-	disable_irq_nosync(adc_pmic->btm_warm_irq);
-	disable_irq_nosync(adc_pmic->btm_cool_irq);
-
-	spin_lock_irqsave(&adc_pmic->btm_lock, flags);
-	/* Set BTM registers to Disable mode */
-	rc = pm8921_adc_read_reg(PM8921_ADC_ARB_BTM_CNTRL1,
-						&data_arb_btm_cntrl);
-	if (rc < 0) {
-		spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-		return rc;
-	}
-
-	data_arb_btm_cntrl |= ~PM8921_ADC_ARB_BTM_CNTRL1_EN_BTM;
-	/* Write twice to the CNTRL register for the arbiter settings
-	   to take into effect */
-	for (i = 0; i < 2; i++) {
-		rc = pm8921_adc_write_reg(PM8921_ADC_ARB_BTM_CNTRL1,
-							data_arb_btm_cntrl);
-		if (rc < 0) {
-			spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-			return rc;
-		}
-	}
-
-	spin_unlock_irqrestore(&adc_pmic->btm_lock, flags);
-
-	return rc;
-}
-EXPORT_SYMBOL_GPL(pm8921_adc_btm_end);
-
-static ssize_t pm8921_adc_show(struct device *dev,
-			struct device_attribute *devattr, char *buf)
-{
-	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	struct pm8921_adc_chan_result result;
-	int rc = -1;
-
-	if (attr->index < adc_pmic->adc_num_channel)
-		rc = pm8921_adc_read(attr->index, &result);
-
-	if (rc)
-		return 0;
-
-	return snprintf(buf, sizeof(struct pm8921_adc_chan_result),
-				"Result:%lld Raw:%d\n",
-				result.physical, result.adc_code);
-}
-
-static int get_adc(void *data, u64 *val)
-{
-	struct pm8921_adc_chan_result result;
-	int i = (int)data;
-	int rc;
-
-	rc = pm8921_adc_read(i, &result);
-	if (!rc)
-		pr_info("ADC value raw:%x physical:%lld\n",
-			result.adc_code, result.physical);
-	*val = result.physical;
-
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(reg_fops, get_adc, NULL, "%llu\n");
-
-static int get_mpp_adc(void *data, u64 *val)
-{
-	struct pm8921_adc_chan_result result;
-	int i = (int)data;
-	int rc;
-
-	rc = pm8921_adc_mpp_config_read(i,
-		ADC_MPP_1_AMUX6, &result);
-	if (!rc)
-		pr_info("ADC MPP value raw:%x physical:%lld\n",
-			result.adc_code, result.physical);
-	*val = result.physical;
-
-	return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(reg_mpp_fops, get_mpp_adc, NULL, "%llu\n");
-
-#ifdef CONFIG_DEBUG_FS
-static void create_debugfs_entries(void)
-{
-	pmic_adc->dent = debugfs_create_dir("pm8921_adc", NULL);
-
-	if (IS_ERR(pmic_adc->dent)) {
-		pr_err("pmic adc debugfs dir not created\n");
-		return;
-	}
-
-	debugfs_create_file("vbat", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_VBAT, &reg_fops);
-	debugfs_create_file("625mv", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_625MV, &reg_fops);
-	debugfs_create_file("125v", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_125V, &reg_fops);
-	debugfs_create_file("die_temp", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_DIE_TEMP, &reg_fops);
-	debugfs_create_file("vcoin", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_VCOIN, &reg_fops);
-	debugfs_create_file("dc_in", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_DCIN, &reg_fops);
-	debugfs_create_file("vph_pwr", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_VPH_PWR, &reg_fops);
-	debugfs_create_file("usb_in", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_USBIN, &reg_fops);
-	debugfs_create_file("batt_therm", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_BATT_THERM, &reg_fops);
-	debugfs_create_file("batt_id", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_BATT_ID, &reg_fops);
-	debugfs_create_file("chg_temp", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_CHG_TEMP, &reg_fops);
-	debugfs_create_file("charger_current", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_ICHG, &reg_fops);
-	debugfs_create_file("ibat", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_IBAT, &reg_fops);
-	debugfs_create_file("pa_therm1", 0644, pmic_adc->dent,
-			    (void *)ADC_MPP_1_AMUX8, &reg_fops);
-	debugfs_create_file("xo_therm", 0644, pmic_adc->dent,
-			    (void *)CHANNEL_MUXOFF, &reg_fops);
-	debugfs_create_file("pa_therm0", 0644, pmic_adc->dent,
-			    (void *)ADC_MPP_1_AMUX3, &reg_fops);
-}
-#else
-static inline void create_debugfs_entries(void)
-{
-}
-#endif
-static struct sensor_device_attribute pm8921_adc_attr =
-	SENSOR_ATTR(NULL, S_IRUGO, pm8921_adc_show, NULL, 0);
-
-static int32_t pm8921_adc_init_hwmon(struct platform_device *pdev)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int rc = 0, i;
-
-	adc_pmic->sens_attr = kzalloc(pmic_adc->adc_num_board_channel *
-		sizeof(struct sensor_device_attribute), GFP_KERNEL);
-
-	if (!adc_pmic->sens_attr) {
-		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		rc = -ENOMEM;
-		goto hwmon_err_sens;
-	}
-
-	for (i = 0; i < pmic_adc->adc_num_board_channel; i++) {
-		pm8921_adc_attr.index = adc_pmic->adc_channel[i].channel_name;
-		pm8921_adc_attr.dev_attr.attr.name =
-						adc_pmic->adc_channel[i].name;
-		memcpy(&adc_pmic->sens_attr[i], &pm8921_adc_attr,
-						sizeof(pm8921_adc_attr));
-		rc = device_create_file(&pdev->dev,
-				&adc_pmic->sens_attr[i].dev_attr);
-		if (rc) {
-			dev_err(&pdev->dev, "device_create_file failed for "
-					    "dev %s\n",
-					    adc_pmic->adc_channel[i].name);
-			goto hwmon_err_sens;
-		}
-	}
-	return 0;
-
-hwmon_err_sens:
-	pr_info("Init HWMON failed for pm8921_adc with %d\n", rc);
-	return rc;
-}
-
-#ifdef CONFIG_PM
-static int pm8921_adc_suspend_noirq(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct pm8921_adc *adc_pmic = platform_get_drvdata(pdev);
-
-	adc_pmic->msm_suspend_check = 1;
-
-	return 0;
-}
-
-static int pm8921_adc_resume_noirq(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct pm8921_adc *adc_pmic = platform_get_drvdata(pdev);
-
-	adc_pmic->msm_suspend_check = 0;
-
-	return 0;
-}
-
-static const struct dev_pm_ops pm8921_adc_dev_pm_ops = {
-	.suspend_noirq = pm8921_adc_suspend_noirq,
-	.resume_noirq = pm8921_adc_resume_noirq,
-};
-
-#define PM8921_ADC_DEV_PM_OPS	(&pm8921_adc_dev_pm_ops)
-#else
-#define PM8921_ADC_DEV_PM_OPS	NULL
-#endif
-
-static int __devexit pm8921_adc_teardown(struct platform_device *pdev)
-{
-	struct pm8921_adc *adc_pmic = pmic_adc;
-	int i;
-
-	wake_lock_destroy(&adc_pmic->adc_wakelock);
-	free_irq(adc_pmic->adc_irq, adc_pmic);
-	free_irq(adc_pmic->btm_warm_irq, adc_pmic);
-	free_irq(adc_pmic->btm_cool_irq, adc_pmic);
-	platform_set_drvdata(pdev, NULL);
-	pmic_adc = NULL;
-	kfree(adc_pmic->conv->chan_prop);
-	kfree(adc_pmic->adc_channel);
-	kfree(adc_pmic->batt);
-	for (i = 0; i < adc_pmic->adc_num_board_channel; i++)
-		device_remove_file(adc_pmic->dev,
-				&adc_pmic->sens_attr[i].dev_attr);
-	kfree(adc_pmic->sens_attr);
-	kfree(adc_pmic);
-	pm8921_adc_initialized = false;
-
-	return 0;
-}
-
-static int __devinit pm8921_adc_probe(struct platform_device *pdev)
-{
-	const struct pm8921_adc_platform_data *pdata = pdev->dev.platform_data;
-	struct pm8921_adc *adc_pmic;
-	struct pm8921_adc_amux_properties *adc_amux_prop;
-	struct pm8921_adc_chan_properties *adc_pmic_chanprop;
-	struct pm8921_adc_arb_btm_param *adc_btm;
-	int rc = 0;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data?\n");
-		return -EINVAL;
-	}
-
-	adc_pmic = kzalloc(sizeof(struct pm8921_adc),
-						GFP_KERNEL);
-	if (!adc_pmic) {
-		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	adc_amux_prop = kzalloc(sizeof(struct pm8921_adc_amux_properties),
-						GFP_KERNEL);
-	if (!adc_amux_prop) {
-		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	adc_pmic_chanprop = kzalloc(sizeof(struct pm8921_adc_chan_properties),
-						GFP_KERNEL);
-	if (!adc_pmic_chanprop) {
-		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	adc_btm = kzalloc(sizeof(struct pm8921_adc_arb_btm_param),
-						GFP_KERNEL);
-	if (!adc_btm) {
-		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	adc_pmic->dev = &pdev->dev;
-	adc_pmic->adc_prop = pdata->adc_prop;
-	adc_pmic->conv = adc_amux_prop;
-	adc_pmic->conv->chan_prop = adc_pmic_chanprop;
-	adc_pmic->batt = adc_btm;
-
-	init_completion(&adc_pmic->adc_rslt_completion);
-	adc_pmic->adc_channel = pdata->adc_channel;
-	adc_pmic->adc_num_board_channel = pdata->adc_num_board_channel;
-	adc_pmic->adc_num_channel = ADC_MPP_2_CHANNEL_NONE;
-	adc_pmic->mpp_base = pdata->adc_mpp_base;
-
-	mutex_init(&adc_pmic->adc_lock);
-	mutex_init(&adc_pmic->mpp_adc_lock);
-	spin_lock_init(&adc_pmic->btm_lock);
-
-	adc_pmic->adc_irq = platform_get_irq(pdev, PM8921_ADC_IRQ_0);
-	if (adc_pmic->adc_irq < 0) {
-		rc = -ENXIO;
-		goto err_cleanup;
-	}
-
-	rc = request_irq(adc_pmic->adc_irq,
-				pm8921_adc_isr,
-		IRQF_TRIGGER_RISING, "pm8921_adc_interrupt", adc_pmic);
-	if (rc) {
-		dev_err(&pdev->dev, "failed to request adc irq "
-						"with error %d\n", rc);
-		goto err_cleanup;
-	}
-
-	disable_irq_nosync(adc_pmic->adc_irq);
-
-	adc_pmic->btm_warm_irq = platform_get_irq(pdev, PM8921_ADC_IRQ_1);
-	if (adc_pmic->btm_warm_irq < 0) {
-		rc = -ENXIO;
-		goto err_cleanup;
-	}
-
-	rc = request_irq(adc_pmic->btm_warm_irq,
-				pm8921_btm_warm_isr,
-		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-			"pm8921_btm_warm_interrupt", adc_pmic);
-	if (rc) {
-		pr_err("btm warm irq failed %d with interrupt number %d\n",
-						rc, adc_pmic->btm_warm_irq);
-		dev_err(&pdev->dev, "failed to request btm irq\n");
-		goto err_cleanup;
-	}
-
-	disable_irq_nosync(adc_pmic->btm_warm_irq);
-
-	adc_pmic->btm_cool_irq = platform_get_irq(pdev, PM8921_ADC_IRQ_2);
-	if (adc_pmic->btm_cool_irq < 0) {
-		rc = -ENXIO;
-		goto err_cleanup;
-	}
-
-	rc = request_irq(adc_pmic->btm_cool_irq,
-				pm8921_btm_cool_isr,
-		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
-			"pm8921_btm_cool_interrupt", adc_pmic);
-	if (rc) {
-		pr_err("btm cool irq failed with return %d and number %d\n",
-						rc, adc_pmic->btm_cool_irq);
-		dev_err(&pdev->dev, "failed to request btm irq\n");
-		goto err_cleanup;
-	}
-
-	disable_irq_nosync(adc_pmic->btm_cool_irq);
-	platform_set_drvdata(pdev, adc_pmic);
-	pmic_adc = adc_pmic;
-
-	INIT_WORK(&adc_pmic->warm_work, pm8921_adc_btm_warm_scheduler_fn);
-	INIT_WORK(&adc_pmic->cool_work, pm8921_adc_btm_cool_scheduler_fn);
-	wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
-					"pm8921_adc_wakelock");
-	create_debugfs_entries();
-	pm8921_adc_calib_first_adc = false;
-	pm8921_adc_calib_device_init = false;
-	pm8921_adc_initialized = true;
-
-	rc = pm8921_adc_init_hwmon(pdev);
-	if (rc) {
-		pr_err("pm8921 adc init hwmon failed with %d\n", rc);
-		goto err_cleanup;
-	}
-	adc_pmic->hwmon = hwmon_device_register(adc_pmic->dev);
-	return 0;
-
-err_cleanup:
-	pm8921_adc_teardown(pdev);
-	return rc;
-}
-
-static struct platform_driver pm8921_adc_driver = {
-	.probe	= pm8921_adc_probe,
-	.remove	= __devexit_p(pm8921_adc_teardown),
-	.driver	= {
-		.name	= PM8921_ADC_DEV_NAME,
-		.owner	= THIS_MODULE,
-		.pm	= PM8921_ADC_DEV_PM_OPS,
-	},
-};
-
-static int __init pm8921_adc_init(void)
-{
-	return platform_driver_register(&pm8921_adc_driver);
-}
-module_init(pm8921_adc_init);
-
-static void __exit pm8921_adc_exit(void)
-{
-	platform_driver_unregister(&pm8921_adc_driver);
-}
-module_exit(pm8921_adc_exit);
-
-MODULE_ALIAS("platform:" PM8921_ADC_DEV_NAME);
-MODULE_DESCRIPTION("PMIC8921 ADC driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/atmel_maxtouch.c b/drivers/input/touchscreen/atmel_maxtouch.c
index 35507e1..e397774 100644
--- a/drivers/input/touchscreen/atmel_maxtouch.c
+++ b/drivers/input/touchscreen/atmel_maxtouch.c
@@ -1878,7 +1878,7 @@
 			       const struct i2c_device_id *id)
 {
 	struct mxt_data          *mxt;
-	struct mxt_platform_data *pdata;
+	struct maxtouch_platform_data *pdata;
 	struct input_dev         *input;
 	u8 *id_data;
 	u8 *t38_data;
diff --git a/drivers/input/touchscreen/cyttsp_fw.h b/drivers/input/touchscreen/cyttsp_fw.h
old mode 100755
new mode 100644
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
index 50ca58c..ca98754 100644
--- a/drivers/media/radio/radio-iris-transport.c
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -85,8 +85,10 @@
 	len = smd_write(hs.fm_channel, skb->data, skb->len);
 	if (len < skb->len) {
 		FMDERR("Failed to write Data %d", len);
+		kfree_skb(skb);
 		return -ENODEV;
 	}
+	kfree_skb(skb);
 	return 0;
 }
 
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 2d42e17..5e70607 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1352,18 +1352,30 @@
 	return ret;
 }
 
-static int hci_fm_set_cal_req(struct radio_hci_dev *hdev,
+static int hci_fm_set_cal_req_proc(struct radio_hci_dev *hdev,
 		unsigned long param)
 {
 	u16 opcode = 0;
-	struct hci_fm_set_cal_req *cal_req =
-		(struct hci_fm_set_cal_req *)param;
+	struct hci_fm_set_cal_req_proc *cal_req =
+		(struct hci_fm_set_cal_req_proc *)param;
 
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_CALIBRATION);
-	return radio_hci_send_cmd(hdev, opcode, sizeof((*hci_fm_set_cal_req)),
+	return radio_hci_send_cmd(hdev, opcode, sizeof(*cal_req),
 		cal_req);
+}
 
+static int hci_fm_set_cal_req_dc(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = 0;
+	struct hci_fm_set_cal_req_dc *cal_req =
+		(struct hci_fm_set_cal_req_dc *)param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_CALIBRATION);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(*cal_req),
+		cal_req);
 }
 
 static int hci_fm_do_cal_req(struct radio_hci_dev *hdev,
@@ -2525,7 +2537,8 @@
 	struct hci_fm_tx_ps tx_ps;
 	struct hci_fm_tx_rt tx_rt;
 	struct hci_fm_def_data_wr_req default_data;
-	struct hci_fm_set_cal_req cal_req;
+	struct hci_fm_set_cal_req_proc proc_cal_req;
+	struct hci_fm_set_cal_req_dc dc_cal_req;
 
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	char *data = NULL;
@@ -2579,24 +2592,33 @@
 		retval = hci_def_data_write(&default_data, radio->fm_hdev);
 			break;
 	case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
-		FMDERR("In Set Calibration");
 		data = (ctrl->controls[0]).string;
 		bytes_to_copy = (ctrl->controls[0]).size;
-		memset(cal_req.data, 0, MAX_CALIB_SIZE);
-		cal_req.mode = PROCS_CALIB_MODE;
-		if (copy_from_user(&cal_req.data[0],
-				data, PROCS_CALIB_SIZE))
+		if (bytes_to_copy < (PROCS_CALIB_SIZE + DC_CALIB_SIZE)) {
+			FMDERR("data is less than required size");
+			return -EFAULT;
+		}
+		memset(proc_cal_req.data, 0, PROCS_CALIB_SIZE);
+		proc_cal_req.mode = PROCS_CALIB_MODE;
+		if (copy_from_user(&proc_cal_req.data[0],
+				data, sizeof(proc_cal_req.data)))
 				return -EFAULT;
-		retval = radio_hci_request(radio->fm_hdev, hci_fm_set_cal_req,
-				(unsigned long)&cal_req, RADIO_HCI_TIMEOUT);
-		if (retval < 0)
+		retval = radio_hci_request(radio->fm_hdev,
+				hci_fm_set_cal_req_proc,
+				(unsigned long)&proc_cal_req,
+				 RADIO_HCI_TIMEOUT);
+		if (retval < 0) {
 			FMDERR("Set Process calibration failed %d", retval);
-		if (copy_from_user(&cal_req.data[PROCS_CALIB_SIZE],
-				data, DC_CALIB_SIZE))
+			return retval;
+		}
+		memset(dc_cal_req.data, 0, DC_CALIB_SIZE);
+		if (copy_from_user(&dc_cal_req.data[0], &data[PROCS_CALIB_SIZE],
+				sizeof(dc_cal_req.data)))
 				return -EFAULT;
-		cal_req.mode = DC_CALIB_MODE;
-		retval = radio_hci_request(radio->fm_hdev, hci_fm_set_cal_req,
-				(unsigned long)&cal_req, RADIO_HCI_TIMEOUT);
+		dc_cal_req.mode = DC_CALIB_MODE;
+		retval = radio_hci_request(radio->fm_hdev,
+				hci_fm_set_cal_req_dc,
+				(unsigned long)&dc_cal_req, RADIO_HCI_TIMEOUT);
 		if (retval < 0)
 			FMDERR("Set DC calibration failed %d", retval);
 		break;
@@ -2676,6 +2698,14 @@
 				FMDERR("Failed to set stereo mode\n");
 				return retval;
 			}
+			radio->event_mask = SIG_LEVEL_INTR |
+						RDS_SYNC_INTR | AUDIO_CTRL_INTR;
+			retval = hci_conf_event_mask(&radio->event_mask,
+							radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Enable Async events failed");
+				return retval;
+			}
 			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
 						radio->fm_hdev);
 			if (retval < 0)
@@ -3180,6 +3210,9 @@
 		if ((i == IRIS_BUF_RAW_RDS) || (i == IRIS_BUF_PEEK))
 			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
 				rds_buf*3, GFP_KERNEL);
+		else if (i == IRIS_BUF_CAL_DATA)
+			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
+				STD_BUF_SIZE*2, GFP_KERNEL);
 		else
 			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
 				STD_BUF_SIZE, GFP_KERNEL);
diff --git a/drivers/media/video/msm/msm_io_vfe31.c b/drivers/media/video/msm/msm_io_vfe31.c
index 1cd731c..f770ce9 100644
--- a/drivers/media/video/msm/msm_io_vfe31.c
+++ b/drivers/media/video/msm/msm_io_vfe31.c
@@ -111,11 +111,6 @@
 static struct clk *camio_jpeg_clk;
 static struct clk *camio_jpeg_pclk;
 static struct clk *camio_vpe_clk;
-static struct vreg *vreg_gp2;
-static struct vreg *vreg_lvsw1;
-static struct vreg *vreg_gp6;
-static struct vreg *vreg_gp16;
-static struct regulator *fs_vfe;
 static struct regulator *fs_vpe;
 static struct msm_camera_io_ext camio_ext;
 static struct msm_camera_io_clk camio_clk;
@@ -123,6 +118,17 @@
 void __iomem *camifpadbase, *csibase;
 static uint32_t vpe_clk_rate;
 
+static struct regulator_bulk_data regs[] = {
+	{ .supply = "gp2",  .min_uV = 2600000, .max_uV = 2600000 },
+	{ .supply = "lvsw1" },
+	{ .supply = "fs_vfe" },
+	/* sn12m0pz regulators */
+	{ .supply = "gp6",  .min_uV = 3050000, .max_uV = 3100000 },
+	{ .supply = "gp16", .min_uV = 1200000, .max_uV = 1200000 },
+};
+
+static int reg_count;
+
 void msm_io_w(u32 data, void __iomem *addr)
 {
 	CDBG("%s: %08x %08x\n", __func__, (int) (addr), (data));
@@ -201,135 +207,54 @@
 
 static void msm_camera_vreg_enable(struct platform_device *pdev)
 {
-	vreg_gp2 = vreg_get(NULL, "gp2");
-	if (IS_ERR(vreg_gp2)) {
-		pr_err("%s: VREG GP2 get failed %ld\n", __func__,
-			PTR_ERR(vreg_gp2));
-		vreg_gp2 = NULL;
+	int count, rc;
+
+	struct device *dev = &pdev->dev;
+
+	/* Use gp6 and gp16 if and only if dev name matches. */
+	if (!strncmp(pdev->name, "msm_camera_sn12m0pz", 20))
+		count = ARRAY_SIZE(regs);
+	else
+		count = ARRAY_SIZE(regs) - 2;
+
+	rc = regulator_bulk_get(dev, count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not get regulators: %d\n",
+				__func__, rc);
 		return;
 	}
 
-	if (vreg_set_level(vreg_gp2, 2600)) {
-		pr_err("%s: VREG GP2 set failed\n", __func__);
-		goto gp2_put;
+	rc = regulator_bulk_set_voltage(count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not set voltages: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
 
-	if (vreg_enable(vreg_gp2)) {
-		pr_err("%s: VREG GP2 enable failed\n", __func__);
-		goto gp2_put;
+	rc = regulator_bulk_enable(count, regs);
+
+	if (rc) {
+		dev_err(dev, "%s: could not enable regulators: %d\n",
+				__func__, rc);
+		goto reg_free;
 	}
 
-	vreg_lvsw1 = vreg_get(NULL, "lvsw1");
-	if (IS_ERR(vreg_lvsw1)) {
-		pr_err("%s: VREG LVSW1 get failed %ld\n", __func__,
-			PTR_ERR(vreg_lvsw1));
-		vreg_lvsw1 = NULL;
-		goto gp2_disable;
-		}
-	if (vreg_set_level(vreg_lvsw1, 1800)) {
-		pr_err("%s: VREG LVSW1 set failed\n", __func__);
-		goto lvsw1_put;
-	}
-	if (vreg_enable(vreg_lvsw1)) {
-		pr_err("%s: VREG LVSW1 enable failed\n", __func__);
-		goto lvsw1_put;
-	}
-
-	if (!strcmp(pdev->name, "msm_camera_sn12m0pz")) {
-		vreg_gp6 = vreg_get(NULL, "gp6");
-		if (IS_ERR(vreg_gp6)) {
-			pr_err("%s: VREG GP6 get failed %ld\n", __func__,
-				PTR_ERR(vreg_gp6));
-			vreg_gp6 = NULL;
-			goto lvsw1_disable;
-		}
-
-		if (vreg_set_level(vreg_gp6, 3050)) {
-			pr_err("%s: VREG GP6 set failed\n", __func__);
-			goto gp6_put;
-		}
-
-		if (vreg_enable(vreg_gp6)) {
-			pr_err("%s: VREG GP6 enable failed\n", __func__);
-			goto gp6_put;
-		}
-		vreg_gp16 = vreg_get(NULL, "gp16");
-		if (IS_ERR(vreg_gp16)) {
-			pr_err("%s: VREG GP16 get failed %ld\n", __func__,
-				PTR_ERR(vreg_gp16));
-			vreg_gp16 = NULL;
-			goto gp6_disable;
-		}
-
-		if (vreg_set_level(vreg_gp16, 1200)) {
-			pr_err("%s: VREG GP16 set failed\n", __func__);
-			goto gp16_put;
-		}
-
-		if (vreg_enable(vreg_gp16)) {
-			pr_err("%s: VREG GP16 enable failed\n", __func__);
-			goto gp16_put;
-		}
-	}
-
-	fs_vfe = regulator_get(NULL, "fs_vfe");
-	if (IS_ERR(fs_vfe)) {
-		pr_err("%s: Regulator FS_VFE get failed %ld\n", __func__,
-			PTR_ERR(fs_vfe));
-		fs_vfe = NULL;
-	} else if (regulator_enable(fs_vfe)) {
-		pr_err("%s: Regulator FS_VFE enable failed\n", __func__);
-		regulator_put(fs_vfe);
-	}
-
+	reg_count = count;
 	return;
 
-gp16_put:
-	vreg_put(vreg_gp16);
-	vreg_gp16 = NULL;
-gp6_disable:
-	 vreg_disable(vreg_gp6);
-gp6_put:
-	vreg_put(vreg_gp6);
-	vreg_gp6 = NULL;
-lvsw1_disable:
-	vreg_disable(vreg_lvsw1);
-lvsw1_put:
-	vreg_put(vreg_lvsw1);
-	vreg_lvsw1 = NULL;
-gp2_disable:
-	vreg_disable(vreg_gp2);
-gp2_put:
-	vreg_put(vreg_gp2);
-	vreg_gp2 = NULL;
+reg_free:
+	regulator_bulk_free(count, regs);
+	return;
 }
 
+
 static void msm_camera_vreg_disable(void)
 {
-	if (vreg_gp2) {
-		vreg_disable(vreg_gp2);
-		vreg_put(vreg_gp2);
-		vreg_gp2 = NULL;
-	}
-	if (vreg_lvsw1) {
-		vreg_disable(vreg_lvsw1);
-		vreg_put(vreg_lvsw1);
-		vreg_lvsw1 = NULL;
-	}
-	if (vreg_gp6) {
-		vreg_disable(vreg_gp6);
-		vreg_put(vreg_gp6);
-		vreg_gp6 = NULL;
-	}
-	if (vreg_gp16) {
-		vreg_disable(vreg_gp16);
-		vreg_put(vreg_gp16);
-		vreg_gp16 = NULL;
-	}
-	if (fs_vfe) {
-		regulator_disable(fs_vfe);
-		regulator_put(fs_vfe);
-	}
+	regulator_bulk_disable(reg_count, regs);
+	regulator_bulk_free(reg_count, regs);
+	reg_count = 0;
 }
 
 int msm_camio_clk_enable(enum msm_camio_clk_type clktype)
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index 99cc2d4..2923e5d 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -315,12 +315,6 @@
 	.sensor_stop_stream = msm_sensor_stop_stream,
 	.sensor_group_hold_on = msm_sensor_group_hold_on,
 	.sensor_group_hold_off = msm_sensor_group_hold_off,
-	.sensor_get_prev_lines_pf = msm_sensor_get_prev_lines_pf,
-	.sensor_get_prev_pixels_pl = msm_sensor_get_prev_pixels_pl,
-	.sensor_get_pict_lines_pf = msm_sensor_get_pict_lines_pf,
-	.sensor_get_pict_pixels_pl = msm_sensor_get_pict_pixels_pl,
-	.sensor_get_pict_max_exp_lc = msm_sensor_get_pict_max_exp_lc,
-	.sensor_get_pict_fps = msm_sensor_get_pict_fps,
 	.sensor_set_fps = msm_sensor_set_fps,
 	.sensor_write_exp_gain = msm_sensor_write_exp_gain1,
 	.sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 76ade6c..7eb3160 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -100,54 +100,6 @@
 		s_ctrl->msm_sensor_reg->default_data_type);
 }
 
-uint16_t msm_sensor_get_prev_lines_pf(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines;
-}
-
-uint16_t msm_sensor_get_prev_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].line_length_pclk;
-}
-
-uint16_t msm_sensor_get_pict_lines_pf(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].frame_length_lines;
-}
-
-uint16_t msm_sensor_get_pict_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].line_length_pclk;
-}
-
-uint32_t msm_sensor_get_pict_max_exp_lc(struct msm_sensor_ctrl_t *s_ctrl)
-{
-	return s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines * 24;
-}
-
-void msm_sensor_get_pict_fps(struct msm_sensor_ctrl_t *s_ctrl,
-			uint16_t fps, uint16_t *pfps)
-{
-	uint32_t divider, d1, d2;
-	d1 = s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].frame_length_lines * Q10 /
-		s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].frame_length_lines;
-
-	d2 = s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->prev_res].line_length_pclk * Q10 /
-		s_ctrl->msm_sensor_reg->
-		output_settings[s_ctrl->pict_res].line_length_pclk;
-
-	divider = d1 * d2 / Q10;
-	*pfps = (uint16_t) (fps * divider / Q10);
-}
-
 int32_t msm_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
 						struct fps_cfg *fps)
 {
@@ -268,15 +220,6 @@
 {
 	int32_t rc = 0;
 	if (s_ctrl->curr_res != res) {
-		switch (mode) {
-		case SENSOR_PREVIEW_MODE:
-			s_ctrl->prev_res = res;
-			break;
-		case SENSOR_SNAPSHOT_MODE:
-		case SENSOR_RAW_SNAPSHOT_MODE:
-			s_ctrl->pict_res = res;
-			break;
-		}
 		s_ctrl->curr_frame_length_lines =
 			s_ctrl->msm_sensor_reg->
 			output_settings[res].frame_length_lines;
@@ -298,27 +241,16 @@
 			int mode, struct sensor_init_cfg *init_info)
 {
 	int32_t rc = 0;
-	s_ctrl->fps = 30*Q8;
 	s_ctrl->fps_divider = Q10;
 	s_ctrl->cam_mode = MSM_SENSOR_MODE_INVALID;
 
 	CDBG("%s: %d\n", __func__, __LINE__);
 	if (mode != s_ctrl->cam_mode) {
-		if (init_info->prev_res >=
-			s_ctrl->msm_sensor_reg->num_conf ||
-			init_info->pict_res >=
-			s_ctrl->msm_sensor_reg->num_conf) {
-			CDBG("Resolution does not exist");
-			return -EINVAL;
-		}
-
-		s_ctrl->prev_res = init_info->prev_res;
-		s_ctrl->pict_res = init_info->pict_res;
 		s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
 		s_ctrl->cam_mode = mode;
 
 		rc = s_ctrl->func_tbl->sensor_setting(s_ctrl,
-			MSM_SENSOR_REG_INIT, s_ctrl->prev_res);
+			MSM_SENSOR_REG_INIT, 0);
 	}
 	return rc;
 }
@@ -349,109 +281,6 @@
 	CDBG("msm_sensor_config: cfgtype = %d\n",
 	cdata.cfgtype);
 		switch (cdata.cfgtype) {
-		case CFG_GET_PICT_FPS:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_fps == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			s_ctrl->func_tbl->
-			sensor_get_pict_fps(
-				s_ctrl,
-				cdata.cfg.gfps.prevfps,
-				&(cdata.cfg.gfps.pictfps));
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PREV_L_PF:
-			if (s_ctrl->func_tbl->
-			sensor_get_prev_lines_pf == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.prevl_pf =
-				s_ctrl->func_tbl->
-				sensor_get_prev_lines_pf
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PREV_P_PL:
-			if (s_ctrl->func_tbl->
-			sensor_get_prev_pixels_pl == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.prevp_pl =
-				s_ctrl->func_tbl->
-				sensor_get_prev_pixels_pl
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_L_PF:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_lines_pf == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pictl_pf =
-				s_ctrl->func_tbl->
-				sensor_get_pict_lines_pf
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_P_PL:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_pixels_pl == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pictp_pl =
-				s_ctrl->func_tbl->
-				sensor_get_pict_pixels_pl
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
-		case CFG_GET_PICT_MAX_EXP_LC:
-			if (s_ctrl->func_tbl->
-			sensor_get_pict_max_exp_lc == NULL) {
-				rc = -EFAULT;
-				break;
-			}
-			cdata.cfg.pict_max_exp_lc =
-				s_ctrl->func_tbl->
-				sensor_get_pict_max_exp_lc
-				(s_ctrl);
-
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
 		case CFG_SET_FPS:
 		case CFG_SET_PICT_FPS:
 			if (s_ctrl->func_tbl->
@@ -506,30 +335,9 @@
 					cdata.rs);
 			break;
 
-		case CFG_PWR_DOWN:
-			break;
-
-		case CFG_MOVE_FOCUS:
-			break;
-
-		case CFG_SET_DEFAULT_FOCUS:
-			break;
-
-		case CFG_GET_AF_MAX_STEPS:
-			cdata.max_steps = 32;
-			if (copy_to_user((void *)argp,
-				&cdata,
-				sizeof(struct sensor_cfg_data)))
-				rc = -EFAULT;
-			break;
-
 		case CFG_SET_EFFECT:
 			break;
 
-
-		case CFG_SEND_WB_INFO:
-			break;
-
 		case CFG_SENSOR_INIT:
 			if (s_ctrl->func_tbl->
 			sensor_mode_init == NULL) {
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 1121170..e4dc34f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -99,18 +99,6 @@
 	void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
 	void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
 
-	uint16_t (*sensor_get_prev_lines_pf)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_prev_pixels_pl)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_pict_lines_pf)
-		(struct msm_sensor_ctrl_t *);
-	uint16_t (*sensor_get_pict_pixels_pl)
-		(struct msm_sensor_ctrl_t *);
-	uint32_t (*sensor_get_pict_max_exp_lc)
-		(struct msm_sensor_ctrl_t *);
-	void (*sensor_get_pict_fps) (struct msm_sensor_ctrl_t *,
-			uint16_t, uint16_t *);
 	int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
 			struct fps_cfg *);
 	int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
@@ -153,10 +141,7 @@
 	uint16_t curr_line_length_pclk;
 	uint16_t curr_frame_length_lines;
 
-	uint16_t fps;
 	uint32_t fps_divider;
-	enum msm_sensor_resolution_t prev_res;
-	enum msm_sensor_resolution_t pict_res;
 	enum msm_sensor_resolution_t curr_res;
 	enum msm_sensor_cam_mode_t cam_mode;
 
@@ -176,13 +161,6 @@
 void msm_sensor_group_hold_on(struct msm_sensor_ctrl_t *s_ctrl);
 void msm_sensor_group_hold_off(struct msm_sensor_ctrl_t *s_ctrl);
 
-uint16_t msm_sensor_get_prev_lines_pf(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_prev_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_pict_lines_pf(struct msm_sensor_ctrl_t *s_ctrl);
-uint16_t msm_sensor_get_pict_pixels_pl(struct msm_sensor_ctrl_t *s_ctrl);
-uint32_t msm_sensor_get_pict_max_exp_lc(struct msm_sensor_ctrl_t *s_ctrl);
-void msm_sensor_get_pict_fps(struct msm_sensor_ctrl_t *s_ctrl,
-			uint16_t fps, uint16_t *pfps);
 int32_t msm_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl,
 			struct fps_cfg   *fps);
 int32_t msm_sensor_write_exp_gain1(struct msm_sensor_ctrl_t *s_ctrl,
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index bdad57c..5938406 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -477,12 +477,6 @@
 	.sensor_stop_stream = msm_sensor_stop_stream,
 	.sensor_group_hold_on = msm_sensor_group_hold_on,
 	.sensor_group_hold_off = msm_sensor_group_hold_off,
-	.sensor_get_prev_lines_pf = msm_sensor_get_prev_lines_pf,
-	.sensor_get_prev_pixels_pl = msm_sensor_get_prev_pixels_pl,
-	.sensor_get_pict_lines_pf = msm_sensor_get_pict_lines_pf,
-	.sensor_get_pict_pixels_pl = msm_sensor_get_pict_pixels_pl,
-	.sensor_get_pict_max_exp_lc = msm_sensor_get_pict_max_exp_lc,
-	.sensor_get_pict_fps = msm_sensor_get_pict_fps,
 	.sensor_set_fps = msm_sensor_set_fps,
 	.sensor_write_exp_gain = ov2720_write_exp_gain,
 	.sensor_write_snapshot_exp_gain = ov2720_write_exp_gain,
diff --git a/drivers/mfd/pm8921-core.c b/drivers/mfd/pm8921-core.c
index d225dfa..51d2224 100644
--- a/drivers/mfd/pm8921-core.c
+++ b/drivers/mfd/pm8921-core.c
@@ -154,7 +154,7 @@
 };
 
 static struct mfd_cell adc_cell __devinitdata = {
-	.name		= PM8921_ADC_DEV_NAME,
+	.name		= PM8XXX_ADC_DEV_NAME,
 	.id		= -1,
 	.resources	= adc_cell_resources,
 	.num_resources	= ARRAY_SIZE(adc_cell_resources),
@@ -304,7 +304,7 @@
 
 static struct pm8xxx_tm_core_data thermal_alarm_cdata = {
 	.adc_channel =			CHANNEL_DIE_TEMP,
-	.adc_type =			PM8XXX_TM_ADC_PM8921_ADC,
+	.adc_type =			PM8XXX_TM_ADC_PM8XXX_ADC,
 	.reg_addr_temp_alarm_ctrl =	REG_TEMP_ALARM_CTRL,
 	.reg_addr_temp_alarm_pwm =	REG_TEMP_ALARM_PWM,
 	.tm_name =			"pm8921_tz",
@@ -461,7 +461,7 @@
 	if (pdata->adc_pdata) {
 		adc_cell.platform_data = pdata->adc_pdata;
 		adc_cell.pdata_size =
-			sizeof(struct pm8921_adc_platform_data);
+			sizeof(struct pm8xxx_adc_platform_data);
 		ret = mfd_add_devices(pmic->dev, 0, &adc_cell, 1, NULL,
 					irq_base);
 		if (ret) {
@@ -616,6 +616,7 @@
 	[PM8XXX_REVISION_8921_1p0]	= "1.0",
 	[PM8XXX_REVISION_8921_1p1]	= "1.1",
 	[PM8XXX_REVISION_8921_2p0]	= "2.0",
+	[PM8XXX_REVISION_8921_3p0]	= "3.0",
 };
 
 static int __devinit pm8921_probe(struct platform_device *pdev)
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index 07bba8b..3d87f0b 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/pmic8901.h>
 #include <linux/platform_device.h>
 #include <linux/debugfs.h>
+#include <linux/delay.h>
 
 /* PMIC8901 Revision */
 #define SSBI_REG_REV			0x002  /* PMIC4 revision */
@@ -65,6 +66,10 @@
 #define REGULATOR_PMR_STATE_MASK	0x60
 #define REGULATOR_PMR_STATE_OFF		0x20
 
+/* Shutdown/restart delays to allow for LDO 7/dVdd regulator load settling. */
+#define DELAY_AFTER_REG_DISABLE_MS	4
+#define DELAY_BEFORE_SHUTDOWN_MS	8
+
 struct pm8901_chip {
 	struct pm8901_platform_data	pdata;
 	struct device			*dev;
@@ -225,10 +230,12 @@
 				       "\n", __func__, pmr_addr[i], pmr, rc);
 				goto get_out;
 			}
+			mdelay(DELAY_AFTER_REG_DISABLE_MS);
 		}
 	}
 
 get_out:
+	mdelay(DELAY_BEFORE_SHUTDOWN_MS);
 	return rc;
 }
 EXPORT_SYMBOL(pm8901_reset_pwr_off);
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index b94de48..692849a 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -1970,6 +1970,13 @@
 	if (!file)
 		return -EBADF;
 
+	/*
+	 * check that the vaddr passed for flushing is valid
+	 * so that you don't crash the kernel
+	 */
+	if (!pmem_addr->vaddr)
+		return -EINVAL;
+
 	data = file->private_data;
 	id = get_id(file);
 
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
old mode 100755
new mode 100644
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 612726c..fa91b53 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -43,7 +43,6 @@
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
-#include <linux/mmc/mmc.h>
 
 #include <asm/cacheflush.h>
 #include <asm/div64.h>
@@ -69,8 +68,6 @@
 #define SPS_SDCC_CONSUMER_PIPE_INDEX	2
 #define SPS_CONS_PERIPHERAL		0
 #define SPS_PROD_PERIPHERAL		1
-/* 16 KB */
-#define SPS_MAX_DESC_SIZE		(16 * 1024)
 
 #if defined(CONFIG_DEBUG_FS)
 static void msmsdcc_dbg_createhost(struct msmsdcc_host *);
@@ -135,6 +132,42 @@
 		      u32 c);
 static inline void msmsdcc_delay(struct msmsdcc_host *host);
 
+static inline unsigned short msmsdcc_get_nr_sg(struct msmsdcc_host *host)
+{
+	unsigned short ret = NR_SG;
+
+	if (host->is_sps_mode) {
+		if (NR_SG > MAX_NR_SG_SPS)
+			ret = MAX_NR_SG_SPS;
+	} else { /* DMA or PIO mode */
+		if (NR_SG > MAX_NR_SG_DMA_PIO)
+			ret = MAX_NR_SG_DMA_PIO;
+	}
+
+	return ret;
+}
+
+static inline unsigned int msmsdcc_get_max_seg_size(struct msmsdcc_host *host)
+{
+	unsigned int max_seg_size;
+
+	/*
+	 * SPS BAM has limitation of max. number of descriptors.
+	 * max. # of descriptors = SPS_MAX_DESCS
+	 * each descriptor can point to SPS_MAX_DESC_SIZE (16KB)
+	 * So (nr_sg * max_seg_size) should be limited to the
+	 * max. size that all of the descriptors can point to.
+	 * i.e., (nr_sg * max_seg_size) = (SPS_MAX_DESCS * SPS_MAX_DESC_SIZE).
+	 */
+	if (host->is_sps_mode) {
+		max_seg_size = (SPS_MAX_DESCS * SPS_MAX_DESC_SIZE) /
+			msmsdcc_get_nr_sg(host);
+	} else { /* DMA or PIO mode */
+		max_seg_size = MMC_MAX_REQ_SIZE;
+	}
+
+	return max_seg_size;
+}
 
 #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
 static int msmsdcc_sps_reset_ep(struct msmsdcc_host *host,
@@ -718,8 +751,9 @@
 	dmov_box *box;
 	uint32_t rows;
 	unsigned int n;
-	int i;
+	int i, err = 0, box_cmd_cnt = 0;
 	struct scatterlist *sg = data->sg;
+	unsigned int len, offset;
 
 	if ((host->dma.channel == -1) || (host->dma.crci == -1))
 		return -ENOENT;
@@ -729,7 +763,8 @@
 	host->dma.sg = data->sg;
 	host->dma.num_ents = data->sg_len;
 
-	BUG_ON(host->dma.num_ents > NR_SG); /* Prevent memory corruption */
+	/* Prevent memory corruption */
+	BUG_ON(host->dma.num_ents > msmsdcc_get_nr_sg(host));
 
 	nc = host->dma.nc;
 
@@ -738,59 +773,8 @@
 	else
 		host->dma.dir = DMA_TO_DEVICE;
 
-	/* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
-	host->curr.user_pages = 0;
-	box = &nc->cmd[0];
-	for (i = 0; i < host->dma.num_ents; i++) {
-		box->cmd = CMD_MODE_BOX;
-
-		/* Initialize sg dma address */
-		sg->dma_address = pfn_to_dma(mmc_dev(host->mmc),
-					      page_to_pfn(sg_page(sg)))
-					      + sg->offset;
-
-		if (i == (host->dma.num_ents - 1))
-			box->cmd |= CMD_LC;
-		rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
-			(sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
-			(sg_dma_len(sg) / MCI_FIFOSIZE) ;
-
-		if (data->flags & MMC_DATA_READ) {
-			box->src_row_addr = msmsdcc_fifo_addr(host);
-			box->dst_row_addr = sg_dma_address(sg);
-
-			box->src_dst_len = (MCI_FIFOSIZE << 16) |
-					   (MCI_FIFOSIZE);
-			box->row_offset = MCI_FIFOSIZE;
-
-			box->num_rows = rows * ((1 << 16) + 1);
-			box->cmd |= CMD_SRC_CRCI(host->dma.crci);
-		} else {
-			box->src_row_addr = sg_dma_address(sg);
-			box->dst_row_addr = msmsdcc_fifo_addr(host);
-
-			box->src_dst_len = (MCI_FIFOSIZE << 16) |
-					   (MCI_FIFOSIZE);
-			box->row_offset = (MCI_FIFOSIZE << 16);
-
-			box->num_rows = rows * ((1 << 16) + 1);
-			box->cmd |= CMD_DST_CRCI(host->dma.crci);
-		}
-		box++;
-		sg++;
-	}
-
-	/* location of command block must be 64 bit aligned */
-	BUG_ON(host->dma.cmd_busaddr & 0x07);
-
-	nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
-	host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
-			       DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
-	host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
-
 	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
 			host->dma.num_ents, host->dma.dir);
-	/* dsb inside dma_map_sg will write nc out to mem as well */
 
 	if (n != host->dma.num_ents) {
 		pr_err("%s: Unable to map in all sg elements\n",
@@ -800,7 +784,79 @@
 		return -ENOMEM;
 	}
 
-	return 0;
+	/* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
+	host->curr.user_pages = 0;
+	box = &nc->cmd[0];
+	for (i = 0; i < host->dma.num_ents; i++) {
+		len = sg_dma_len(sg);
+		offset = 0;
+
+		do {
+			/* Check if we can do DMA */
+			if (!len || (box_cmd_cnt >= MMC_MAX_DMA_CMDS)) {
+				err = -ENOTSUPP;
+				goto unmap;
+			}
+
+			box->cmd = CMD_MODE_BOX;
+
+			if (len >= MMC_MAX_DMA_BOX_LENGTH) {
+				len = MMC_MAX_DMA_BOX_LENGTH;
+				len -= len % data->blksz;
+			}
+			rows = (len % MCI_FIFOSIZE) ?
+				(len / MCI_FIFOSIZE) + 1 :
+				(len / MCI_FIFOSIZE);
+
+			if (data->flags & MMC_DATA_READ) {
+				box->src_row_addr = msmsdcc_fifo_addr(host);
+				box->dst_row_addr = sg_dma_address(sg) + offset;
+				box->src_dst_len = (MCI_FIFOSIZE << 16) |
+						(MCI_FIFOSIZE);
+				box->row_offset = MCI_FIFOSIZE;
+				box->num_rows = rows * ((1 << 16) + 1);
+				box->cmd |= CMD_SRC_CRCI(host->dma.crci);
+			} else {
+				box->src_row_addr = sg_dma_address(sg) + offset;
+				box->dst_row_addr = msmsdcc_fifo_addr(host);
+				box->src_dst_len = (MCI_FIFOSIZE << 16) |
+						(MCI_FIFOSIZE);
+				box->row_offset = (MCI_FIFOSIZE << 16);
+				box->num_rows = rows * ((1 << 16) + 1);
+				box->cmd |= CMD_DST_CRCI(host->dma.crci);
+			}
+
+			offset += len;
+			len = sg_dma_len(sg) - offset;
+			box++;
+			box_cmd_cnt++;
+		} while (len);
+		sg++;
+	}
+	/* Mark last command */
+	box--;
+	box->cmd |= CMD_LC;
+
+	/* location of command block must be 64 bit aligned */
+	BUG_ON(host->dma.cmd_busaddr & 0x07);
+
+	nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
+	host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
+			       DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
+	host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
+
+	/* Flush all data to memory before starting dma */
+	mb();
+
+unmap:
+	if (err) {
+		dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
+				host->dma.num_ents, host->dma.dir);
+		pr_err("%s: cannot do DMA, fall back to PIO mode err=%d\n",
+				mmc_hostname(host->mmc), err);
+	}
+
+	return err;
 }
 
 #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
@@ -826,7 +882,8 @@
 	struct scatterlist *sg = data->sg;
 	struct sps_pipe *sps_pipe_handle;
 
-	BUG_ON(data->sg_len > NR_SG); /* Prevent memory corruption */
+	/* Prevent memory corruption */
+	BUG_ON(data->sg_len > msmsdcc_get_nr_sg(host));
 
 	host->sps.sg = data->sg;
 	host->sps.num_ents = data->sg_len;
@@ -921,9 +978,11 @@
 	if (/*interrupt*/0)
 		*c |= MCI_CPSM_INTERRUPT;
 
-	if ((((cmd->opcode == 17) || (cmd->opcode == 18))  ||
-	     ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
-	      (cmd->opcode == 53))
+	if (cmd->opcode == MMC_READ_SINGLE_BLOCK ||
+		cmd->opcode == MMC_READ_MULTIPLE_BLOCK ||
+		cmd->opcode == MMC_WRITE_BLOCK ||
+		cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK ||
+		cmd->opcode == SD_IO_RW_EXTENDED)
 		*c |= MCI_CSPM_DATCMD;
 
 	/* Check if AUTO CMD19 is required or not? */
@@ -934,10 +993,12 @@
 		 * For close ended block read operation (with CMD23),
 		 * AUTO_CMD19 bit should be set while sending CMD23.
 		 */
-		if ((cmd->opcode == 23 && (host->curr.mrq->cmd->opcode == 17 ||
-			host->curr.mrq->cmd->opcode == 18)) ||
+		if ((cmd->opcode == MMC_SET_BLOCK_COUNT &&
+			host->curr.mrq->cmd->opcode ==
+				MMC_READ_MULTIPLE_BLOCK) ||
 			(!host->curr.mrq->sbc &&
-			(cmd->opcode == 17 || cmd->opcode == 18))) {
+			(cmd->opcode == MMC_READ_SINGLE_BLOCK ||
+			cmd->opcode == MMC_READ_MULTIPLE_BLOCK))) {
 			msmsdcc_enable_cdr_cm_sdc4_dll(host);
 			*c |= MCI_CSPM_AUTO_CMD19;
 		}
@@ -1646,6 +1707,9 @@
 				 * without the need of sending dummy CMD52.
 				 */
 				host->curr.wait_for_auto_prog_done = 1;
+		} else if (mrq->cmd->opcode == MMC_WRITE_BLOCK &&
+				host->sdcc_version) {
+			host->curr.wait_for_auto_prog_done = 1;
 		}
 	}
 
@@ -3022,17 +3086,10 @@
 	 * transfer. It's ignored for BAM-to-System mode transfer.
 	 */
 	sps_config->event_thresh = 0x10;
-	/*
-	 * Max. no of scatter/gather buffers that can
-	 * be passed by block layer = 32 (NR_SG).
-	 * Each BAM descritor needs 64 bits (8 bytes).
-	 * One BAM descriptor is required per buffer transfer.
-	 * So we would require total 256 (32 * 8) bytes of descriptor FIFO.
-	 * But due to HW limitation we need to allocate atleast one extra
-	 * descriptor memory (256 bytes + 8 bytes). But in order to be
-	 * in power of 2, we are allocating 512 bytes of memory.
-	 */
-	sps_config->desc.size = 512;
+
+	/* Allocate maximum descriptor fifo size */
+	sps_config->desc.size = SPS_MAX_DESC_FIFO_SIZE -
+		(SPS_MAX_DESC_FIFO_SIZE % SPS_MAX_DESC_LENGTH);
 	sps_config->desc.base = dma_alloc_coherent(mmc_dev(host->mmc),
 						sps_config->desc.size,
 						&sps_config->desc.phys_base,
@@ -3915,12 +3972,12 @@
 	if (plat->is_sdio_al_client)
 		mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
 
-	mmc->max_segs = NR_SG;
-	mmc->max_blk_size = 4096;	/* MCI_DATA_CTL BLOCKSIZE up to 4096 */
-	mmc->max_blk_count = 65535;
+	mmc->max_segs = msmsdcc_get_nr_sg(host);
+	mmc->max_blk_size = MMC_MAX_BLK_SIZE;
+	mmc->max_blk_count = MMC_MAX_BLK_CNT;
 
-	mmc->max_req_size = 33554432;	/* MCI_DATA_LENGTH is 25 bits */
-	mmc->max_seg_size = mmc->max_req_size;
+	mmc->max_req_size = MMC_MAX_REQ_SIZE;
+	mmc->max_seg_size = msmsdcc_get_max_seg_size(host);
 
 	writel_relaxed(0, host->base + MMCIMASK0);
 	writel_relaxed(MCI_CLEAR_STATIC_MASK, host->base + MMCICLEAR);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 580da82..ca3eed8 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -207,7 +207,7 @@
 
 #define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2)
 
-#define NR_SG		32
+#define NR_SG		128
 
 #define MSM_MMC_IDLE_TIMEOUT	5000 /* msecs */
 
@@ -217,10 +217,46 @@
  */
 #define MSM_MMC_REQ_TIMEOUT	10000 /* msecs */
 
+/*
+ * Controller HW limitations
+ */
+#define MCI_DATALENGTH_BITS	25
+#define MMC_MAX_REQ_SIZE	((1 << MCI_DATALENGTH_BITS) - 1)
+/* MCI_DATA_CTL BLOCKSIZE up to 4096 */
+#define MMC_MAX_BLK_SIZE	4096
+#define MMC_MIN_BLK_SIZE	512
+#define MMC_MAX_BLK_CNT		(MMC_MAX_REQ_SIZE / MMC_MIN_BLK_SIZE)
+
+/* 64KiB */
+#define MAX_SG_SIZE		(64 * 1024)
+#define MAX_NR_SG_DMA_PIO	(MMC_MAX_REQ_SIZE / MAX_SG_SIZE)
+
+/*
+ * BAM limitations
+ */
+/* upto 16 bits (64K - 1) */
+#define SPS_MAX_DESC_FIFO_SIZE	65535
+/* 16KiB */
+#define SPS_MAX_DESC_SIZE	(16 * 1024)
+/* Each descriptor is of length 8 bytes */
+#define SPS_MAX_DESC_LENGTH	8
+#define SPS_MAX_DESCS		(SPS_MAX_DESC_FIFO_SIZE / SPS_MAX_DESC_LENGTH)
+#define SPS_MAX_SG_DESCS	(MAX_SG_SIZE / SPS_MAX_DESC_SIZE)
+#define MAX_NR_SG_SPS		(SPS_MAX_DESCS / SPS_MAX_SG_DESCS)
+
+/*
+ * DMA limitations
+ */
+/* upto 16 bits (64K - 1) */
+#define MMC_MAX_DMA_ROWS (64 * 1024 - 1)
+#define MMC_MAX_DMA_BOX_LENGTH (MMC_MAX_DMA_ROWS * MCI_FIFOSIZE)
+#define MMC_MAX_DMA_CMDS (MAX_NR_SG_DMA_PIO * (MMC_MAX_REQ_SIZE / \
+		MMC_MAX_DMA_BOX_LENGTH))
+
 struct clk;
 
 struct msmsdcc_nc_dmadata {
-	dmov_box	cmd[NR_SG];
+	dmov_box	cmd[MMC_MAX_DMA_CMDS];
 	uint32_t	cmdptr;
 };
 
diff --git a/drivers/platform/msm/sps/Makefile b/drivers/platform/msm/sps/Makefile
old mode 100755
new mode 100644
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 143d9b5..6741ef4 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/mfd/pm8xxx/core.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
@@ -839,9 +839,9 @@
 static int get_battery_uvolts(struct pm8921_bms_chip *chip, int *uvolts)
 {
 	int rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(chip->vbat_channel, &result);
+	rc = pm8xxx_adc_read(chip->vbat_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					chip->vbat_channel, rc);
@@ -1107,9 +1107,9 @@
 static void calib_hkadc(struct pm8921_bms_chip *chip)
 {
 	int voltage, rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(the_chip->ref1p25v_channel, &result);
+	rc = pm8xxx_adc_read(the_chip->ref1p25v_channel, &result);
 	if (rc) {
 		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
 		return;
@@ -1126,7 +1126,7 @@
 		voltage = XOADC_MIN_1P25V;
 	chip->xoadc_v125 = voltage;
 
-	rc = pm8921_adc_read(the_chip->ref625mv_channel, &result);
+	rc = pm8xxx_adc_read(the_chip->ref625mv_channel, &result);
 	if (rc) {
 		pr_err("ADC failed for 1.25volts rc = %d\n", rc);
 		return;
@@ -1210,14 +1210,14 @@
 int pm8921_bms_get_percent_charge(void)
 {
 	int batt_temp, rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
 	if (!the_chip) {
 		pr_err("called before initialization\n");
 		return -EINVAL;
 	}
 
-	rc = pm8921_adc_read(the_chip->batt_temp_channel, &result);
+	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					the_chip->batt_temp_channel, rc);
@@ -1234,14 +1234,14 @@
 int pm8921_bms_get_fcc(void)
 {
 	int batt_temp, rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
 	if (!the_chip) {
 		pr_err("called before initialization\n");
 		return -EINVAL;
 	}
 
-	rc = pm8921_adc_read(the_chip->batt_temp_channel, &result);
+	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					the_chip->batt_temp_channel, rc);
@@ -1266,9 +1266,9 @@
 	if (is_battery_full && the_chip != NULL) {
 		unsigned long flags;
 		int batt_temp, rc, cc_reading;
-		struct pm8921_adc_chan_result result;
+		struct pm8xxx_adc_chan_result result;
 
-		rc = pm8921_adc_read(the_chip->batt_temp_channel, &result);
+		rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
 		if (rc) {
 			pr_err("error reading adc channel = %d, rc = %d\n",
 					the_chip->batt_temp_channel, rc);
@@ -1481,9 +1481,9 @@
 static int64_t read_battery_id(struct pm8921_bms_chip *chip)
 {
 	int rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(chip->batt_id_channel, &result);
+	rc = pm8xxx_adc_read(chip->batt_id_channel, &result);
 	if (rc) {
 		pr_err("error reading batt id channel = %d, rc = %d\n",
 					chip->vbat_channel, rc);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index aa24409..a91630a 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/ccadc.h>
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/interrupt.h>
@@ -264,7 +264,7 @@
 
 static struct pm8921_chg_chip *the_chip;
 
-static struct pm8921_adc_arb_btm_param btm_config;
+static struct pm8xxx_adc_arb_btm_param btm_config;
 
 static int pm_chg_masked_write(struct pm8921_chg_chip *chip, u16 addr,
 							u8 mask, u8 val)
@@ -722,9 +722,9 @@
 static int64_t read_battery_id(struct pm8921_chg_chip *chip)
 {
 	int rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(chip->batt_id_channel, &result);
+	rc = pm8xxx_adc_read(chip->batt_id_channel, &result);
 	if (rc) {
 		pr_err("error reading batt id channel = %d, rc = %d\n",
 					chip->vbat_channel, rc);
@@ -925,9 +925,9 @@
 static int get_prop_battery_mvolts(struct pm8921_chg_chip *chip)
 {
 	int rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(chip->vbat_channel, &result);
+	rc = pm8xxx_adc_read(chip->vbat_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					chip->vbat_channel, rc);
@@ -1067,9 +1067,9 @@
 static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
 {
 	int rc;
-	struct pm8921_adc_chan_result result;
+	struct pm8xxx_adc_chan_result result;
 
-	rc = pm8921_adc_read(chip->batt_temp_channel, &result);
+	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
 					chip->vbat_channel, rc);
@@ -1367,6 +1367,7 @@
 		notify_usb_of_the_plugin_event(usb_present);
 		chip->usb_present = usb_present;
 		power_supply_changed(&chip->usb_psy);
+		power_supply_changed(&chip->batt_psy);
 	}
 	bms_notify_check(chip);
 }
@@ -1451,6 +1452,7 @@
 	if (chip->dc_present ^ dc_present) {
 		chip->dc_present = dc_present;
 		power_supply_changed(&chip->dc_psy);
+		power_supply_changed(&chip->batt_psy);
 	}
 	bms_notify_check(chip);
 }
@@ -1686,13 +1688,31 @@
 	power_supply_changed(&chip->dc_psy);
 	return IRQ_HANDLED;
 }
-
+/*
+ *
+ * bat_temp_ok_irq_handler - is edge triggered, hence it will
+ * fire for two cases:
+ *
+ * If the interrupt line switches to high temperature is okay
+ * and thus charging begins.
+ * If bat_temp_ok is low this means the temperature is now
+ * too hot or cold, so charging is stopped.
+ *
+ */
 static irqreturn_t bat_temp_ok_irq_handler(int irq, void *data)
 {
+	int bat_temp_ok;
 	struct pm8921_chg_chip *chip = data;
 
-	pr_debug("batt temp ok fsm_state=%d\n", pm_chg_get_fsm_state(data));
-	handle_start_ext_chg(chip);
+	bat_temp_ok = pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ);
+
+	pr_debug("batt_temp_ok = %d fsm_state%d\n",
+			 bat_temp_ok, pm_chg_get_fsm_state(data));
+
+	if (bat_temp_ok)
+		handle_start_ext_chg(chip);
+	else
+		handle_stop_ext_chg(chip);
 
 	power_supply_changed(&chip->batt_psy);
 	power_supply_changed(&chip->usb_psy);
@@ -1915,7 +1935,7 @@
 {
 	int rc;
 
-	rc = pm8921_adc_btm_configure(&btm_config);
+	rc = pm8xxx_adc_btm_configure(&btm_config);
 	if (rc)
 		pr_err("failed to configure btm rc=%d", rc);
 }
@@ -1976,10 +1996,10 @@
 	btm_config.low_thr_temp = chip->cool_temp;
 	btm_config.high_thr_temp = chip->warm_temp;
 	btm_config.interval = chip->temp_check_period;
-	rc = pm8921_adc_btm_configure(&btm_config);
+	rc = pm8xxx_adc_btm_configure(&btm_config);
 	if (rc)
 		pr_err("failed to configure btm rc = %d\n", rc);
-	rc = pm8921_adc_btm_start();
+	rc = pm8xxx_adc_btm_start();
 	if (rc)
 		pr_err("failed to start btm rc = %d\n", rc);
 
@@ -2117,6 +2137,7 @@
 	pm8921_chg_enable_irq(chip, CHGFAIL_IRQ);
 	pm8921_chg_enable_irq(chip, FASTCHG_IRQ);
 	pm8921_chg_enable_irq(chip, VBATDET_LOW_IRQ);
+	pm8921_chg_enable_irq(chip, BAT_TEMP_OK_IRQ);
 
 	spin_lock_irqsave(&vbus_lock, flags);
 	if (usb_chg_current) {
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 1245045..5e0f8ec 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -700,6 +700,9 @@
 	chip->eoc_irq = res->start;
 	chip->r_sense = pdata->r_sense;
 
+	calib_ccadc_read_offset_and_gain(chip,
+					&chip->ccadc_gain_uv,
+					&chip->ccadc_offset);
 	rc = request_irq(chip->eoc_irq,
 			pm8921_bms_ccadc_eoc_handler, IRQF_TRIGGER_RISING,
 			"bms_eoc_ccadc", chip);
@@ -707,15 +710,13 @@
 		pr_err("failed to request %d irq rc= %d\n", chip->eoc_irq, rc);
 		goto free_chip;
 	}
+	disable_irq_nosync(chip->eoc_irq);
 
 	platform_set_drvdata(pdev, chip);
 	the_chip = chip;
 
 	create_debugfs_entries(chip);
 
-	calib_ccadc_read_offset_and_gain(chip,
-					&chip->ccadc_gain_uv,
-					&chip->ccadc_offset);
 	return 0;
 
 free_chip:
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 4194e59..01a7df5 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -41,20 +41,41 @@
  * system's wall clock; restore it on resume().
  */
 
-static time_t		oldtime;
-static struct timespec	oldts;
+static struct timespec old_rtc, old_system, old_delta;
+
 
 static int rtc_suspend(struct device *dev, pm_message_t mesg)
 {
 	struct rtc_device	*rtc = to_rtc_device(dev);
 	struct rtc_time		tm;
-
+	struct timespec		delta, delta_delta;
 	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
 		return 0;
 
+	/* snapshot the current RTC and system time at suspend*/
 	rtc_read_time(rtc, &tm);
-	ktime_get_ts(&oldts);
-	rtc_tm_to_time(&tm, &oldtime);
+	getnstimeofday(&old_system);
+	rtc_tm_to_time(&tm, &old_rtc.tv_sec);
+
+
+	/*
+	 * To avoid drift caused by repeated suspend/resumes,
+	 * which each can add ~1 second drift error,
+	 * try to compensate so the difference in system time
+	 * and rtc time stays close to constant.
+	 */
+	delta = timespec_sub(old_system, old_rtc);
+	delta_delta = timespec_sub(delta, old_delta);
+	if (abs(delta_delta.tv_sec)  >= 2) {
+		/*
+		 * if delta_delta is too large, assume time correction
+		 * has occured and set old_delta to the current delta.
+		 */
+		old_delta = delta;
+	} else {
+		/* Otherwise try to adjust old_system to compensate */
+		old_system = timespec_sub(old_system, delta_delta);
+	}
 
 	return 0;
 }
@@ -63,32 +84,42 @@
 {
 	struct rtc_device	*rtc = to_rtc_device(dev);
 	struct rtc_time		tm;
-	time_t			newtime;
-	struct timespec		time;
-	struct timespec		newts;
+	struct timespec		new_system, new_rtc;
+	struct timespec		sleep_time;
 
 	if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0)
 		return 0;
 
-	ktime_get_ts(&newts);
+	/* snapshot the current rtc and system time at resume */
+	getnstimeofday(&new_system);
 	rtc_read_time(rtc, &tm);
 	if (rtc_valid_tm(&tm) != 0) {
 		pr_debug("%s:  bogus resume time\n", dev_name(&rtc->dev));
 		return 0;
 	}
-	rtc_tm_to_time(&tm, &newtime);
-	if (newtime <= oldtime) {
-		if (newtime < oldtime)
+	rtc_tm_to_time(&tm, &new_rtc.tv_sec);
+	new_rtc.tv_nsec = 0;
+
+	if (new_rtc.tv_sec <= old_rtc.tv_sec) {
+		if (new_rtc.tv_sec < old_rtc.tv_sec)
 			pr_debug("%s:  time travel!\n", dev_name(&rtc->dev));
 		return 0;
 	}
-	/* calculate the RTC time delta */
-	set_normalized_timespec(&time, newtime - oldtime, 0);
 
-	/* subtract kernel time between rtc_suspend to rtc_resume */
-	time = timespec_sub(time, timespec_sub(newts, oldts));
+	/* calculate the RTC time delta (sleep time)*/
+	sleep_time = timespec_sub(new_rtc, old_rtc);
 
-	timekeeping_inject_sleeptime(&time);
+	/*
+	 * Since these RTC suspend/resume handlers are not called
+	 * at the very end of suspend or the start of resume,
+	 * some run-time may pass on either sides of the sleep time
+	 * so subtract kernel run-time between rtc_suspend to rtc_resume
+	 * to keep things accurate.
+	 */
+	sleep_time = timespec_sub(sleep_time,
+			timespec_sub(new_system, old_system));
+
+	timekeeping_inject_sleeptime(&sleep_time);
 	return 0;
 }
 
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 86d5195..70131fa 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -35,6 +35,8 @@
 #include <linux/oom.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
+#include <linux/memory.h>
+#include <linux/memory_hotplug.h>
 
 static uint32_t lowmem_debug_level = 2;
 static int lowmem_adj[6] = {
@@ -52,6 +54,7 @@
 };
 static int lowmem_minfree_size = 4;
 
+static unsigned int offlining;
 static struct task_struct *lowmem_deathpending;
 static unsigned long lowmem_deathpending_timeout;
 
@@ -79,6 +82,32 @@
 	return NOTIFY_OK;
 }
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+static int lmk_hotplug_callback(struct notifier_block *self,
+				unsigned long cmd, void *data)
+{
+	switch (cmd) {
+	/* Don't care LMK cases */
+	case MEM_ONLINE:
+	case MEM_OFFLINE:
+	case MEM_CANCEL_ONLINE:
+	case MEM_CANCEL_OFFLINE:
+	case MEM_GOING_ONLINE:
+		offlining = 0;
+		lowmem_print(4, "lmk in normal mode\n");
+		break;
+	/* LMK should account for movable zone */
+	case MEM_GOING_OFFLINE:
+		offlining = 1;
+		lowmem_print(4, "lmk in hotplug mode\n");
+		break;
+	}
+	return NOTIFY_DONE;
+}
+#endif
+
+
+
 static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
 {
 	struct task_struct *p;
@@ -93,7 +122,20 @@
 	int other_free = global_page_state(NR_FREE_PAGES);
 	int other_file = global_page_state(NR_FILE_PAGES) -
 						global_page_state(NR_SHMEM);
+	struct zone *zone;
 
+	if (offlining) {
+		/* Discount all free space in the section being offlined */
+		for_each_zone(zone) {
+			 if (zone_idx(zone) == ZONE_MOVABLE) {
+				other_free -= zone_page_state(zone,
+						NR_FREE_PAGES);
+				lowmem_print(4, "lowmem_shrink discounted "
+					"%lu pages in movable zone\n",
+					zone_page_state(zone, NR_FREE_PAGES));
+			}
+		}
+	}
 	/*
 	 * If we already have a death outstanding, then
 	 * bail out right away; indicating to vmscan
@@ -190,6 +232,9 @@
 {
 	task_free_register(&task_nb);
 	register_shrinker(&lowmem_shrinker);
+#ifdef CONFIG_MEMORY_HOTPLUG
+	hotplug_memory_notifier(lmk_hotplug_callback, 0);
+#endif
 	return 0;
 }
 
diff --git a/drivers/staging/gobi/QCUSBNet2k/Makefile b/drivers/staging/gobi/QCUSBNet2k/Makefile
old mode 100755
new mode 100644
diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c
index 1d518e3..50238f3 100644
--- a/drivers/thermal/pm8xxx-tm.c
+++ b/drivers/thermal/pm8xxx-tm.c
@@ -29,7 +29,7 @@
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/tm.h>
 #include <linux/completion.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/msm_adc.h>
 
 /* Register TEMP_ALARM_CTRL bits */
@@ -264,11 +264,11 @@
 	return 0;
 }
 
-static int pm8xxx_tz_get_temp_pm8921_adc(struct thermal_zone_device *thermal,
+static int pm8xxx_tz_get_temp_pm8xxx_adc(struct thermal_zone_device *thermal,
 				      unsigned long *temp)
 {
 	struct pm8xxx_tm_chip *chip = thermal->devdata;
-	struct pm8921_adc_chan_result result = {
+	struct pm8xxx_adc_chan_result result = {
 		.physical = 0lu,
 	};
 	int rc;
@@ -278,7 +278,7 @@
 
 	*temp = chip->temp;
 
-	rc = pm8921_adc_read(chip->cdata.adc_channel, &result);
+	rc = pm8xxx_adc_read(chip->cdata.adc_channel, &result);
 	if (rc < 0) {
 		pr_err("%s: adc_channel_read_result() failed, rc = %d\n",
 			chip->cdata.tm_name, rc);
@@ -401,8 +401,8 @@
 	.get_crit_temp = pm8xxx_tz_get_crit_temp,
 };
 
-static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8921_adc = {
-	.get_temp = pm8xxx_tz_get_temp_pm8921_adc,
+static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8xxx_adc = {
+	.get_temp = pm8xxx_tz_get_temp_pm8xxx_adc,
 	.get_mode = pm8xxx_tz_get_mode,
 	.set_mode = pm8xxx_tz_set_mode,
 	.get_trip_type = pm8xxx_tz_get_trip_type,
@@ -577,8 +577,8 @@
 	}
 
 	/* Select proper thermal zone ops functions based on ADC type. */
-	if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8921_ADC)
-		tz_ops = &pm8xxx_thermal_zone_ops_pm8921_adc;
+	if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8XXX_ADC)
+		tz_ops = &pm8xxx_thermal_zone_ops_pm8xxx_adc;
 	else if (chip->cdata.adc_type == PM8XXX_TM_ADC_PM8058_ADC)
 		tz_ops = &pm8xxx_thermal_zone_ops_pm8058_adc;
 	else
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index bc1a25b..84cb3f5 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -405,9 +405,9 @@
 		      msm_uport->rx.rbuffer);
 	dma_pool_destroy(msm_uport->rx.pool);
 
-	dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32 *),
+	dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32),
 			 DMA_TO_DEVICE);
-	dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32 *),
+	dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32),
 			 DMA_TO_DEVICE);
 	dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box),
 			 DMA_TO_DEVICE);
@@ -897,7 +897,7 @@
 	mb();
 
 	dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr,
-				   sizeof(u32 *), DMA_TO_DEVICE);
+				   sizeof(u32), DMA_TO_DEVICE);
 
 	msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
 }
@@ -1726,7 +1726,7 @@
 	if (!tx->command_ptr)
 		return -ENOMEM;
 
-	tx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA);
+	tx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
 	if (!tx->command_ptr_ptr) {
 		ret = -ENOMEM;
 		goto free_tx_command_ptr;
@@ -1736,7 +1736,7 @@
 					    sizeof(dmov_box), DMA_TO_DEVICE);
 	tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev,
 						tx->command_ptr_ptr,
-						sizeof(u32 *), DMA_TO_DEVICE);
+						sizeof(u32), DMA_TO_DEVICE);
 	tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr);
 
 	init_waitqueue_head(&rx->wait);
@@ -1772,7 +1772,7 @@
 		goto free_rx_buffer;
 	}
 
-	rx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA);
+	rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
 	if (!rx->command_ptr_ptr) {
 		pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__);
 		ret = -ENOMEM;
@@ -1803,7 +1803,7 @@
 	*rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr);
 
 	rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr,
-					    sizeof(u32 *), DMA_TO_DEVICE);
+					    sizeof(u32), DMA_TO_DEVICE);
 	rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr);
 
 	INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
@@ -1826,7 +1826,7 @@
 	tasklet_kill(&msm_uport->tx.tlet);
 	tasklet_kill(&msm_uport->rx.tlet);
 	dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr,
-			sizeof(u32 *), DMA_TO_DEVICE);
+			sizeof(u32), DMA_TO_DEVICE);
 	dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr,
 			sizeof(dmov_box), DMA_TO_DEVICE);
 	kfree(msm_uport->tx.command_ptr_ptr);
@@ -1999,12 +1999,12 @@
 	tasklet_kill(&msm_uport->rx.tlet);
 	cancel_delayed_work_sync(&msm_uport->rx.flip_insert_work);
 
-	spin_lock_irqsave(&uport->lock, flags);
 	clk_enable(msm_uport->clk);
 
 	pm_runtime_disable(uport->dev);
 	pm_runtime_set_suspended(uport->dev);
 
+	spin_lock_irqsave(&uport->lock, flags);
 	/* Disable the transmitter */
 	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
 	/* Disable the receiver */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 2bfd914..1e3beac 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -57,6 +57,8 @@
 #include "u_smd.c"
 #include "u_bam.c"
 #include "u_rmnet_ctrl_smd.c"
+#include "u_ctrl_hsic.c"
+#include "u_data_hsic.c"
 #include "f_serial.c"
 //#include "f_acm.c"
 #include "f_adb.c"
@@ -252,14 +254,9 @@
 	.attributes	= rmnet_smd_sdio_attributes,
 };
 
-/* RMNET - used with BAM */
-#define MAX_RMNET_INSTANCES 1
-static int rmnet_instances;
-static int rmnet_function_init(struct android_usb_function *f,
-					 struct usb_composite_dev *cdev)
-{
-	return frmnet_init_port(MAX_RMNET_INSTANCES);
-}
+/*rmnet transport string format(per port):"ctrl0,data0,ctrl1,data1..." */
+#define MAX_XPORT_STR_LEN 50
+static char rmnet_transports[MAX_XPORT_STR_LEN];
 
 static void rmnet_function_cleanup(struct android_usb_function *f)
 {
@@ -270,45 +267,74 @@
 					 struct usb_configuration *c)
 {
 	int i;
-	int ret = 0;
+	int err = 0;
+	char *ctrl_name;
+	char *data_name;
+	char buf[MAX_XPORT_STR_LEN], *b;
+	static int rmnet_initialized, ports;
 
-	for (i = 0; i < rmnet_instances; i++) {
-		ret = frmnet_bind_config(c, i);
-		if (ret) {
+	if (!rmnet_initialized) {
+		rmnet_initialized = 1;
+		strlcpy(buf, rmnet_transports, sizeof(buf));
+		b = strim(buf);
+		while (b) {
+			ctrl_name = strsep(&b, ",");
+			data_name = strsep(&b, ",");
+			if (ctrl_name && data_name) {
+				err = frmnet_init_port(ctrl_name, data_name);
+				if (err) {
+					pr_err("rmnet: Cannot open ctrl port:"
+						"'%s' data port:'%s'\n",
+						ctrl_name, data_name);
+					goto out;
+				}
+				ports++;
+			}
+		}
+
+		err = rmnet_gport_setup();
+		if (err) {
+			pr_err("rmnet: Cannot setup transports");
+			goto out;
+		}
+	}
+
+	for (i = 0; i < ports; i++) {
+		err = frmnet_bind_config(c, i);
+		if (err) {
 			pr_err("Could not bind rmnet%u config\n", i);
 			break;
 		}
 	}
-
-	return ret;
+out:
+	return err;
 }
 
-static ssize_t rmnet_instances_show(struct device *dev,
+static ssize_t rmnet_transports_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", rmnet_instances);
+	return snprintf(buf, PAGE_SIZE, "%s\n", rmnet_transports);
 }
 
-static ssize_t rmnet_instances_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t size)
+static ssize_t rmnet_transports_store(
+		struct device *device, struct device_attribute *attr,
+		const char *buff, size_t size)
 {
-	int value;
+	strlcpy(rmnet_transports, buff, sizeof(rmnet_transports));
 
-	sscanf(buf, "%d", &value);
-	if (value > MAX_RMNET_INSTANCES)
-		value = MAX_RMNET_INSTANCES;
-	rmnet_instances = value;
 	return size;
 }
 
-static DEVICE_ATTR(instances, S_IRUGO | S_IWUSR, rmnet_instances_show,
-						 rmnet_instances_store);
+static struct device_attribute dev_attr_rmnet_transports =
+					__ATTR(transports, S_IRUGO | S_IWUSR,
+						rmnet_transports_show,
+						rmnet_transports_store);
 static struct device_attribute *rmnet_function_attributes[] = {
-					&dev_attr_instances, NULL };
+					&dev_attr_rmnet_transports,
+					NULL };
 
 static struct android_usb_function rmnet_function = {
 	.name		= "rmnet",
-	.init		= rmnet_function_init,
 	.cleanup	= rmnet_function_cleanup,
 	.bind_config	= rmnet_function_bind_config,
 	.attributes	= rmnet_function_attributes,
@@ -609,26 +635,14 @@
 
 static int rndis_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
 {
-	int ret;
-	struct rndis_function_config *rndis;
-
 	f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
 	if (!f->config)
 		return -ENOMEM;
-
-	rndis = f->config;
-	ret = gether_setup_name(cdev->gadget, rndis->ethaddr, "usb");
-	if (ret) {
-		pr_err("%s: gether_setup failed\n", __func__);
-		return ret;
-	}
-
 	return 0;
 }
 
 static void rndis_function_cleanup(struct android_usb_function *f)
 {
-	gether_cleanup();
 	kfree(f->config);
 	f->config = NULL;
 }
@@ -636,6 +650,7 @@
 static int rndis_function_bind_config(struct android_usb_function *f,
 					struct usb_configuration *c)
 {
+	int ret;
 	struct rndis_function_config *rndis = f->config;
 
 	if (!rndis) {
@@ -647,6 +662,12 @@
 		rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
 		rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
 
+	ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+	if (ret) {
+		pr_err("%s: gether_setup failed\n", __func__);
+		return ret;
+	}
+
 	if (rndis->wceis) {
 		/* "Wireless" RNDIS; auto-detected by Windows */
 		rndis_iad_descriptor.bFunctionClass =
@@ -666,6 +687,7 @@
 static void rndis_function_unbind_config(struct android_usb_function *f,
 						struct usb_configuration *c)
 {
+	gether_cleanup();
 }
 
 static ssize_t rndis_manufacturer_show(struct device *dev,
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 11bfe9f..17fe820 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2862,6 +2862,7 @@
 	udc->softconnect = 1;
 
 	spin_unlock_irqrestore(udc->lock, flags);
+	pm_runtime_get_sync(&udc->gadget.dev);
 	retval = bind(&udc->gadget);                /* MAY SLEEP */
 	spin_lock_irqsave(udc->lock, flags);
 
@@ -2871,13 +2872,11 @@
 	}
 
 	udc->driver = driver;
-	pm_runtime_get_sync(&udc->gadget.dev);
 	if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) {
 		if (udc->vbus_active) {
 			if (udc->udc_driver->flags & CI13XXX_REGS_SHARED)
 				hw_device_reset(udc);
 		} else {
-			pm_runtime_put_sync(&udc->gadget.dev);
 			goto done;
 		}
 	}
@@ -2886,11 +2885,11 @@
 		goto done;
 
 	retval = hw_device_state(udc->ep0out.qh.dma);
-	if (retval)
-		pm_runtime_put_sync(&udc->gadget.dev);
 
  done:
 	spin_unlock_irqrestore(udc->lock, flags);
+	if (retval)
+		pm_runtime_put_sync(&udc->gadget.dev);
 	return retval;
 }
 EXPORT_SYMBOL(usb_gadget_probe_driver);
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 3fd12b1..7299dff 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -107,20 +107,6 @@
 	return container_of(p, struct f_acm, port);
 }
 
-static char *transport_to_str(enum transport_type t)
-{
-	switch (t) {
-	case USB_GADGET_FSERIAL_TRANSPORT_TTY:
-		return "TTY";
-	case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
-		return "SDIO";
-	case USB_GADGET_FSERIAL_TRANSPORT_SMD:
-		return "SMD";
-	}
-
-	return "NONE";
-}
-
 static int gport_setup(struct usb_configuration *c)
 {
 	int ret = 0;
@@ -146,7 +132,7 @@
 
 
 	pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_port_no:%d\n",
-			__func__, transport_to_str(acm->transport),
+			__func__, xport_to_str(acm->transport),
 			acm, &acm->port, acm->port_num, port_num);
 
 	switch (acm->transport) {
@@ -161,7 +147,7 @@
 		break;
 	default:
 		pr_err("%s: Un-supported transport: %s\n", __func__,
-				transport_to_str(acm->transport));
+				xport_to_str(acm->transport));
 		return -ENODEV;
 	}
 
@@ -175,7 +161,7 @@
 	port_num = gacm_ports[acm->port_num].client_port_num;
 
 	pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_pno:%d\n",
-			__func__, transport_to_str(acm->transport),
+			__func__, xport_to_str(acm->transport),
 			acm, &acm->port, acm->port_num, port_num);
 
 	switch (acm->transport) {
@@ -190,7 +176,7 @@
 		break;
 	default:
 		pr_err("%s: Un-supported transport:%s\n", __func__,
-				transport_to_str(acm->transport));
+				xport_to_str(acm->transport));
 		return -ENODEV;
 	}
 
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 7686bf2..32791d9 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -17,7 +17,7 @@
 #include <linux/usb/android_composite.h>
 #include <linux/spinlock.h>
 
-#include <linux/platform_data/usb_rmnet.h>
+#include <mach/usb_gadget_xport.h>
 #include "u_rmnet.h"
 #include "gadget_chips.h"
 
@@ -63,7 +63,15 @@
 
 #define NR_RMNET_PORTS	1
 static unsigned int nr_rmnet_ports;
+static unsigned int no_ctrl_smd_ports;
+static unsigned int no_ctrl_hsic_ports;
+static unsigned int no_data_bam_ports;
+static unsigned int no_data_hsic_ports;
 static struct rmnet_ports {
+	enum transport_type		data_xport;
+	enum transport_type		ctrl_xport;
+	unsigned			data_xport_num;
+	unsigned			ctrl_xport_num;
 	unsigned			port_num;
 	struct f_rmnet			*port;
 } rmnet_ports[NR_RMNET_PORTS];
@@ -227,42 +235,123 @@
 
 /* -------------------------------------------*/
 
-static int rmnet_gport_setup(int no_rmnet_ports)
+static int rmnet_gport_setup(void)
 {
-	int ret;
+	int	ret;
+	int	port_idx;
+	int	i;
 
-	pr_debug("%s: no_rmnet_ports:%d\n", __func__, no_rmnet_ports);
+	pr_debug("%s: bam ports: %u data hsic ports: %u smd ports: %u"
+			" ctrl hsic ports: %u nr_rmnet_ports: %u\n",
+			__func__, no_data_bam_ports, no_data_hsic_ports,
+			no_ctrl_smd_ports, no_ctrl_hsic_ports, nr_rmnet_ports);
 
-	ret = gbam_setup(no_rmnet_ports);
-	if (ret)
-		return ret;
+	if (no_data_bam_ports) {
+		ret = gbam_setup(no_data_bam_ports);
+		if (ret)
+			return ret;
+	}
 
-	ret = gsmd_ctrl_setup(no_rmnet_ports);
-	if (ret)
-		return ret;
+	if (no_ctrl_smd_ports) {
+		ret = gsmd_ctrl_setup(no_ctrl_smd_ports);
+		if (ret)
+			return ret;
+	}
+
+	if (no_data_hsic_ports) {
+		port_idx = ghsic_data_setup(no_data_hsic_ports,
+				USB_GADGET_RMNET);
+		if (port_idx < 0)
+			return port_idx;
+		for (i = 0; i < nr_rmnet_ports; i++) {
+			if (rmnet_ports[i].data_xport ==
+					USB_GADGET_XPORT_HSIC) {
+				rmnet_ports[i].data_xport_num = port_idx;
+				port_idx++;
+			}
+		}
+	}
+
+	if (no_ctrl_hsic_ports) {
+		port_idx = ghsic_ctrl_setup(no_ctrl_hsic_ports,
+				USB_GADGET_RMNET);
+		if (port_idx < 0)
+			return port_idx;
+		for (i = 0; i < nr_rmnet_ports; i++) {
+			if (rmnet_ports[i].ctrl_xport ==
+					USB_GADGET_XPORT_HSIC) {
+				rmnet_ports[i].ctrl_xport_num = port_idx;
+				port_idx++;
+			}
+		}
+	}
 
 	return 0;
 }
 
 static int gport_rmnet_connect(struct f_rmnet *dev)
 {
-	int ret;
+	int			ret;
+	unsigned		port_num;
+	enum transport_type	cxport = rmnet_ports[dev->port_num].ctrl_xport;
+	enum transport_type	dxport = rmnet_ports[dev->port_num].data_xport;
 
-	pr_debug("%s:dev:%p portno:%d\n",
-			__func__, dev, dev->port_num);
+	pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
+			__func__, xport_to_str(cxport), xport_to_str(dxport),
+			dev, dev->port_num);
 
-	ret = gsmd_ctrl_connect(&dev->port, dev->port_num);
-	if (ret) {
-		pr_err("%s: gsmd_ctrl_connect failed: err:%d\n",
-				__func__, ret);
-		return ret;
+	port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
+	switch (cxport) {
+	case USB_GADGET_XPORT_SMD:
+		ret = gsmd_ctrl_connect(&dev->port, port_num);
+		if (ret) {
+			pr_err("%s: gsmd_ctrl_connect failed: err:%d\n",
+					__func__, ret);
+			return ret;
+		}
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		ret = ghsic_ctrl_connect(&dev->port, port_num);
+		if (ret) {
+			pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
+					__func__, ret);
+			return ret;
+		}
+		break;
+	case USB_GADGET_XPORT_NONE:
+		break;
+	default:
+		pr_err("%s: Un-supported transport: %s\n", __func__,
+				xport_to_str(cxport));
+		return -ENODEV;
 	}
 
-	ret = gbam_connect(&dev->port, dev->port_num);
-	if (ret) {
-		pr_err("%s: gbam_connect failed: err:%d\n",
-				__func__, ret);
-		return ret;
+	port_num = rmnet_ports[dev->port_num].data_xport_num;
+	switch (dxport) {
+	case USB_GADGET_XPORT_BAM:
+		ret = gbam_connect(&dev->port, port_num);
+		if (ret) {
+			pr_err("%s: gbam_connect failed: err:%d\n",
+					__func__, ret);
+			gsmd_ctrl_disconnect(&dev->port, port_num);
+			return ret;
+		}
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		ret = ghsic_data_connect(&dev->port, port_num);
+		if (ret) {
+			pr_err("%s: ghsic_data_connect failed: err:%d\n",
+					__func__, ret);
+			ghsic_ctrl_disconnect(&dev->port, port_num);
+			return ret;
+		}
+		break;
+	case USB_GADGET_XPORT_NONE:
+		 break;
+	default:
+		pr_err("%s: Un-supported transport: %s\n", __func__,
+				xport_to_str(dxport));
+		return -ENODEV;
 	}
 
 	return 0;
@@ -270,12 +359,45 @@
 
 static int gport_rmnet_disconnect(struct f_rmnet *dev)
 {
-	pr_debug("%s:dev:%p portno:%d\n",
-			__func__, dev, dev->port_num);
+	unsigned		port_num;
+	enum transport_type	cxport = rmnet_ports[dev->port_num].ctrl_xport;
+	enum transport_type	dxport = rmnet_ports[dev->port_num].data_xport;
 
-	gbam_disconnect(&dev->port, dev->port_num);
+	pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
+			__func__, xport_to_str(cxport), xport_to_str(dxport),
+			dev, dev->port_num);
 
-	gsmd_ctrl_disconnect(&dev->port, dev->port_num);
+	port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
+	switch (cxport) {
+	case USB_GADGET_XPORT_SMD:
+		gsmd_ctrl_disconnect(&dev->port, port_num);
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		ghsic_ctrl_disconnect(&dev->port, port_num);
+		break;
+	case USB_GADGET_XPORT_NONE:
+		break;
+	default:
+		pr_err("%s: Un-supported transport: %s\n", __func__,
+				xport_to_str(cxport));
+		return -ENODEV;
+	}
+
+	port_num = rmnet_ports[dev->port_num].data_xport_num;
+	switch (dxport) {
+	case USB_GADGET_XPORT_BAM:
+		gbam_disconnect(&dev->port, port_num);
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		ghsic_data_disconnect(&dev->port, port_num);
+		break;
+	case USB_GADGET_XPORT_NONE:
+		break;
+	default:
+		pr_err("%s: Un-supported transport: %s\n", __func__,
+				xport_to_str(dxport));
+		return -ENODEV;
+	}
 
 	return 0;
 }
@@ -466,16 +588,24 @@
 }
 
 static int
-frmnet_send_cpkt_response(struct grmnet *gr, struct rmnet_ctrl_pkt *cpkt)
+frmnet_send_cpkt_response(void *gr, void *buf, size_t len)
 {
 	struct f_rmnet		*dev;
+	struct rmnet_ctrl_pkt	*cpkt;
 	unsigned long		flags;
 
-	if (!gr || !cpkt) {
-		pr_err("%s: Invalid grmnet/cpkt, grmnet:%p cpkt:%p\n",
-				__func__, gr, cpkt);
+	if (!gr || !buf) {
+		pr_err("%s: Invalid grmnet/buf, grmnet:%p buf:%p\n",
+				__func__, gr, buf);
 		return -ENODEV;
 	}
+	cpkt = rmnet_alloc_ctrl_pkt(len, GFP_ATOMIC);
+	if (IS_ERR(cpkt)) {
+		pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
+		return -ENOMEM;
+	}
+	memcpy(cpkt->buf, buf, len);
+	cpkt->len = len;
 
 	dev = port_to_rmnet(gr);
 
@@ -500,7 +630,7 @@
 {
 	struct f_rmnet			*dev = req->context;
 	struct usb_composite_dev	*cdev;
-	struct rmnet_ctrl_pkt		*cpkt;
+	unsigned			port_num;
 
 	if (!dev) {
 		pr_err("%s: rmnet dev is null\n", __func__);
@@ -511,16 +641,10 @@
 
 	cdev = dev->cdev;
 
-	cpkt = rmnet_alloc_ctrl_pkt(req->actual, GFP_ATOMIC);
-	if (IS_ERR(cpkt)) {
-		pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
-		return;
+	if (dev->port.send_encap_cmd) {
+		port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
+		dev->port.send_encap_cmd(port_num, req->buf, req->actual);
 	}
-
-	memcpy(cpkt->buf, req->buf, req->actual);
-
-	if (dev->port.send_cpkt_request)
-		dev->port.send_cpkt_request(&dev->port, dev->port_num, cpkt);
 }
 
 static void frmnet_notify_complete(struct usb_ep *ep, struct usb_request *req)
@@ -561,6 +685,7 @@
 	struct f_rmnet			*dev = func_to_rmnet(f);
 	struct usb_composite_dev	*cdev = dev->cdev;
 	struct usb_request		*req = cdev->req;
+	unsigned			port_num;
 	u16				w_index = le16_to_cpu(ctrl->wIndex);
 	u16				w_value = le16_to_cpu(ctrl->wValue);
 	u16				w_length = le16_to_cpu(ctrl->wLength);
@@ -615,10 +740,10 @@
 		break;
 	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
 			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
-		if (dev->port.send_cbits_tomodem)
-			dev->port.send_cbits_tomodem(&dev->port,
-							dev->port_num,
-							w_value);
+		if (dev->port.notify_modem) {
+			port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
+			dev->port.notify_modem(&dev->port, port_num, w_value);
+		}
 		ret = 0;
 
 		break;
@@ -827,42 +952,80 @@
 		kfree(rmnet_ports[i].port);
 
 	nr_rmnet_ports = 0;
+	no_ctrl_smd_ports = 0;
+	no_data_bam_ports = 0;
+	no_ctrl_hsic_ports = 0;
+	no_data_hsic_ports = 0;
 }
 
-static int frmnet_init_port(int instances)
+static int frmnet_init_port(const char *ctrl_name, const char *data_name)
 {
-	int i;
-	struct f_rmnet *dev;
-	int ret;
+	struct f_rmnet			*dev;
+	struct rmnet_ports		*rmnet_port;
+	int				ret;
+	int				i;
 
-	pr_debug("%s: instances :%d\n", __func__, instances);
-
-	if (instances > NR_RMNET_PORTS) {
-		pr_err("%s: Max-%d instances supported\n", __func__,
-						 NR_RMNET_PORTS);
+	if (nr_rmnet_ports >= NR_RMNET_PORTS) {
+		pr_err("%s: Max-%d instances supported\n",
+				__func__, NR_RMNET_PORTS);
 		return -EINVAL;
 	}
 
-	for (i = 0; i < instances; i++) {
-		dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
-		if (!dev) {
-			pr_err("%s: Unable to allocate rmnet device\n",
-					__func__);
-			ret = -ENOMEM;
-			goto fail_probe;
-		}
+	pr_debug("%s: port#:%d, ctrl port: %s data port: %s\n",
+		__func__, nr_rmnet_ports, ctrl_name, data_name);
 
-		dev->port_num = i;
-		spin_lock_init(&dev->lock);
-		INIT_LIST_HEAD(&dev->cpkt_resp_q);
-
-		rmnet_ports[i].port = dev;
-		rmnet_ports[i].port_num = i;
-
-		nr_rmnet_ports++;
+	dev = kzalloc(sizeof(struct f_rmnet), GFP_KERNEL);
+	if (!dev) {
+		pr_err("%s: Unable to allocate rmnet device\n", __func__);
+		return -ENOMEM;
 	}
 
-	rmnet_gport_setup(nr_rmnet_ports);
+	dev->port_num = nr_rmnet_ports;
+	spin_lock_init(&dev->lock);
+	INIT_LIST_HEAD(&dev->cpkt_resp_q);
+
+	rmnet_port = &rmnet_ports[nr_rmnet_ports];
+	rmnet_port->port = dev;
+	rmnet_port->port_num = nr_rmnet_ports;
+	rmnet_port->ctrl_xport = str_to_xport(ctrl_name);
+	rmnet_port->data_xport = str_to_xport(data_name);
+
+	switch (rmnet_port->ctrl_xport) {
+	case USB_GADGET_XPORT_SMD:
+		rmnet_port->ctrl_xport_num = no_ctrl_smd_ports;
+		no_ctrl_smd_ports++;
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		rmnet_port->ctrl_xport_num = no_ctrl_hsic_ports;
+		no_ctrl_hsic_ports++;
+		break;
+	case USB_GADGET_XPORT_NONE:
+		break;
+	default:
+		pr_err("%s: Un-supported transport: %u\n", __func__,
+				rmnet_port->ctrl_xport);
+		ret = -ENODEV;
+		goto fail_probe;
+	}
+
+	switch (rmnet_port->data_xport) {
+	case USB_GADGET_XPORT_BAM:
+		rmnet_port->data_xport_num = no_data_bam_ports;
+		no_data_bam_ports++;
+		break;
+	case USB_GADGET_XPORT_HSIC:
+		rmnet_port->data_xport_num = no_data_hsic_ports;
+		no_data_hsic_ports++;
+		break;
+	case USB_GADGET_XPORT_NONE:
+		break;
+	default:
+		pr_err("%s: Un-supported transport: %u\n", __func__,
+				rmnet_port->data_xport);
+		ret = -ENODEV;
+		goto fail_probe;
+	}
+	nr_rmnet_ports++;
 
 	return 0;
 
@@ -870,5 +1033,11 @@
 	for (i = 0; i < nr_rmnet_ports; i++)
 		kfree(rmnet_ports[i].port);
 
+	nr_rmnet_ports = 0;
+	no_ctrl_smd_ports = 0;
+	no_data_bam_ports = 0;
+	no_ctrl_hsic_ports = 0;
+	no_data_hsic_ports = 0;
+
 	return ret;
 }
diff --git a/drivers/usb/gadget/f_rmnet_smd_sdio.c b/drivers/usb/gadget/f_rmnet_smd_sdio.c
index 2ddbd7c..f974b8a 100644
--- a/drivers/usb/gadget/f_rmnet_smd_sdio.c
+++ b/drivers/usb/gadget/f_rmnet_smd_sdio.c
@@ -42,6 +42,7 @@
 #include <mach/msm_smd.h>
 #include <mach/sdio_cmux.h>
 #include <mach/sdio_dmux.h>
+#include <mach/usb_gadget_xport.h>
 
 #ifdef CONFIG_RMNET_SMD_SDIO_CTL_CHANNEL
 static uint32_t rmnet_mux_sdio_ctl_ch = CONFIG_RMNET_SMD_SDIO_CTL_CHANNEL;
@@ -104,12 +105,6 @@
 	struct list_head list;
 };
 
-enum usb_rmnet_mux_xport_type {
-	USB_RMNET_MUX_XPORT_UNDEFINED,
-	USB_RMNET_MUX_XPORT_SDIO,
-	USB_RMNET_MUX_XPORT_SMD,
-};
-
 struct rmnet_mux_ctrl_dev {
 	struct list_head tx_q;
 	wait_queue_head_t tx_wait_q;
@@ -176,7 +171,7 @@
 	struct rmnet_mux_ctrl_dev ctrl_dev;
 
 	u8 ifc_id;
-	enum usb_rmnet_mux_xport_type xport;
+	enum transport_type xport;
 	spinlock_t lock;
 	atomic_t online;
 	atomic_t notify_count;
@@ -291,18 +286,6 @@
 	NULL,
 };
 
-static char *xport_to_str(enum usb_rmnet_mux_xport_type t)
-{
-	switch (t) {
-	case USB_RMNET_MUX_XPORT_SDIO:
-		return "SDIO";
-	case USB_RMNET_MUX_XPORT_SMD:
-		return "SMD";
-	default:
-		return "UNDEFINED";
-	}
-}
-
 static struct rmnet_mux_ctrl_pkt *rmnet_mux_alloc_ctrl_pkt(unsigned len,
 							   gfp_t flags)
 {
@@ -556,7 +539,7 @@
 	int status = req->status;
 	int queue = 0;
 
-	if (dev->xport == USB_RMNET_MUX_XPORT_UNDEFINED) {
+	if (dev->xport == USB_GADGET_XPORT_UNDEF) {
 		dev_kfree_skb_any(skb);
 		req->buf = 0;
 		rmnet_mux_free_req(ep, req);
@@ -614,7 +597,7 @@
 	struct usb_composite_dev *cdev = dev->cdev;
 	int status = req->status;
 
-	if (dev->xport == USB_RMNET_MUX_XPORT_UNDEFINED) {
+	if (dev->xport == USB_GADGET_XPORT_UNDEF) {
 		dev_kfree_skb_any(skb);
 		req->buf = 0;
 		rmnet_mux_free_req(ep, req);
@@ -797,7 +780,7 @@
 	int status = req->status;
 	int ret;
 
-	if (dev->xport == USB_RMNET_MUX_XPORT_UNDEFINED) {
+	if (dev->xport == USB_GADGET_XPORT_UNDEF) {
 		rmnet_mux_free_req(ep, req);
 		return;
 	}
@@ -857,7 +840,7 @@
 	int status = req->status;
 	int schedule = 0;
 
-	if (dev->xport == USB_RMNET_MUX_XPORT_UNDEFINED) {
+	if (dev->xport == USB_GADGET_XPORT_UNDEF) {
 		rmnet_mux_free_req(ep, req);
 		return;
 	}
@@ -1276,7 +1259,7 @@
 	struct rmnet_mux_smd_dev *smd_dev = &dev->smd_dev;
 	struct rmnet_mux_ctrl_dev *ctrl_dev = &dev->ctrl_dev;
 
-	if (dev->xport == USB_RMNET_MUX_XPORT_SMD) {
+	if (dev->xport == USB_GADGET_XPORT_SMD) {
 		tasklet_kill(&smd_dev->smd_data.rx_tlet);
 		tasklet_kill(&smd_dev->smd_data.tx_tlet);
 	}
@@ -1416,8 +1399,8 @@
 	struct rmnet_mux_dev *dev = container_of(f, struct rmnet_mux_dev,
 								function);
 	int value;
-	enum usb_rmnet_mux_xport_type given_xport;
-	enum usb_rmnet_mux_xport_type t;
+	enum transport_type given_xport;
+	enum transport_type t;
 	struct rmnet_mux_smd_dev *smd_dev = &dev->smd_dev;
 	struct rmnet_mux_sdio_dev *sdio_dev = &dev->sdio_dev;
 	struct list_head *pool;
@@ -1433,9 +1416,9 @@
 
 	sscanf(buf, "%d", &value);
 	if (value)
-		given_xport = USB_RMNET_MUX_XPORT_SDIO;
+		given_xport = USB_GADGET_XPORT_SDIO;
 	else
-		given_xport = USB_RMNET_MUX_XPORT_SMD;
+		given_xport = USB_GADGET_XPORT_SMD;
 
 	if (given_xport == dev->xport) {
 		pr_err("%s: given_xport:%s cur_xport:%s doing nothing\n",
@@ -1449,14 +1432,14 @@
 
 	/* prevent any other pkts to/from usb  */
 	t = dev->xport;
-	dev->xport = USB_RMNET_MUX_XPORT_UNDEFINED;
-	if (t != USB_RMNET_MUX_XPORT_UNDEFINED) {
+	dev->xport = USB_GADGET_XPORT_UNDEF;
+	if (t != USB_GADGET_XPORT_UNDEF) {
 		usb_ep_fifo_flush(dev->epin);
 		usb_ep_fifo_flush(dev->epout);
 	}
 
 	switch (t) {
-	case USB_RMNET_MUX_XPORT_SDIO:
+	case USB_GADGET_XPORT_SDIO:
 		spin_lock_irqsave(&dev->lock, flags);
 		/* tx_idle */
 
@@ -1491,7 +1474,7 @@
 
 		spin_unlock_irqrestore(&dev->lock, flags);
 		break;
-	case USB_RMNET_MUX_XPORT_SMD:
+	case USB_GADGET_XPORT_SMD:
 		/* close smd xport */
 		tasklet_kill(&smd_dev->smd_data.rx_tlet);
 		tasklet_kill(&smd_dev->smd_data.tx_tlet);
@@ -1530,10 +1513,10 @@
 	dev->xport = given_xport;
 
 	switch (dev->xport) {
-	case USB_RMNET_MUX_XPORT_SDIO:
+	case USB_GADGET_XPORT_SDIO:
 		rmnet_mux_sdio_enable(dev);
 		break;
-	case USB_RMNET_MUX_XPORT_SMD:
+	case USB_GADGET_XPORT_SMD:
 		rmnet_mux_smd_enable(dev);
 		break;
 	default:
diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c
index 6cf148a..de8c8ed 100644
--- a/drivers/usb/gadget/f_serial.c
+++ b/drivers/usb/gadget/f_serial.c
@@ -13,7 +13,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <mach/usb_gadget_fserial.h>
+#include <mach/usb_gadget_xport.h>
 
 #include "u_serial.h"
 #include "gadget_chips.h"
@@ -27,6 +27,7 @@
  * CDC ACM driver.  However, for many purposes it's just as functional
  * if you can arrange appropriate host side drivers.
  */
+#define GSERIAL_NO_PORTS 2
 
 struct gser_descs {
 	struct usb_endpoint_descriptor	*in;
@@ -75,6 +76,7 @@
 static unsigned int no_tty_ports;
 static unsigned int no_sdio_ports;
 static unsigned int no_smd_ports;
+static unsigned int no_hsic_sports;
 static unsigned int nr_ports;
 
 static struct port_info {
@@ -85,7 +87,7 @@
 
 static inline bool is_transport_sdio(enum transport_type t)
 {
-	if (t == USB_GADGET_FSERIAL_TRANSPORT_SDIO)
+	if (t == USB_GADGET_XPORT_SDIO)
 		return 1;
 	return 0;
 }
@@ -250,37 +252,16 @@
 	NULL,
 };
 
-static char *transport_to_str(enum transport_type t)
-{
-	switch (t) {
-	case USB_GADGET_FSERIAL_TRANSPORT_TTY:
-		return "TTY";
-	case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
-		return "SDIO";
-	case USB_GADGET_FSERIAL_TRANSPORT_SMD:
-		return "SMD";
-	}
-
-	return "NONE";
-}
-
-static enum transport_type serial_str_to_transport(const char *name)
-{
-	if (!strcasecmp("SDIO", name))
-		return USB_GADGET_FSERIAL_TRANSPORT_SDIO;
-	if (!strcasecmp("SMD", name))
-		return USB_GADGET_FSERIAL_TRANSPORT_SMD;
-
-	return USB_GADGET_FSERIAL_TRANSPORT_TTY;
-}
-
-
 static int gport_setup(struct usb_configuration *c)
 {
 	int ret = 0;
+	int port_idx;
+	int i;
 
-	pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
-			__func__, no_tty_ports, no_sdio_ports, nr_ports);
+	pr_debug("%s: no_tty_ports: %u no_sdio_ports: %u"
+		" no_smd_ports: %u no_hsic_sports: %u nr_ports: %u\n",
+			__func__, no_tty_ports, no_sdio_ports, no_smd_ports,
+			no_hsic_sports, nr_ports);
 
 	if (no_tty_ports)
 		ret = gserial_setup(c->cdev->gadget, no_tty_ports);
@@ -288,33 +269,67 @@
 		ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
 	if (no_smd_ports)
 		ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
+	if (no_hsic_sports) {
+		port_idx = ghsic_data_setup(no_hsic_sports, USB_GADGET_SERIAL);
+		if (port_idx < 0)
+			return port_idx;
 
+		for (i = 0; i < nr_ports; i++) {
+			if (gserial_ports[i].transport ==
+					USB_GADGET_XPORT_HSIC) {
+				gserial_ports[i].client_port_num = port_idx;
+				port_idx++;
+			}
+		}
+
+		/*clinet port num is same for data setup and ctrl setup*/
+		ret = ghsic_ctrl_setup(no_hsic_sports, USB_GADGET_SERIAL);
+		if (ret < 0)
+			return ret;
+		return 0;
+	}
 	return ret;
 }
 
 static int gport_connect(struct f_gser *gser)
 {
-	unsigned port_num;
+	unsigned	port_num;
+	int		ret;
 
-	pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
-			__func__, transport_to_str(gser->transport),
+	pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n",
+			__func__, xport_to_str(gser->transport),
 			gser, &gser->port, gser->port_num);
 
 	port_num = gserial_ports[gser->port_num].client_port_num;
 
 	switch (gser->transport) {
-	case USB_GADGET_FSERIAL_TRANSPORT_TTY:
+	case USB_GADGET_XPORT_TTY:
 		gserial_connect(&gser->port, port_num);
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
+	case USB_GADGET_XPORT_SDIO:
 		gsdio_connect(&gser->port, port_num);
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SMD:
+	case USB_GADGET_XPORT_SMD:
 		gsmd_connect(&gser->port, port_num);
 		break;
+	case USB_GADGET_XPORT_HSIC:
+		ret = ghsic_ctrl_connect(&gser->port, port_num);
+		if (ret) {
+			pr_err("%s: ghsic_ctrl_connect failed: err:%d\n",
+					__func__, ret);
+			return ret;
+		}
+		ret = ghsic_data_connect(&gser->port, port_num);
+		if (ret) {
+			pr_err("%s: ghsic_data_connect failed: err:%d\n",
+					__func__, ret);
+			ghsic_ctrl_disconnect(&gser->port, port_num);
+			return ret;
+		}
+		break;
 	default:
 		pr_err("%s: Un-supported transport: %s\n", __func__,
-				transport_to_str(gser->transport));
+				xport_to_str(gser->transport));
 		return -ENODEV;
 	}
 
@@ -325,25 +340,29 @@
 {
 	unsigned port_num;
 
-	pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
-			__func__, transport_to_str(gser->transport),
+	pr_debug("%s: transport: %s f_gser: %p gserial: %p port_num: %d\n",
+			__func__, xport_to_str(gser->transport),
 			gser, &gser->port, gser->port_num);
 
 	port_num = gserial_ports[gser->port_num].client_port_num;
 
 	switch (gser->transport) {
-	case USB_GADGET_FSERIAL_TRANSPORT_TTY:
+	case USB_GADGET_XPORT_TTY:
 		gserial_disconnect(&gser->port);
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
+	case USB_GADGET_XPORT_SDIO:
 		gsdio_disconnect(&gser->port, port_num);
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SMD:
+	case USB_GADGET_XPORT_SMD:
 		gsmd_disconnect(&gser->port, port_num);
 		break;
+	case USB_GADGET_XPORT_HSIC:
+		ghsic_ctrl_disconnect(&gser->port, port_num);
+		ghsic_data_disconnect(&gser->port, port_num);
+		break;
 	default:
 		pr_err("%s: Un-supported transport:%s\n", __func__,
-				transport_to_str(gser->transport));
+				xport_to_str(gser->transport));
 		return -ENODEV;
 	}
 
@@ -887,26 +906,30 @@
 	if (port_num >= GSERIAL_NO_PORTS)
 		return -ENODEV;
 
-	transport = serial_str_to_transport(name);
+	transport = str_to_xport(name);
 	pr_debug("%s, port:%d, transport:%s\n", __func__,
-				port_num, transport_to_str(transport));
+			port_num, xport_to_str(transport));
 
 	gserial_ports[port_num].transport = transport;
 	gserial_ports[port_num].port_num = port_num;
 
 	switch (transport) {
-	case USB_GADGET_FSERIAL_TRANSPORT_TTY:
+	case USB_GADGET_XPORT_TTY:
 		gserial_ports[port_num].client_port_num = no_tty_ports;
 		no_tty_ports++;
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
+	case USB_GADGET_XPORT_SDIO:
 		gserial_ports[port_num].client_port_num = no_sdio_ports;
 		no_sdio_ports++;
 		break;
-	case USB_GADGET_FSERIAL_TRANSPORT_SMD:
+	case USB_GADGET_XPORT_SMD:
 		gserial_ports[port_num].client_port_num = no_smd_ports;
 		no_smd_ports++;
 		break;
+	case USB_GADGET_XPORT_HSIC:
+		/*client port number will be updated in gport_setup*/
+		no_hsic_sports++;
+		break;
 	default:
 		pr_err("%s: Un-supported transport transport: %u\n",
 				__func__, gserial_ports[port_num].transport);
diff --git a/drivers/usb/gadget/u_ctrl_hsic.c b/drivers/usb/gadget/u_ctrl_hsic.c
new file mode 100644
index 0000000..fdfab96
--- /dev/null
+++ b/drivers/usb/gadget/u_ctrl_hsic.c
@@ -0,0 +1,617 @@
+/* Copyright (c) 2011, 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/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/termios.h>
+#include <linux/debugfs.h>
+#include <linux/bitops.h>
+#include <linux/termios.h>
+#include <mach/usb_bridge.h>
+#include <mach/usb_gadget_xport.h>
+
+/* from cdc-acm.h */
+#define ACM_CTRL_RTS		(1 << 1)	/* unused with full duplex */
+#define ACM_CTRL_DTR		(1 << 0)	/* host is ready for data r/w */
+#define ACM_CTRL_OVERRUN	(1 << 6)
+#define ACM_CTRL_PARITY		(1 << 5)
+#define ACM_CTRL_FRAMING	(1 << 4)
+#define ACM_CTRL_RI		(1 << 3)
+#define ACM_CTRL_BRK		(1 << 2)
+#define ACM_CTRL_DSR		(1 << 1)
+#define ACM_CTRL_DCD		(1 << 0)
+
+
+static unsigned int	no_ctrl_ports;
+
+static const char	*ctrl_bridge_names[] = {
+	"dun_ctrl_hsic0",
+	"rmnet_ctrl_hsic0"
+};
+
+#define CTRL_BRIDGE_NAME_MAX_LEN	20
+#define READ_BUF_LEN			1024
+
+#define CH_OPENED 0
+#define CH_READY 1
+
+struct gctrl_port {
+	/* port */
+	unsigned		port_num;
+
+	/* gadget */
+	spinlock_t		port_lock;
+	void			*port_usb;
+
+	/* work queue*/
+	struct workqueue_struct	*wq;
+	struct work_struct	connect_w;
+	struct work_struct	disconnect_w;
+
+	enum gadget_type	gtype;
+
+	/*ctrl pkt response cb*/
+	int (*send_cpkt_response)(void *g, void *buf, size_t len);
+
+	struct bridge		brdg;
+
+	/* bridge status */
+	unsigned long		bridge_sts;
+
+	/* control bits */
+	unsigned		cbits_tomodem;
+	unsigned		cbits_tohost;
+
+	/* counters */
+	unsigned long		to_modem;
+	unsigned long		to_host;
+	unsigned long		drp_cpkt_cnt;
+};
+
+static struct {
+	struct gctrl_port	*port;
+	struct platform_driver	pdrv;
+} gctrl_ports[NUM_PORTS];
+
+static int ghsic_ctrl_receive(void *dev, void *buf, size_t actual)
+{
+	struct gctrl_port	*port = dev;
+	int retval = 0;
+
+	pr_debug_ratelimited("%s: read complete bytes read: %d\n",
+			__func__, actual);
+
+	/* send it to USB here */
+	if (port && port->send_cpkt_response) {
+		retval = port->send_cpkt_response(port->port_usb, buf, actual);
+		port->to_host++;
+	}
+
+	return retval;
+}
+
+static int
+ghsic_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
+{
+	void			*cbuf;
+	struct gctrl_port	*port;
+
+	if (portno >= no_ctrl_ports) {
+		pr_err("%s: Invalid portno#%d\n", __func__, portno);
+		return -ENODEV;
+	}
+
+	port = gctrl_ports[portno].port;
+	if (!port) {
+		pr_err("%s: port is null\n", __func__);
+		return -ENODEV;
+	}
+
+	cbuf = kmalloc(len, GFP_ATOMIC);
+	if (!cbuf)
+		return -ENOMEM;
+
+	memcpy(cbuf, buf, len);
+
+	/* drop cpkt if ch is not open */
+	if (!test_bit(CH_OPENED, &port->bridge_sts)) {
+		port->drp_cpkt_cnt++;
+		kfree(cbuf);
+		return 0;
+	}
+
+	pr_debug("%s: ctrl_pkt:%d bytes\n", __func__, len);
+
+	ctrl_bridge_write(port->brdg.ch_id, cbuf, len);
+
+	port->to_modem++;
+
+	return 0;
+}
+
+static void
+ghsic_send_cbits_tomodem(void *gptr, u8 portno, int cbits)
+{
+	struct gctrl_port	*port;
+
+	if (portno >= no_ctrl_ports || !gptr) {
+		pr_err("%s: Invalid portno#%d\n", __func__, portno);
+		return;
+	}
+
+	port = gctrl_ports[portno].port;
+	if (!port) {
+		pr_err("%s: port is null\n", __func__);
+		return;
+	}
+
+	if (cbits == port->cbits_tomodem)
+		return;
+
+	port->cbits_tomodem = cbits;
+
+	if (!test_bit(CH_OPENED, &port->bridge_sts))
+		return;
+
+	pr_debug("%s: ctrl_tomodem:%d\n", __func__, cbits);
+
+	ctrl_bridge_set_cbits(port->brdg.ch_id, cbits);
+}
+
+static void ghsic_ctrl_connect_w(struct work_struct *w)
+{
+	struct gserial		*gser = NULL;
+	struct grmnet		*gr = NULL;
+	struct gctrl_port	*port =
+			container_of(w, struct gctrl_port, connect_w);
+	unsigned long		flags;
+	int			retval;
+	unsigned		cbits;
+
+	if (!port || !test_bit(CH_READY, &port->bridge_sts))
+		return;
+
+	pr_debug("%s: port:%p\n", __func__, port);
+
+	retval = ctrl_bridge_open(&port->brdg);
+	if (retval) {
+		pr_err("%s: ctrl bridge open failed :%d\n", __func__, retval);
+		return;
+	}
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		ctrl_bridge_close(port->brdg.ch_id);
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+	set_bit(CH_OPENED, &port->bridge_sts);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	cbits = ctrl_bridge_get_cbits_tohost(port->brdg.ch_id);
+
+	if (port->gtype == USB_GADGET_SERIAL && (cbits & ACM_CTRL_DCD)) {
+		gser = port->port_usb;
+		if (gser && gser->connect)
+			gser->connect(gser);
+		return;
+	}
+
+	if (port->gtype == USB_GADGET_RMNET) {
+		gr = port->port_usb;
+		if (gr && gr->connect)
+			gr->connect(gr);
+	}
+}
+
+int ghsic_ctrl_connect(void *gptr, int port_num)
+{
+	struct gctrl_port	*port;
+	struct gserial		*gser;
+	struct grmnet		*gr;
+	unsigned long		flags;
+
+	pr_debug("%s: port#%d\n", __func__, port_num);
+
+	if (port_num > no_ctrl_ports || !gptr) {
+		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+		return -ENODEV;
+	}
+
+	port = gctrl_ports[port_num].port;
+	if (!port) {
+		pr_err("%s: port is null\n", __func__);
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->gtype == USB_GADGET_SERIAL) {
+		gser = gptr;
+		gser->notify_modem = ghsic_send_cbits_tomodem;
+	}
+
+	if (port->gtype == USB_GADGET_RMNET) {
+		gr = gptr;
+		port->send_cpkt_response = gr->send_cpkt_response;
+		gr->send_encap_cmd = ghsic_send_cpkt_tomodem;
+		gr->notify_modem = ghsic_send_cbits_tomodem;
+	}
+
+	port->port_usb = gptr;
+	port->to_host = 0;
+	port->to_modem = 0;
+	port->drp_cpkt_cnt = 0;
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	queue_work(port->wq, &port->connect_w);
+
+	return 0;
+}
+
+static void gctrl_disconnect_w(struct work_struct *w)
+{
+	struct gctrl_port	*port =
+			container_of(w, struct gctrl_port, disconnect_w);
+
+	if (!test_bit(CH_OPENED, &port->bridge_sts))
+		return;
+
+	/* send the dtr zero */
+	ctrl_bridge_close(port->brdg.ch_id);
+	clear_bit(CH_OPENED, &port->bridge_sts);
+}
+
+void ghsic_ctrl_disconnect(void *gptr, int port_num)
+{
+	struct gctrl_port	*port;
+	struct gserial		*gser = NULL;
+	struct grmnet		*gr = NULL;
+	unsigned long		flags;
+
+	pr_debug("%s: port#%d\n", __func__, port_num);
+
+	port = gctrl_ports[port_num].port;
+
+	if (port_num > no_ctrl_ports) {
+		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+		return;
+	}
+
+	if (!gptr || !port) {
+		pr_err("%s: grmnet port is null\n", __func__);
+		return;
+	}
+
+	if (port->gtype == USB_GADGET_SERIAL)
+		gser = gptr;
+	 else
+		gr = gptr;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (gr) {
+		gr->send_encap_cmd = 0;
+		gr->notify_modem = 0;
+	}
+
+	if (gser)
+		gser->notify_modem = 0;
+	port->cbits_tomodem = 0;
+	port->port_usb = 0;
+	port->send_cpkt_response = 0;
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	queue_work(port->wq, &port->disconnect_w);
+}
+
+static void ghsic_ctrl_status(void *ctxt, unsigned int ctrl_bits)
+{
+	struct gctrl_port	*port = ctxt;
+	struct gserial		*gser;
+
+	pr_debug("%s - input control lines: dcd%c dsr%c break%c "
+		 "ring%c framing%c parity%c overrun%c\n", __func__,
+		 ctrl_bits & ACM_CTRL_DCD ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_DSR ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_BRK ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_RI  ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_FRAMING ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_PARITY ? '+' : '-',
+		 ctrl_bits & ACM_CTRL_OVERRUN ? '+' : '-');
+
+	port->cbits_tohost = ctrl_bits;
+	gser = port->port_usb;
+	if (gser && gser->send_modem_ctrl_bits)
+		gser->send_modem_ctrl_bits(gser, ctrl_bits);
+}
+
+static int ghsic_ctrl_probe(struct platform_device *pdev)
+{
+	struct gctrl_port	*port;
+	unsigned long		flags;
+
+	pr_debug("%s: name:%s\n", __func__, pdev->name);
+
+	if (pdev->id >= no_ctrl_ports) {
+		pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+		return -EINVAL;
+	}
+
+	port = gctrl_ports[pdev->id].port;
+	set_bit(CH_READY, &port->bridge_sts);
+
+	/* if usb is online, start read */
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb)
+		queue_work(port->wq, &port->connect_w);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return 0;
+}
+
+static int ghsic_ctrl_remove(struct platform_device *pdev)
+{
+	struct gctrl_port	*port;
+	struct gserial		*gser = NULL;
+	struct grmnet		*gr = NULL;
+	unsigned long		flags;
+
+	pr_debug("%s: name:%s\n", __func__, pdev->name);
+
+	if (pdev->id >= no_ctrl_ports) {
+		pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+		return -EINVAL;
+	}
+
+	port = gctrl_ports[pdev->id].port;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		goto not_ready;
+	}
+
+	if (port->gtype == USB_GADGET_SERIAL)
+		gser = port->port_usb;
+	else
+		gr = port->port_usb;
+
+	port->cbits_tohost = 0;
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	if (gr && gr->disconnect)
+		gr->disconnect(gr);
+
+	if (gser && gser->disconnect)
+		gser->disconnect(gser);
+
+	ctrl_bridge_close(port->brdg.ch_id);
+
+	clear_bit(CH_OPENED, &port->bridge_sts);
+not_ready:
+	clear_bit(CH_READY, &port->bridge_sts);
+
+	return 0;
+}
+
+static void ghsic_ctrl_port_free(int portno)
+{
+	struct gctrl_port	*port = gctrl_ports[portno].port;
+	struct platform_driver	*pdrv = &gctrl_ports[portno].pdrv;
+
+	destroy_workqueue(port->wq);
+	kfree(port);
+
+	if (pdrv)
+		platform_driver_unregister(pdrv);
+}
+
+static int gctrl_port_alloc(int portno, enum gadget_type gtype)
+{
+	struct gctrl_port	*port;
+	struct platform_driver	*pdrv;
+
+	port = kzalloc(sizeof(struct gctrl_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	port->wq = create_singlethread_workqueue(ctrl_bridge_names[portno]);
+	if (!port->wq) {
+		pr_err("%s: Unable to create workqueue:%s\n",
+			__func__, ctrl_bridge_names[portno]);
+		return -ENOMEM;
+	}
+
+	port->port_num = portno;
+	port->gtype = gtype;
+
+	spin_lock_init(&port->port_lock);
+
+	INIT_WORK(&port->connect_w, ghsic_ctrl_connect_w);
+	INIT_WORK(&port->disconnect_w, gctrl_disconnect_w);
+
+	port->brdg.ch_id = portno;
+	port->brdg.ctx = port;
+	port->brdg.ops.send_pkt = ghsic_ctrl_receive;
+	if (port->gtype == USB_GADGET_SERIAL)
+		port->brdg.ops.send_cbits = ghsic_ctrl_status;
+	gctrl_ports[portno].port = port;
+
+	pdrv = &gctrl_ports[portno].pdrv;
+	pdrv->probe = ghsic_ctrl_probe;
+	pdrv->remove = ghsic_ctrl_remove;
+	pdrv->driver.name = ctrl_bridge_names[portno];
+	pdrv->driver.owner = THIS_MODULE;
+
+	platform_driver_register(pdrv);
+
+	pr_debug("%s: port:%p portno:%d\n", __func__, port, portno);
+
+	return 0;
+}
+
+int ghsic_ctrl_setup(unsigned int num_ports, enum gadget_type gtype)
+{
+	int		first_port_id = no_ctrl_ports;
+	int		total_num_ports = num_ports + no_ctrl_ports;
+	int		i;
+	int		ret = 0;
+
+	if (!num_ports || total_num_ports > NUM_PORTS) {
+		pr_err("%s: Invalid num of ports count:%d\n",
+				__func__, num_ports);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: requested ports:%d\n", __func__, num_ports);
+
+	for (i = first_port_id; i < (first_port_id + num_ports); i++) {
+
+		/*probe can be called while port_alloc,so update no_ctrl_ports*/
+		no_ctrl_ports++;
+		ret = gctrl_port_alloc(i, gtype);
+		if (ret) {
+			no_ctrl_ports--;
+			pr_err("%s: Unable to alloc port:%d\n", __func__, i);
+			goto free_ports;
+		}
+	}
+
+	return first_port_id;
+
+free_ports:
+	for (i = first_port_id; i < no_ctrl_ports; i++)
+		ghsic_ctrl_port_free(i);
+		no_ctrl_ports = first_port_id;
+	return ret;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	1024
+static ssize_t gctrl_read_stats(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	struct gctrl_port	*port;
+	struct platform_driver	*pdrv;
+	char			*buf;
+	unsigned long		flags;
+	int			ret;
+	int			i;
+	int			temp = 0;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < no_ctrl_ports; i++) {
+		port = gctrl_ports[i].port;
+		if (!port)
+			continue;
+		pdrv = &gctrl_ports[i].pdrv;
+		spin_lock_irqsave(&port->port_lock, flags);
+
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\nName:        %s\n"
+				"#PORT:%d port: %p\n"
+				"to_usbhost:    %lu\n"
+				"to_modem:      %lu\n"
+				"cpkt_drp_cnt:  %lu\n"
+				"DTR:           %s\n"
+				"ch_open:       %d\n"
+				"ch_ready:      %d\n",
+				pdrv->driver.name,
+				i, port,
+				port->to_host, port->to_modem,
+				port->drp_cpkt_cnt,
+				port->cbits_tomodem ? "HIGH" : "LOW",
+				test_bit(CH_OPENED, &port->bridge_sts),
+				test_bit(CH_READY, &port->bridge_sts));
+
+		spin_unlock_irqrestore(&port->port_lock, flags);
+	}
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t gctrl_reset_stats(struct file *file,
+	const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct gctrl_port	*port;
+	int			i;
+	unsigned long		flags;
+
+	for (i = 0; i < no_ctrl_ports; i++) {
+		port = gctrl_ports[i].port;
+		if (!port)
+			continue;
+
+		spin_lock_irqsave(&port->port_lock, flags);
+		port->to_host = 0;
+		port->to_modem = 0;
+		port->drp_cpkt_cnt = 0;
+		spin_unlock_irqrestore(&port->port_lock, flags);
+	}
+	return count;
+}
+
+const struct file_operations gctrl_stats_ops = {
+	.read = gctrl_read_stats,
+	.write = gctrl_reset_stats,
+};
+
+struct dentry	*gctrl_dent;
+struct dentry	*gctrl_dfile;
+static void gctrl_debugfs_init(void)
+{
+	gctrl_dent = debugfs_create_dir("ghsic_ctrl_xport", 0);
+	if (IS_ERR(gctrl_dent))
+		return;
+
+	gctrl_dfile =
+		debugfs_create_file("status", 0444, gctrl_dent, 0,
+			&gctrl_stats_ops);
+	if (!gctrl_dfile || IS_ERR(gctrl_dfile))
+		debugfs_remove(gctrl_dent);
+}
+
+static void gctrl_debugfs_exit(void)
+{
+	debugfs_remove(gctrl_dfile);
+	debugfs_remove(gctrl_dent);
+}
+
+#else
+static void gctrl_debugfs_init(void) { }
+static void gctrl_debugfs_exit(void) { }
+#endif
+
+static int __init gctrl_init(void)
+{
+	gctrl_debugfs_init();
+
+	return 0;
+}
+module_init(gctrl_init);
+
+static void __exit gctrl_exit(void)
+{
+	gctrl_debugfs_exit();
+}
+module_exit(gctrl_exit);
+MODULE_DESCRIPTION("hsic control xport driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/u_data_hsic.c b/drivers/usb/gadget/u_data_hsic.c
new file mode 100644
index 0000000..61458ea
--- /dev/null
+++ b/drivers/usb/gadget/u_data_hsic.c
@@ -0,0 +1,961 @@
+/* Copyright (c) 2011, 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/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/termios.h>
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/bitops.h>
+#include <linux/termios.h>
+#include <mach/usb_bridge.h>
+#include <mach/usb_gadget_xport.h>
+
+static unsigned int no_data_ports;
+
+static const char *data_bridge_names[] = {
+	"dun_data_hsic0",
+	"rmnet_data_hsic0"
+};
+
+#define DATA_BRIDGE_NAME_MAX_LEN		20
+
+#define GHSIC_DATA_RMNET_RX_Q_SIZE		50
+#define GHSIC_DATA_RMNET_TX_Q_SIZE		300
+#define GHSIC_DATA_SERIAL_RX_Q_SIZE		2
+#define GHSIC_DATA_SERIAL_TX_Q_SIZE		2
+#define GHSIC_DATA_RX_REQ_SIZE			2048
+
+static unsigned int ghsic_data_rmnet_tx_q_size = GHSIC_DATA_RMNET_TX_Q_SIZE;
+module_param(ghsic_data_rmnet_tx_q_size, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_rmnet_rx_q_size = GHSIC_DATA_RMNET_RX_Q_SIZE;
+module_param(ghsic_data_rmnet_rx_q_size, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_serial_tx_q_size = GHSIC_DATA_SERIAL_TX_Q_SIZE;
+module_param(ghsic_data_serial_tx_q_size, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_serial_rx_q_size = GHSIC_DATA_SERIAL_RX_Q_SIZE;
+module_param(ghsic_data_serial_rx_q_size, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_rx_req_size = GHSIC_DATA_RX_REQ_SIZE;
+module_param(ghsic_data_rx_req_size, uint, S_IRUGO | S_IWUSR);
+
+/*flow ctrl*/
+#define GHSIC_DATA_FLOW_CTRL_EN_THRESHOLD	500
+#define GHSIC_DATA_FLOW_CTRL_DISABLE		300
+#define GHSIC_DATA_FLOW_CTRL_SUPPORT		1
+#define GHSIC_DATA_PENDLIMIT_WITH_BRIDGE	500
+
+static unsigned int ghsic_data_fctrl_support = GHSIC_DATA_FLOW_CTRL_SUPPORT;
+module_param(ghsic_data_fctrl_support, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_fctrl_en_thld =
+		GHSIC_DATA_FLOW_CTRL_EN_THRESHOLD;
+module_param(ghsic_data_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_fctrl_dis_thld = GHSIC_DATA_FLOW_CTRL_DISABLE;
+module_param(ghsic_data_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int ghsic_data_pend_limit_with_bridge =
+		GHSIC_DATA_PENDLIMIT_WITH_BRIDGE;
+module_param(ghsic_data_pend_limit_with_bridge, uint, S_IRUGO | S_IWUSR);
+
+#define CH_OPENED 0
+#define CH_READY 1
+
+struct gdata_port {
+	/* port */
+	unsigned		port_num;
+
+	/* gadget */
+	spinlock_t		port_lock;
+	void			*port_usb;
+	struct usb_ep		*in;
+	struct usb_ep		*out;
+
+	enum gadget_type	gtype;
+
+	/* data transfer queues */
+	unsigned int		tx_q_size;
+	struct list_head	tx_idle;
+	struct sk_buff_head	tx_skb_q;
+
+	unsigned int		rx_q_size;
+	struct list_head	rx_idle;
+	struct sk_buff_head	rx_skb_q;
+
+	/* work */
+	struct workqueue_struct	*wq;
+	struct work_struct	connect_w;
+	struct work_struct	disconnect_w;
+	struct work_struct	write_tomdm_w;
+	struct work_struct	write_tohost_w;
+
+	struct bridge		brdg;
+
+	/*bridge status*/
+	unsigned long		bridge_sts;
+
+	/*counters*/
+	unsigned long		to_modem;
+	unsigned long		to_host;
+	unsigned int		rx_throttled_cnt;
+	unsigned int		rx_unthrottled_cnt;
+	unsigned int		tx_throttled_cnt;
+	unsigned int		tx_unthrottled_cnt;
+	unsigned int		tomodem_drp_cnt;
+	unsigned int		unthrottled_pnd_skbs;
+};
+
+static struct {
+	struct gdata_port	*port;
+	struct platform_driver	pdrv;
+} gdata_ports[NUM_PORTS];
+
+static void ghsic_data_start_rx(struct gdata_port *port);
+
+static void ghsic_data_free_requests(struct usb_ep *ep, struct list_head *head)
+{
+	struct usb_request	*req;
+
+	while (!list_empty(head)) {
+		req = list_entry(head->next, struct usb_request, list);
+		list_del(&req->list);
+		usb_ep_free_request(ep, req);
+	}
+}
+
+static int ghsic_data_alloc_requests(struct usb_ep *ep, struct list_head *head,
+		int num,
+		void (*cb)(struct usb_ep *ep, struct usb_request *),
+		gfp_t flags)
+{
+	int			i;
+	struct usb_request	*req;
+
+	pr_debug("%s: ep:%s head:%p num:%d cb:%p", __func__,
+			ep->name, head, num, cb);
+
+	for (i = 0; i < num; i++) {
+		req = usb_ep_alloc_request(ep, flags);
+		if (!req) {
+			pr_debug("%s: req allocated:%d\n", __func__, i);
+			return list_empty(head) ? -ENOMEM : 0;
+		}
+		req->complete = cb;
+		list_add(&req->list, head);
+	}
+
+	return 0;
+}
+
+static void ghsic_data_unthrottle_tx(void *ctx)
+{
+	struct gdata_port	*port = ctx;
+	unsigned long		flags;
+
+	if (!port)
+		return;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb) {
+		port->tx_unthrottled_cnt++;
+		queue_work(port->wq, &port->write_tomdm_w);
+		pr_debug("%s: port num =%d unthrottled\n", __func__,
+			port->port_num);
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static void ghsic_data_write_tohost(struct work_struct *w)
+{
+	unsigned long		flags;
+	struct sk_buff		*skb;
+	int			ret;
+	struct usb_request	*req;
+	struct usb_ep		*ep;
+	struct gdata_port	*port;
+
+	port = container_of(w, struct gdata_port, write_tohost_w);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	ep = port->in;
+
+	while (!list_empty(&port->tx_idle)) {
+		skb = __skb_dequeue(&port->tx_skb_q);
+		if (!skb)
+			break;
+
+		req = list_first_entry(&port->tx_idle, struct usb_request,
+				list);
+		req->context = skb;
+		req->buf = skb->data;
+		req->length = skb->len;
+
+		list_del(&req->list);
+
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		ret = usb_ep_queue(ep, req, GFP_KERNEL);
+		spin_lock_irqsave(&port->port_lock, flags);
+		if (ret) {
+			pr_err("%s: usb epIn failed\n", __func__);
+			list_add(&req->list, &port->tx_idle);
+			dev_kfree_skb_any(skb);
+			break;
+		}
+		port->to_host++;
+		if (ghsic_data_fctrl_support &&
+			port->tx_skb_q.qlen <= ghsic_data_fctrl_dis_thld &&
+			test_and_clear_bit(RX_THROTTLED, &port->brdg.flags)) {
+			port->rx_unthrottled_cnt++;
+			port->unthrottled_pnd_skbs = port->tx_skb_q.qlen;
+			pr_debug_ratelimited("%s: disable flow ctrl:"
+					" tx skbq len: %u\n",
+					__func__, port->tx_skb_q.qlen);
+			data_bridge_unthrottle_rx(port->brdg.ch_id);
+		}
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int ghsic_data_receive(void *p, void *data, size_t len)
+{
+	struct gdata_port	*port = p;
+	unsigned long		flags;
+	struct sk_buff		*skb = data;
+
+	if (!port) {
+		dev_kfree_skb_any(skb);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: p:%p#%d skb_len:%d\n", __func__,
+			port, port->port_num, skb->len);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		dev_kfree_skb_any(skb);
+		return -ENOTCONN;
+	}
+
+	__skb_queue_tail(&port->tx_skb_q, skb);
+
+	if (ghsic_data_fctrl_support &&
+			port->tx_skb_q.qlen >= ghsic_data_fctrl_en_thld) {
+		set_bit(RX_THROTTLED, &port->brdg.flags);
+		port->rx_throttled_cnt++;
+		pr_debug_ratelimited("%s: flow ctrl enabled: tx skbq len: %u\n",
+					__func__, port->tx_skb_q.qlen);
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		queue_work(port->wq, &port->write_tohost_w);
+		return -EBUSY;
+	}
+
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	queue_work(port->wq, &port->write_tohost_w);
+
+	return 0;
+}
+
+static void ghsic_data_write_tomdm(struct work_struct *w)
+{
+	struct gdata_port	*port;
+	struct sk_buff		*skb;
+	unsigned long		flags;
+	int			ret;
+
+	port = container_of(w, struct gdata_port, write_tomdm_w);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	if (test_bit(TX_THROTTLED, &port->brdg.flags)) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		goto start_rx;
+	}
+
+	while ((skb = __skb_dequeue(&port->rx_skb_q))) {
+		pr_debug("%s: port:%p tom:%lu pno:%d\n", __func__,
+				port, port->to_modem, port->port_num);
+
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		ret = data_bridge_write(port->brdg.ch_id, skb);
+		spin_lock_irqsave(&port->port_lock, flags);
+		if (ret < 0) {
+			if (ret == -EBUSY) {
+				/*flow control*/
+				port->tx_throttled_cnt++;
+				break;
+			}
+			pr_err_ratelimited("%s: write error:%d\n",
+					__func__, ret);
+			port->tomodem_drp_cnt++;
+			dev_kfree_skb_any(skb);
+			break;
+		}
+		port->to_modem++;
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+start_rx:
+	ghsic_data_start_rx(port);
+}
+
+static void ghsic_data_epin_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gdata_port	*port = ep->driver_data;
+	struct sk_buff		*skb = req->context;
+	int			status = req->status;
+
+	switch (status) {
+	case 0:
+		/* successful completion */
+		break;
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		/* connection gone */
+		dev_kfree_skb_any(skb);
+		req->buf = 0;
+		usb_ep_free_request(ep, req);
+		return;
+	default:
+		pr_err("%s: data tx ep error %d\n", __func__, status);
+		break;
+	}
+
+	dev_kfree_skb_any(skb);
+
+	spin_lock(&port->port_lock);
+	list_add_tail(&req->list, &port->tx_idle);
+	spin_unlock(&port->port_lock);
+
+	queue_work(port->wq, &port->write_tohost_w);
+}
+
+static void
+ghsic_data_epout_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct gdata_port	*port = ep->driver_data;
+	struct sk_buff		*skb = req->context;
+	int			status = req->status;
+	int			queue = 0;
+
+	switch (status) {
+	case 0:
+		skb_put(skb, req->actual);
+		queue = 1;
+		break;
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		/* cable disconnection */
+		dev_kfree_skb_any(skb);
+		req->buf = 0;
+		usb_ep_free_request(ep, req);
+		return;
+	default:
+		pr_err_ratelimited("%s: %s response error %d, %d/%d\n",
+					__func__, ep->name, status,
+				req->actual, req->length);
+		dev_kfree_skb_any(skb);
+		break;
+	}
+
+	spin_lock(&port->port_lock);
+	if (queue) {
+		__skb_queue_tail(&port->rx_skb_q, skb);
+		list_add_tail(&req->list, &port->rx_idle);
+		queue_work(port->wq, &port->write_tomdm_w);
+	}
+	spin_unlock(&port->port_lock);
+}
+
+static void ghsic_data_start_rx(struct gdata_port *port)
+{
+	struct usb_request	*req;
+	struct usb_ep		*ep;
+	unsigned long		flags;
+	int			ret;
+	struct sk_buff		*skb;
+
+	pr_debug("%s: port:%p\n", __func__, port);
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	ep = port->out;
+
+	while (port->port_usb && !list_empty(&port->rx_idle)) {
+		if (port->rx_skb_q.qlen > ghsic_data_pend_limit_with_bridge)
+			break;
+
+		req = list_first_entry(&port->rx_idle,
+					struct usb_request, list);
+
+		skb = alloc_skb(ghsic_data_rx_req_size, GFP_ATOMIC);
+		if (!skb)
+			break;
+
+		list_del(&req->list);
+		req->buf = skb->data;
+		req->length = ghsic_data_rx_req_size;
+		req->context = skb;
+
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		ret = usb_ep_queue(ep, req, GFP_KERNEL);
+		spin_lock_irqsave(&port->port_lock, flags);
+		if (ret) {
+			dev_kfree_skb_any(skb);
+
+			pr_err_ratelimited("%s: rx queue failed\n", __func__);
+
+			if (port->port_usb)
+				list_add(&req->list, &port->rx_idle);
+			else
+				usb_ep_free_request(ep, req);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static void ghsic_data_start_io(struct gdata_port *port)
+{
+	unsigned long	flags;
+	struct usb_ep	*ep;
+	int		ret;
+
+	pr_debug("%s: port:%p\n", __func__, port);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (!port->port_usb) {
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	ep = port->out;
+	ret = ghsic_data_alloc_requests(ep, &port->rx_idle,
+		port->rx_q_size, ghsic_data_epout_complete, GFP_ATOMIC);
+	if (ret) {
+		pr_err("%s: rx req allocation failed\n", __func__);
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	ep = port->in;
+	ret = ghsic_data_alloc_requests(ep, &port->tx_idle,
+		port->tx_q_size, ghsic_data_epin_complete, GFP_ATOMIC);
+	if (ret) {
+		pr_err("%s: tx req allocation failed\n", __func__);
+		ghsic_data_free_requests(ep, &port->rx_idle);
+		spin_unlock_irqrestore(&port->port_lock, flags);
+		return;
+	}
+
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	/* queue out requests */
+	ghsic_data_start_rx(port);
+}
+
+static void ghsic_data_connect_w(struct work_struct *w)
+{
+	struct gdata_port	*port =
+		container_of(w, struct gdata_port, connect_w);
+	int			ret;
+
+	if (!port || !test_bit(CH_READY, &port->bridge_sts))
+		return;
+
+	pr_debug("%s: port:%p\n", __func__, port);
+
+	ret = data_bridge_open(&port->brdg);
+	if (ret) {
+		pr_err("%s: unable open bridge ch:%d err:%d\n",
+				__func__, port->brdg.ch_id, ret);
+		return;
+	}
+
+	set_bit(CH_OPENED, &port->bridge_sts);
+
+	ghsic_data_start_io(port);
+}
+
+static void ghsic_data_disconnect_w(struct work_struct *w)
+{
+	struct gdata_port	*port =
+		container_of(w, struct gdata_port, disconnect_w);
+
+	if (!test_bit(CH_OPENED, &port->bridge_sts))
+		return;
+
+	data_bridge_close(port->brdg.ch_id);
+	clear_bit(CH_OPENED, &port->bridge_sts);
+}
+
+static void ghsic_data_free_buffers(struct gdata_port *port)
+{
+	struct sk_buff	*skb;
+	unsigned long	flags;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+
+	if (!port || !port->port_usb)
+		goto free_buf_out;
+
+	ghsic_data_free_requests(port->in, &port->tx_idle);
+	ghsic_data_free_requests(port->out, &port->rx_idle);
+
+	while ((skb = __skb_dequeue(&port->tx_skb_q)))
+		dev_kfree_skb_any(skb);
+
+	while ((skb = __skb_dequeue(&port->rx_skb_q)))
+		dev_kfree_skb_any(skb);
+
+free_buf_out:
+	spin_unlock_irqrestore(&port->port_lock, flags);
+}
+
+static int ghsic_data_probe(struct platform_device *pdev)
+{
+	struct gdata_port *port;
+	unsigned long flags;
+
+	pr_debug("%s: name:%s no_data_ports= %d\n",
+		__func__, pdev->name, no_data_ports);
+
+	if (pdev->id >= no_data_ports) {
+		pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+		return -EINVAL;
+	}
+
+	port = gdata_ports[pdev->id].port;
+	set_bit(CH_READY, &port->bridge_sts);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	/* if usb is online, try opening bridge */
+	if (port->port_usb)
+		queue_work(port->wq, &port->connect_w);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	return 0;
+}
+
+/* mdm disconnect */
+static int ghsic_data_remove(struct platform_device *pdev)
+{
+	struct gdata_port *port;
+	struct usb_ep *ep_in = NULL;
+	struct usb_ep *ep_out = NULL;
+	unsigned long flags;
+
+	pr_debug("%s: name:%s\n", __func__, pdev->name);
+
+	if (pdev->id >= no_data_ports) {
+		pr_err("%s: invalid port: %d\n", __func__, pdev->id);
+		return -EINVAL;
+	}
+
+	port = gdata_ports[pdev->id].port;
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	if (port->port_usb) {
+		ep_in = port->in;
+		ep_out = port->out;
+	}
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	if (ep_in)
+		usb_ep_fifo_flush(ep_in);
+	if (ep_out)
+		usb_ep_fifo_flush(ep_out);
+
+	ghsic_data_free_buffers(port);
+
+	data_bridge_close(port->brdg.ch_id);
+
+	clear_bit(CH_READY, &port->bridge_sts);
+	clear_bit(CH_OPENED, &port->bridge_sts);
+
+	return 0;
+}
+
+static void ghsic_data_port_free(int portno)
+{
+	struct gdata_port	*port = gdata_ports[portno].port;
+	struct platform_driver	*pdrv = &gdata_ports[portno].pdrv;
+
+	destroy_workqueue(port->wq);
+	kfree(port);
+
+	if (pdrv)
+		platform_driver_unregister(pdrv);
+}
+
+static int ghsic_data_port_alloc(unsigned port_num, enum gadget_type gtype)
+{
+	struct gdata_port	*port;
+	struct platform_driver	*pdrv;
+
+	port = kzalloc(sizeof(struct gdata_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	port->wq = create_singlethread_workqueue(data_bridge_names[port_num]);
+	if (!port->wq) {
+		pr_err("%s: Unable to create workqueue:%s\n",
+			__func__, data_bridge_names[port_num]);
+		return -ENOMEM;
+	}
+	port->port_num = port_num;
+
+	/* port initialization */
+	spin_lock_init(&port->port_lock);
+
+	INIT_WORK(&port->connect_w, ghsic_data_connect_w);
+	INIT_WORK(&port->disconnect_w, ghsic_data_disconnect_w);
+	INIT_WORK(&port->write_tohost_w, ghsic_data_write_tohost);
+	INIT_WORK(&port->write_tomdm_w, ghsic_data_write_tomdm);
+
+	INIT_LIST_HEAD(&port->tx_idle);
+	INIT_LIST_HEAD(&port->rx_idle);
+
+	skb_queue_head_init(&port->tx_skb_q);
+	skb_queue_head_init(&port->rx_skb_q);
+
+	port->gtype = gtype;
+	port->brdg.ch_id = port_num;
+	port->brdg.ctx = port;
+	port->brdg.ops.send_pkt = ghsic_data_receive;
+	port->brdg.ops.unthrottle_tx = ghsic_data_unthrottle_tx;
+	gdata_ports[port_num].port = port;
+
+	pdrv = &gdata_ports[port_num].pdrv;
+	pdrv->probe = ghsic_data_probe;
+	pdrv->remove = ghsic_data_remove;
+	pdrv->driver.name = data_bridge_names[port_num];
+	pdrv->driver.owner = THIS_MODULE;
+
+	platform_driver_register(pdrv);
+
+	pr_debug("%s: port:%p portno:%d\n", __func__, port, port_num);
+
+	return 0;
+}
+
+void ghsic_data_disconnect(void *gptr, int port_num)
+{
+	struct gdata_port	*port;
+	unsigned long		flags;
+
+	pr_debug("%s: port#%d\n", __func__, port_num);
+
+	port = gdata_ports[port_num].port;
+
+	if (port_num > no_data_ports) {
+		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+		return;
+	}
+
+	if (!gptr || !port) {
+		pr_err("%s: port is null\n", __func__);
+		return;
+	}
+
+	ghsic_data_free_buffers(port);
+
+	/* disable endpoints */
+	if (port->in)
+		usb_ep_disable(port->out);
+
+	if (port->out)
+		usb_ep_disable(port->in);
+
+	spin_lock_irqsave(&port->port_lock, flags);
+	port->port_usb = 0;
+	port->in = NULL;
+	port->out = NULL;
+	clear_bit(TX_THROTTLED, &port->brdg.flags);
+	clear_bit(RX_THROTTLED, &port->brdg.flags);
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	queue_work(port->wq, &port->disconnect_w);
+}
+
+int ghsic_data_connect(void *gptr, int port_num)
+{
+	struct gdata_port		*port;
+	struct gserial			*gser;
+	struct grmnet			*gr;
+	struct usb_endpoint_descriptor	*in_desc;
+	struct usb_endpoint_descriptor	*out_desc;
+	unsigned long			flags;
+	int				ret = 0;
+
+	pr_debug("%s: port#%d\n", __func__, port_num);
+
+	port = gdata_ports[port_num].port;
+
+	if (port_num > no_data_ports) {
+		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+		return -ENODEV;
+	}
+
+	if (!gptr || !port) {
+		pr_err("%s: port is null\n", __func__);
+		return -ENODEV;
+	}
+
+	if (port->gtype == USB_GADGET_SERIAL) {
+		gser = gptr;
+		port->in = gser->in;
+		port->out = gser->out;
+		port->tx_q_size = ghsic_data_serial_tx_q_size;
+		port->rx_q_size = ghsic_data_serial_rx_q_size;
+		gser->in->driver_data = port;
+		gser->out->driver_data = port;
+		in_desc = gser->in_desc;
+		out_desc = gser->out_desc;
+	} else {
+		gr = gptr;
+		port->in = gr->in;
+		port->out = gr->out;
+		port->tx_q_size = ghsic_data_rmnet_tx_q_size;
+		port->rx_q_size = ghsic_data_rmnet_rx_q_size;
+		gr->in->driver_data = port;
+		gr->out->driver_data = port;
+		in_desc = gr->in_desc;
+		out_desc = gr->out_desc;
+	}
+
+	ret = usb_ep_enable(port->in, in_desc);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+				__func__, port->in);
+		goto fail;
+	}
+
+	ret = usb_ep_enable(port->out, out_desc);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+				__func__, port->out);
+		usb_ep_disable(port->in);
+		goto fail;
+	}
+	spin_lock_irqsave(&port->port_lock, flags);
+	port->port_usb = gptr;
+	port->to_host = 0;
+	port->to_modem = 0;
+	port->tomodem_drp_cnt = 0;
+	port->rx_throttled_cnt = 0;
+	port->rx_unthrottled_cnt = 0;
+	port->tx_throttled_cnt = 0;
+	port->tx_unthrottled_cnt = 0;
+	port->unthrottled_pnd_skbs = 0;
+	spin_unlock_irqrestore(&port->port_lock, flags);
+
+	queue_work(port->wq, &port->connect_w);
+fail:
+	return ret;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE 1024
+static ssize_t ghsic_data_read_stats(struct file *file,
+	char __user *ubuf, size_t count, loff_t *ppos)
+{
+	struct gdata_port	*port;
+	struct platform_driver	*pdrv;
+	char			*buf;
+	unsigned long		flags;
+	int			ret;
+	int			i;
+	int			temp = 0;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < no_data_ports; i++) {
+		port = gdata_ports[i].port;
+		if (!port)
+			continue;
+		pdrv = &gdata_ports[i].pdrv;
+		spin_lock_irqsave(&port->port_lock, flags);
+
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\nName:           %s\n"
+				"#PORT:%d port#:   %p\n"
+				"dpkts_to_usbhost: %lu\n"
+				"dpkts_to_modem:   %lu\n"
+				"tomodem_drp_cnt:  %u\n"
+				"tx_buf_len:       %u\n"
+				"rx_buf_len:       %u\n"
+				"rx thld cnt       %u\n"
+				"rx unthld cnt     %u\n"
+				"tx thld cnt       %u\n"
+				"tx unthld cnt     %u\n"
+				"uthld pnd skbs    %u\n"
+				"RX_THROTTLED      %d\n"
+				"TX_THROTTLED      %d\n"
+				"data_ch_open:     %d\n"
+				"data_ch_ready:    %d\n",
+				pdrv->driver.name,
+				i, port,
+				port->to_host, port->to_modem,
+				port->tomodem_drp_cnt,
+				port->tx_skb_q.qlen,
+				port->rx_skb_q.qlen,
+				port->rx_throttled_cnt,
+				port->rx_unthrottled_cnt,
+				port->tx_throttled_cnt,
+				port->tx_unthrottled_cnt,
+				port->unthrottled_pnd_skbs,
+				test_bit(RX_THROTTLED, &port->brdg.flags),
+				test_bit(TX_THROTTLED, &port->brdg.flags),
+				test_bit(CH_OPENED, &port->bridge_sts),
+				test_bit(CH_READY, &port->bridge_sts));
+
+		spin_unlock_irqrestore(&port->port_lock, flags);
+	}
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t ghsic_data_reset_stats(struct file *file,
+	const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct gdata_port	*port;
+	int			i;
+	unsigned long		flags;
+
+	for (i = 0; i < no_data_ports; i++) {
+		port = gdata_ports[i].port;
+		if (!port)
+			continue;
+
+		spin_lock_irqsave(&port->port_lock, flags);
+		port->to_host = 0;
+		port->to_modem = 0;
+		port->tomodem_drp_cnt = 0;
+		port->rx_throttled_cnt = 0;
+		port->rx_unthrottled_cnt = 0;
+		port->tx_throttled_cnt = 0;
+		port->tx_unthrottled_cnt = 0;
+		port->unthrottled_pnd_skbs = 0;
+		spin_unlock_irqrestore(&port->port_lock, flags);
+	}
+	return count;
+}
+
+const struct file_operations ghsic_stats_ops = {
+	.read = ghsic_data_read_stats,
+	.write = ghsic_data_reset_stats,
+};
+
+static struct dentry	*gdata_dent;
+static struct dentry	*gdata_dfile;
+
+static void ghsic_data_debugfs_init(void)
+{
+	gdata_dent = debugfs_create_dir("ghsic_data_xport", 0);
+	if (IS_ERR(gdata_dent))
+		return;
+
+	gdata_dfile = debugfs_create_file("status", 0444, gdata_dent, 0,
+			&ghsic_stats_ops);
+	if (!gdata_dfile || IS_ERR(gdata_dfile))
+		debugfs_remove(gdata_dent);
+}
+
+static void ghsic_data_debugfs_exit(void)
+{
+	debugfs_remove(gdata_dfile);
+	debugfs_remove(gdata_dent);
+}
+
+#else
+static void ghsic_data_debugfs_init(void) { }
+static void ghsic_data_debugfs_exit(void) { }
+
+#endif
+
+int ghsic_data_setup(unsigned num_ports, enum gadget_type gtype)
+{
+	int		first_port_id = no_data_ports;
+	int		total_num_ports = num_ports + no_data_ports;
+	int		ret = 0;
+	int		i;
+
+	if (!num_ports || total_num_ports > NUM_PORTS) {
+		pr_err("%s: Invalid num of ports count:%d\n",
+				__func__, num_ports);
+		return -EINVAL;
+	}
+	pr_debug("%s: count: %d\n", __func__, num_ports);
+
+	for (i = first_port_id; i < (num_ports + first_port_id); i++) {
+
+		/*probe can be called while port_alloc,so update no_data_ports*/
+		no_data_ports++;
+		ret = ghsic_data_port_alloc(i, gtype);
+		if (ret) {
+			no_data_ports--;
+			pr_err("%s: Unable to alloc port:%d\n", __func__, i);
+			goto free_ports;
+		}
+	}
+
+	/*return the starting index*/
+	return first_port_id;
+
+free_ports:
+	for (i = first_port_id; i < no_data_ports; i++)
+		ghsic_data_port_free(i);
+		no_data_ports = first_port_id;
+
+	return ret;
+}
+
+static int __init ghsic_data_init(void)
+{
+	ghsic_data_debugfs_init();
+
+	return 0;
+}
+module_init(ghsic_data_init);
+
+static void __exit ghsic_data_exit(void)
+{
+	ghsic_data_debugfs_exit();
+}
+module_exit(ghsic_data_exit);
+MODULE_DESCRIPTION("hsic data xport driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index 3c21316..d8de31e 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -35,19 +35,14 @@
 	/* to usb host, aka laptop, windows pc etc. Will
 	 * be filled by usb driver of rmnet functionality
 	 */
-	int (*send_cpkt_response)(struct grmnet *g,
-				struct rmnet_ctrl_pkt *pkt);
+	int (*send_cpkt_response)(void *g, void *buf, size_t len);
 
 	/* to modem, and to be filled by driver implementing
 	 * control function
 	 */
-	int (*send_cpkt_request)(struct grmnet *g,
-				u8 port_num,
-				struct rmnet_ctrl_pkt *pkt);
+	int (*send_encap_cmd)(u8 port_num, void *buf, size_t len);
 
-	void (*send_cbits_tomodem)(struct grmnet *g,
-				u8 port_num,
-				int cbits);
+	void (*notify_modem)(void *g, u8 port_num, int cbits);
 
 	void (*disconnect)(struct grmnet *g);
 	void (*connect)(struct grmnet *g);
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index fc159cc..8b08b7a 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -83,6 +83,7 @@
 		kfree(pkt);
 		return ERR_PTR(-ENOMEM);
 	}
+
 	pkt->len = len;
 
 	return pkt;
@@ -103,7 +104,8 @@
 	struct smd_ch_info *c = container_of(w, struct smd_ch_info, read_w);
 	struct rmnet_ctrl_port *port = c->port;
 	int sz;
-	struct rmnet_ctrl_pkt *cpkt;
+	size_t len;
+	void *buf;
 	unsigned long flags;
 
 	while (1) {
@@ -114,22 +116,20 @@
 		if (smd_read_avail(c->ch) < sz)
 			break;
 
-		cpkt = alloc_rmnet_ctrl_pkt(sz, GFP_KERNEL);
-		if (IS_ERR(cpkt)) {
-			pr_err("%s: unable to allocate rmnet control pkt\n",
-					__func__);
+		buf = kmalloc(sz, GFP_KERNEL);
+		if (!buf)
 			return;
-		}
-		cpkt->len = smd_read(c->ch, cpkt->buf, sz);
+
+		len = smd_read(c->ch, buf, sz);
 
 		/* send it to USB here */
 		spin_lock_irqsave(&port->port_lock, flags);
 		if (port->port_usb && port->port_usb->send_cpkt_response) {
-			port->port_usb->send_cpkt_response(
-							port->port_usb,
-							cpkt);
+			port->port_usb->send_cpkt_response(port->port_usb,
+							buf, len);
 			c->to_host++;
 		}
+		kfree(buf);
 		spin_unlock_irqrestore(&port->port_lock, flags);
 	}
 }
@@ -157,8 +157,7 @@
 		ret = smd_write(c->ch, cpkt->buf, cpkt->len);
 		spin_lock_irqsave(&port->port_lock, flags);
 		if (ret != cpkt->len) {
-			pr_err("%s: smd_write failed err:%d\n",
-					__func__, ret);
+			pr_err("%s: smd_write failed err:%d\n", __func__, ret);
 			free_rmnet_ctrl_pkt(cpkt);
 			break;
 		}
@@ -169,24 +168,29 @@
 }
 
 static int
-grmnet_ctrl_smd_send_cpkt_tomodem(struct grmnet *gr, u8 portno,
-			struct rmnet_ctrl_pkt *cpkt)
+grmnet_ctrl_smd_send_cpkt_tomodem(u8 portno,
+	void *buf, size_t len)
 {
 	unsigned long		flags;
 	struct rmnet_ctrl_port	*port;
 	struct smd_ch_info	*c;
+	struct rmnet_ctrl_pkt *cpkt;
 
 	if (portno >= n_rmnet_ctrl_ports) {
 		pr_err("%s: Invalid portno#%d\n", __func__, portno);
 		return -ENODEV;
 	}
 
-	if (!gr) {
-		pr_err("%s: grmnet is null\n", __func__);
-		return -ENODEV;
+	port = ctrl_smd_ports[portno].port;
+
+	cpkt = alloc_rmnet_ctrl_pkt(len, GFP_ATOMIC);
+	if (IS_ERR(cpkt)) {
+		pr_err("%s: Unable to allocate ctrl pkt\n", __func__);
+		return -ENOMEM;
 	}
 
-	port = ctrl_smd_ports[portno].port;
+	memcpy(cpkt->buf, buf, len);
+	cpkt->len = len;
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	c = &port->ctrl_ch;
@@ -207,7 +211,7 @@
 
 #define RMNET_CTRL_DTR		0x01
 static void
-gsmd_ctrl_send_cbits_tomodem(struct grmnet *gr, u8 portno, int cbits)
+gsmd_ctrl_send_cbits_tomodem(void *gptr, u8 portno, int cbits)
 {
 	struct rmnet_ctrl_port	*port;
 	struct smd_ch_info	*c;
@@ -220,7 +224,7 @@
 		return;
 	}
 
-	if (!gr) {
+	if (!gptr) {
 		pr_err("%s: grmnet is null\n", __func__);
 		return;
 	}
@@ -362,8 +366,8 @@
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	port->port_usb = gr;
-	gr->send_cpkt_request = grmnet_ctrl_smd_send_cpkt_tomodem;
-	gr->send_cbits_tomodem = gsmd_ctrl_send_cbits_tomodem;
+	gr->send_encap_cmd = grmnet_ctrl_smd_send_cpkt_tomodem;
+	gr->notify_modem = gsmd_ctrl_send_cbits_tomodem;
 	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	queue_work(grmnet_ctrl_wq, &port->connect_w);
@@ -395,8 +399,8 @@
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	port->port_usb = 0;
-	gr->send_cpkt_request = 0;
-	gr->send_cbits_tomodem = 0;
+	gr->send_encap_cmd = 0;
+	gr->notify_modem = 0;
 	c->cbits_tomodem = 0;
 
 	while (!list_empty(&c->tx_q)) {
diff --git a/drivers/usb/gadget/u_sdio.c b/drivers/usb/gadget/u_sdio.c
index 6ba7543..9bd4370 100644
--- a/drivers/usb/gadget/u_sdio.c
+++ b/drivers/usb/gadget/u_sdio.c
@@ -639,10 +639,11 @@
 			port->cbits_to_modem, ~(port->cbits_to_modem));
 }
 
-void gsdio_ctrl_notify_modem(struct gserial *gser, u8 portno, int ctrl_bits)
+void gsdio_ctrl_notify_modem(void *gptr, u8 portno, int ctrl_bits)
 {
 	struct gsdio_port *port;
 	int temp;
+	struct gserial *gser = gptr;
 
 	if (portno >= n_sdio_ports) {
 		pr_err("%s: invalid portno#%d\n", __func__, portno);
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index fea53d8..c937006 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -55,7 +55,7 @@
 	int (*send_modem_ctrl_bits)(struct gserial *p, int ctrl_bits);
 
 	/* notification changes to modem */
-	void (*notify_modem)(struct gserial *gser, u8 portno, int ctrl_bits);
+	void (*notify_modem)(void *gser, u8 portno, int ctrl_bits);
 };
 
 /* utilities to allocate/free request and buffer */
diff --git a/drivers/usb/gadget/u_smd.c b/drivers/usb/gadget/u_smd.c
index 60826b9..caccade 100644
--- a/drivers/usb/gadget/u_smd.c
+++ b/drivers/usb/gadget/u_smd.c
@@ -579,10 +579,11 @@
 	}
 }
 
-static void gsmd_notify_modem(struct gserial *gser, u8 portno, int ctrl_bits)
+static void gsmd_notify_modem(void *gptr, u8 portno, int ctrl_bits)
 {
 	struct gsmd_port *port;
 	int temp;
+	struct gserial *gser = gptr;
 
 	if (portno >= n_smd_ports) {
 		pr_err("%s: invalid portno#%d\n", __func__, portno);
diff --git a/drivers/usb/host/pehci/host/otg.c b/drivers/usb/host/pehci/host/otg.c
old mode 100755
new mode 100644
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index c5dcdbf..13828e0 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -283,27 +283,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called diag_bridge_test.  If unsure, choose N.
 
-config USB_QCOM_DUN_BRIDGE
-	tristate "USB Qualcomm modem DUN bridge driver"
+config USB_QCOM_MDM_BRIDGE
+	tristate "USB Qualcomm modem bridge driver for DUN and RMNET"
 	depends on USB
 	help
 	  Say Y here if you have a Qualcomm modem device connected via USB that
-	  will be bridged in kernel space. This driver will enable bridging
-	  with the gadget serial driver for use in dial-up networking. This is
-	  not the same as the qcserial driver that exposes a TTY interface to
-	  userspace.
-
+	  will be bridged in kernel space. This driver works as a bridge to pass
+	  control and data packets between the modem and peripheral usb gadget
+	  driver for dial up network and RMNET.
 	  To compile this driver as a module, choose M here: the module
-	  will be called dun_bridge.
-
-config USB_QCOM_DUN_BRIDGE_TEST
-	tristate "USB Qualcomm modem DUN bridge driver test"
-	depends on USB && USB_QCOM_DUN_BRIDGE && !USB_SERIAL_QUALCOMM
-	help
-	  Say Y here if you want to enable the test hook for the
-	  Qualcomm modem bridge driver. When enabled, this will create
-	  a debugfs file entry named "dun_bridge_test" which can be used
-	  to read and write directly to the modem.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called dun_bridge_test.
+	  will be called mdm_bridge. If unsure, choose N.
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index bb69a02..b4aee65 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -31,5 +31,5 @@
 
 obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE)	+= diag_bridge.o
 obj-$(CONFIG_USB_QCOM_DIAG_BRIDGE_TEST)	+= diag_bridge_test.o
-obj-$(CONFIG_USB_QCOM_DUN_BRIDGE)	+= dun_bridge.o
-obj-$(CONFIG_USB_QCOM_DUN_BRIDGE_TEST)	+= dun_bridge_test.o
+mdm_bridge-y				:= mdm_ctrl_bridge.o mdm_data_bridge.o
+obj-$(CONFIG_USB_QCOM_MDM_BRIDGE) 	+= mdm_bridge.o
diff --git a/drivers/usb/misc/dun_bridge.c b/drivers/usb/misc/dun_bridge.c
deleted file mode 100644
index aca7714..0000000
--- a/drivers/usb/misc/dun_bridge.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* Copyright (c) 2011, 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/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/platform_device.h>
-#include <linux/usb.h>
-#include <linux/usb/cdc.h>
-#include <linux/usb/ch9.h>
-#include <asm/unaligned.h>
-#include <mach/usb_dun_bridge.h>
-
-#define DRIVER_DESC "Qualcomm USB DUN bridge driver"
-#define DRIVER_VERSION "1.0"
-
-struct dun_bridge {
-	struct usb_device	*udev;
-	struct usb_interface	*intf;
-	struct usb_anchor	submitted;
-	u8			int_in_epaddr;
-	unsigned		in, out; /* bulk in/out pipes */
-
-	struct urb		*inturb;
-	struct usb_ctrlrequest	cmd;
-	u8			*ctrl_buf;
-
-	struct kref		kref;
-	struct platform_device	*pdev;
-
-	struct dun_bridge_ops	*ops;
-};
-
-static struct dun_bridge *__dev;
-
-/* This assumes that __dev has already been initialized by probe(). */
-int dun_bridge_open(struct dun_bridge_ops *ops)
-{
-	struct dun_bridge *dev = __dev;
-	int ret = 0;
-
-	if (!dev) {
-		err("%s: dev is null", __func__);
-		return -ENODEV;
-	}
-
-	if (!ops || !ops->read_complete || !ops->write_complete)
-		return -EINVAL;
-
-	dev->ops = ops;
-	if (ops->ctrl_status) {
-		ret = usb_submit_urb(dev->inturb, GFP_KERNEL);
-		if (ret)
-			pr_err("%s: submitting int urb failed: %d\n",
-				__func__, ret);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(dun_bridge_open);
-
-int dun_bridge_close(void)
-{
-	struct dun_bridge *dev = __dev;
-	if (!dev)
-		return -ENODEV;
-
-	dev_dbg(&dev->udev->dev, "%s:", __func__);
-	usb_unlink_anchored_urbs(&dev->submitted);
-	usb_unlink_urb(dev->inturb);
-	dev->ops = NULL;
-
-	return 0;
-}
-EXPORT_SYMBOL(dun_bridge_close);
-
-static void read_cb(struct urb *urb)
-{
-	struct dun_bridge *dev = urb->context;
-	struct dun_bridge_ops *ops;
-
-	if (!dev || !dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		kfree(urb->transfer_buffer);
-		return;
-	}
-
-	dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
-			urb->status, urb->actual_length);
-
-	usb_autopm_put_interface(dev->intf);
-	ops = dev->ops;
-	if (ops)
-		ops->read_complete(ops->ctxt,
-				urb->transfer_buffer,
-				urb->transfer_buffer_length,
-				/* callback must check this value for error */
-				urb->status < 0 ?
-					urb->status : urb->actual_length);
-	else {
-		/* can't call back, free buffer on caller's behalf */
-		dev_err(&dev->udev->dev, "cannot complete read callback\n");
-		kfree(urb->transfer_buffer);
-	}
-}
-
-int dun_bridge_read(void *data, int len)
-{
-	struct dun_bridge *dev = __dev;
-	struct urb *urb;
-	int ret;
-
-	if (!dev || !dev->ops)
-		return -ENODEV;
-
-	if (!dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		return -ENODEV;
-	}
-
-	if (!len) {
-		dev_err(&dev->udev->dev, "%s: invalid len:%d\n", __func__, len);
-		return -EINVAL;
-	}
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb) {
-		dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
-		return -ENOMEM;
-	}
-
-	usb_fill_bulk_urb(urb, dev->udev, dev->in,
-			data, len, read_cb, dev);
-	usb_anchor_urb(urb, &dev->submitted);
-
-	usb_autopm_get_interface(dev->intf);
-	ret = usb_submit_urb(urb, GFP_KERNEL);
-	if (ret) {
-		dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
-			__func__, ret);
-		usb_unanchor_urb(urb);
-		usb_autopm_put_interface(dev->intf);
-	}
-
-	usb_free_urb(urb);
-	return ret;
-}
-EXPORT_SYMBOL(dun_bridge_read);
-
-static void write_cb(struct urb *urb)
-{
-	struct dun_bridge *dev = urb->context;
-	struct dun_bridge_ops *ops;
-
-	if (!dev || !dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		kfree(urb->transfer_buffer);
-		return;
-	}
-
-	dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
-			urb->status, urb->actual_length);
-
-	usb_autopm_put_interface(dev->intf);
-	ops = dev->ops;
-	if (ops)
-		ops->write_complete(ops->ctxt,
-				urb->transfer_buffer,
-				urb->transfer_buffer_length,
-				/* callback must check this value for error */
-				urb->status < 0 ?
-					urb->status : urb->actual_length);
-	else {
-		/* can't call back, free buffer on caller's behalf */
-		dev_err(&dev->udev->dev, "cannot complete write callback\n");
-		kfree(urb->transfer_buffer);
-	}
-}
-
-int dun_bridge_write(void *data, int len)
-{
-	struct dun_bridge *dev = __dev;
-	struct urb *urb;
-	int ret;
-
-	if (!dev || !dev->ops)
-		return -ENODEV;
-
-	if (!dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		return -ENODEV;
-	}
-
-	if (!len) {
-		dev_err(&dev->udev->dev, "%s: invalid len:%d\n", __func__, len);
-		return -EINVAL;
-	}
-
-	urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!urb) {
-		dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
-		return -ENOMEM;
-	}
-
-	usb_fill_bulk_urb(urb, dev->udev, dev->out,
-			data, len, write_cb, dev);
-	usb_anchor_urb(urb, &dev->submitted);
-
-	usb_autopm_get_interface(dev->intf);
-	ret = usb_submit_urb(urb, GFP_KERNEL);
-	if (ret) {
-		dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
-			__func__, ret);
-		usb_unanchor_urb(urb);
-		usb_autopm_put_interface(dev->intf);
-	}
-
-	usb_free_urb(urb);
-	return ret;
-}
-EXPORT_SYMBOL(dun_bridge_write);
-
-static void ctrl_cb(struct urb *urb)
-{
-	struct dun_bridge *dev = urb->context;
-	usb_autopm_put_interface(dev->intf);
-}
-
-int dun_bridge_send_ctrl_bits(unsigned ctrl_bits)
-{
-	struct dun_bridge *dev = __dev;
-	struct urb *urb = NULL;
-	int ret;
-
-	if (!dev || !dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		return -ENODEV;
-	}
-
-	dev_dbg(&dev->udev->dev, "%s: %#x", __func__, ctrl_bits);
-
-	dev->cmd.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	dev->cmd.bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
-	dev->cmd.wValue = cpu_to_le16(ctrl_bits);
-	dev->cmd.wIndex = cpu_to_le16(dev->int_in_epaddr);
-	dev->cmd.wLength = 0;
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
-		return -ENOMEM;
-	}
-
-	usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
-			     (unsigned char *)&dev->cmd, NULL, 0,
-			     ctrl_cb, dev);
-
-	usb_autopm_get_interface(dev->intf);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
-			__func__, ret);
-		usb_autopm_put_interface(dev->intf);
-	}
-
-	usb_free_urb(urb);
-	return ret;
-}
-EXPORT_SYMBOL(dun_bridge_send_ctrl_bits);
-
-static void int_cb(struct urb *urb)
-{
-	struct dun_bridge *dev = urb->context;
-	struct usb_cdc_notification *dr = urb->transfer_buffer;
-	unsigned char *data;
-	unsigned int ctrl_bits;
-	int status = urb->status;
-
-	if (!dev || !dev->intf) {
-		pr_err("%s: device is disconnected\n", __func__);
-		return;
-	}
-
-	switch (status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dev_err(&dev->udev->dev,
-			"%s - urb shutting down with status: %d\n",
-			__func__, status);
-		return;
-	default:
-		dev_err(&dev->udev->dev,
-			"%s - nonzero urb status received: %d\n",
-			__func__, status);
-		goto resubmit_urb;
-	}
-
-	data = (unsigned char *)(dr + 1);
-	switch (dr->bNotificationType) {
-	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
-		dev_dbg(&dev->udev->dev, "%s network\n", dr->wValue ?
-					"connected to" : "disconnected from");
-		break;
-
-	case USB_CDC_NOTIFY_SERIAL_STATE:
-		ctrl_bits = get_unaligned_le16(data);
-		dev_dbg(&dev->udev->dev, "serial state: %d\n", ctrl_bits);
-		if (dev->ops && dev->ops->ctrl_status)
-			dev->ops->ctrl_status(dev->ops->ctxt, ctrl_bits);
-		break;
-
-	default:
-		dev_err(&dev->udev->dev, "unknown notification %d received: "
-			"index %d len %d data0 %d data1 %d\n",
-			dr->bNotificationType, dr->wIndex,
-			dr->wLength, data[0], data[1]);
-		break;
-	}
-resubmit_urb:
-	status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
-	if (status)
-		dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
-			__func__, status);
-}
-
-static void dun_bridge_delete(struct kref *kref)
-{
-	struct dun_bridge *dev = container_of(kref, struct dun_bridge, kref);
-
-	__dev = NULL;
-	usb_put_dev(dev->udev);
-	usb_free_urb(dev->inturb);
-	kfree(dev->ctrl_buf);
-	kfree(dev);
-}
-
-static int
-dun_bridge_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-	struct dun_bridge *dev;
-	struct usb_host_interface *iface_desc;
-	struct usb_endpoint_descriptor *epd;
-	__u8 iface_num;
-	int i;
-	int ctrlsize = 0;
-	int ret = -ENOMEM;
-
-	iface_desc = intf->cur_altsetting;
-	iface_num = iface_desc->desc.bInterfaceNumber;
-
-	/* is this interface supported? */
-	if (iface_num != id->driver_info)
-		return -ENODEV;
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev) {
-		pr_err("%s: unable to allocate dev\n", __func__);
-		goto error;
-	}
-
-	dev->pdev = platform_device_alloc("dun_bridge", 0);
-	if (!dev->pdev) {
-		pr_err("%s: unable to allocate platform device\n", __func__);
-		kfree(dev);
-		return -ENOMEM;
-	}
-	__dev = dev;
-
-	kref_init(&dev->kref);
-	dev->udev = usb_get_dev(interface_to_usbdev(intf));
-	dev->intf = intf;
-
-	init_usb_anchor(&dev->submitted);
-	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!dev->inturb) {
-		ret = -ENOMEM;
-		goto error;
-	}
-
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		epd = &iface_desc->endpoint[i].desc;
-
-		if (usb_endpoint_is_int_in(epd)) {
-			dev->int_in_epaddr = epd->bEndpointAddress;
-			ctrlsize = le16_to_cpu(epd->wMaxPacketSize);
-
-			dev->ctrl_buf = kzalloc(ctrlsize, GFP_KERNEL);
-			if (!dev->ctrl_buf) {
-				ret = -ENOMEM;
-				goto error;
-			}
-
-			usb_fill_int_urb(dev->inturb, dev->udev,
-					 usb_rcvintpipe(dev->udev,
-							dev->int_in_epaddr),
-					 dev->ctrl_buf, ctrlsize,
-					 int_cb, dev, epd->bInterval);
-
-		} else if (usb_endpoint_is_bulk_in(epd))
-			dev->in = usb_rcvbulkpipe(dev->udev,
-						epd->bEndpointAddress &
-						USB_ENDPOINT_NUMBER_MASK);
-
-		else if (usb_endpoint_is_bulk_out(epd))
-			dev->out = usb_sndbulkpipe(dev->udev,
-						epd->bEndpointAddress &
-						USB_ENDPOINT_NUMBER_MASK);
-	}
-
-	if (!dev->int_in_epaddr && !dev->in && !dev->out) {
-		dev_err(&dev->udev->dev, "%s: could not find all endpoints\n",
-					__func__);
-		ret = -ENODEV;
-		goto error;
-	}
-
-	usb_set_intfdata(intf, dev);
-	platform_device_add(dev->pdev);
-	return 0;
-error:
-	if (dev)
-		kref_put(&dev->kref, dun_bridge_delete);
-	return ret;
-}
-
-static void dun_bridge_disconnect(struct usb_interface *intf)
-{
-	struct dun_bridge *dev = usb_get_intfdata(intf);
-
-	platform_device_del(dev->pdev);
-	usb_set_intfdata(intf, NULL);
-	dev->intf = NULL;
-
-	kref_put(&dev->kref, dun_bridge_delete);
-
-	pr_debug("%s: DUN Bridge now disconnected\n", __func__);
-}
-
-static int dun_bridge_suspend(struct usb_interface *intf, pm_message_t message)
-{
-	struct dun_bridge *dev = usb_get_intfdata(intf);
-
-	dev_dbg(&dev->udev->dev, "%s:", __func__);
-	usb_unlink_anchored_urbs(&dev->submitted);
-	usb_unlink_urb(dev->inturb);
-
-	return 0;
-}
-
-static int dun_bridge_resume(struct usb_interface *intf)
-{
-	struct dun_bridge *dev = usb_get_intfdata(intf);
-	int ret = 0;
-
-	if (dev->ops && dev->ops->ctrl_status) {
-		ret = usb_submit_urb(dev->inturb, GFP_KERNEL);
-		if (ret)
-			dev_err(&dev->udev->dev, "%s: submit int urb err: %d\n",
-				__func__, ret);
-	}
-
-	return ret;
-}
-
-#define VALID_INTERFACE_NUM	2
-static const struct usb_device_id id_table[] = {
-	{ USB_DEVICE(0x05c6, 0x9001),	/* Generic QC Modem device */
-	.driver_info = VALID_INTERFACE_NUM },
-	{ }				/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static struct usb_driver dun_bridge_driver = {
-	.name			= "dun_usb_bridge",
-	.probe			= dun_bridge_probe,
-	.disconnect		= dun_bridge_disconnect,
-	.id_table		= id_table,
-	.suspend		= dun_bridge_suspend,
-	.resume			= dun_bridge_resume,
-	.supports_autosuspend	= true,
-};
-
-static int __init dun_bridge_init(void)
-{
-	int ret;
-
-	ret = usb_register(&dun_bridge_driver);
-	if (ret)
-		pr_err("%s: unable to register dun_bridge_driver\n", __func__);
-
-	return ret;
-}
-
-static void __exit dun_bridge_exit(void)
-{
-	usb_deregister(&dun_bridge_driver);
-}
-
-module_init(dun_bridge_init);
-module_exit(dun_bridge_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL V2");
diff --git a/drivers/usb/misc/dun_bridge_test.c b/drivers/usb/misc/dun_bridge_test.c
deleted file mode 100644
index d545e13..0000000
--- a/drivers/usb/misc/dun_bridge_test.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2011, 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/slab.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/debugfs.h>
-#include <linux/usb/cdc.h>
-#include <linux/uaccess.h>
-#include <mach/usb_dun_bridge.h>
-
-#define RD_BUF_SIZE		2048
-#define DUN_TEST_CONNECTED	0
-
-
-struct dun_bridge_test_dev {
-	char *read_buf;
-	size_t buflen;
-	struct work_struct read_w;
-	unsigned long	flags;
-
-	struct dun_bridge_ops	ops;
-};
-static struct dun_bridge_test_dev *__dev;
-
-static struct dentry *dfile;
-
-static void
-dun_bridge_test_read_complete(void *d, char *buf, size_t size, size_t actual)
-{
-	if (actual < 0) {
-		pr_err("%s: read complete err\n", __func__);
-		return;
-	}
-
-	__dev->buflen = actual;
-	buf[actual] = 0;
-
-	pr_info("%s: %s\n", __func__, buf);
-
-	if (test_bit(DUN_TEST_CONNECTED, &__dev->flags))
-		schedule_work(&__dev->read_w);
-}
-
-static void dun_bridge_test_read_work(struct work_struct *w)
-{
-	struct dun_bridge_test_dev *dev =
-		container_of(w, struct dun_bridge_test_dev, read_w);
-
-	dun_bridge_read(dev->read_buf, RD_BUF_SIZE);
-}
-
-static void
-dun_bridge_test_write_complete(void *d, char *buf, size_t size, size_t actual)
-{
-	struct dun_bridge_test_dev *dev = d;
-
-	if (actual > 0)
-		schedule_work(&dev->read_w);
-
-	kfree(buf);
-}
-
-#if defined(CONFIG_DEBUG_FS)
-#define DEBUG_BUF_SIZE	1024
-
-#define ACM_CTRL_DTR		0x01
-#define ACM_CTRL_RTS		0x02
-
-static int debug_open(struct inode *inode, struct file *file)
-{
-	struct dun_bridge_test_dev *dev = __dev;
-	int ret = 0;
-
-	if (!dev)
-		return -ENODEV;
-
-	if (!test_bit(DUN_TEST_CONNECTED, &dev->flags)) {
-		ret = dun_bridge_open(&dev->ops);
-		if (ret)
-			return ret;
-		set_bit(DUN_TEST_CONNECTED, &dev->flags);
-		dun_bridge_send_ctrl_bits(ACM_CTRL_DTR | ACM_CTRL_RTS);
-	}
-
-	return ret;
-}
-
-static ssize_t debug_read(struct file *file, char __user *ubuf,
-				 size_t count, loff_t *ppos)
-{
-	struct dun_bridge_test_dev	*dev = __dev;
-	return simple_read_from_buffer(ubuf, count, ppos,
-			dev->read_buf, dev->buflen);
-}
-
-static ssize_t debug_write(struct file *file, const char __user *ubuf,
-				 size_t count, loff_t *ppos)
-{
-	struct dun_bridge_test_dev *dev = __dev;
-	unsigned char *buf;
-	int ret;
-
-	if (!dev)
-		return -ENODEV;
-
-	buf = kmalloc(count, GFP_KERNEL);
-	if (!buf) {
-		pr_err("%s: unable to allocate mem for writing\n", __func__);
-		return -ENOMEM;
-	}
-
-	if (!copy_from_user(buf, ubuf, count)) {
-		ret = dun_bridge_write(buf, count);
-		if (ret < 0) {
-			pr_err("%s: error writing to dun_bridge\n", __func__);
-			kfree(buf);
-			return ret;
-		}
-	} else {
-		pr_err("%s: error copying for writing\n", __func__);
-		kfree(buf);
-	}
-
-	return count;
-}
-
-const struct file_operations dun_bridge_test_debug_ops = {
-	.open = debug_open,
-	.read = debug_read,
-	.write = debug_write,
-};
-
-static void dun_bridge_test_debug_init(void)
-{
-	dfile = debugfs_create_file("dun_bridge_test", 0555, NULL,
-			NULL, &dun_bridge_test_debug_ops);
-}
-#else
-static void dun_bridge_test_debug_init(void) { }
-#endif
-
-static int __init dun_bridge_test_init(void)
-{
-	struct dun_bridge_test_dev	*dev;
-
-	pr_info("%s\n", __func__);
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	__dev = dev;
-
-	dev->ops.read_complete = dun_bridge_test_read_complete;
-	dev->ops.write_complete = dun_bridge_test_write_complete;
-	dev->read_buf = kmalloc(RD_BUF_SIZE, GFP_KERNEL);
-	if (!dev->read_buf) {
-		pr_err("%s: unable to allocate read buffer\n", __func__);
-		kfree(dev);
-		return -ENOMEM;
-	}
-
-	dev->ops.ctxt = dev;
-	INIT_WORK(&dev->read_w, dun_bridge_test_read_work);
-
-	dun_bridge_test_debug_init();
-
-	return 0;
-}
-
-static void __exit dun_bridge_test_exit(void)
-{
-	struct dun_bridge_test_dev *dev = __dev;
-
-	pr_info("%s:\n", __func__);
-
-	if (test_bit(DUN_TEST_CONNECTED, &dev->flags))
-		dun_bridge_close();
-
-	debugfs_remove(dfile);
-
-	kfree(dev->read_buf);
-	kfree(dev);
-}
-
-module_init(dun_bridge_test_init);
-module_exit(dun_bridge_test_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL V2");
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
new file mode 100644
index 0000000..87adf2e
--- /dev/null
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -0,0 +1,729 @@
+/* Copyright (c) 2011, 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/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/ratelimit.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/cdc.h>
+#include <linux/termios.h>
+#include <asm/unaligned.h>
+#include <mach/usb_bridge.h>
+
+static const char *ctrl_bridge_names[] = {
+	"dun_ctrl_hsic0",
+	"rmnet_ctrl_hsic0"
+};
+
+/* polling interval for Interrupt ep */
+#define HS_INTERVAL		7
+#define FS_LS_INTERVAL		3
+
+#define ACM_CTRL_DTR		(1 << 0)
+#define DEFAULT_READ_URB_LENGTH	4096
+
+struct ctrl_bridge {
+
+	struct usb_device	*udev;
+	struct usb_interface	*intf;
+
+	unsigned int		int_pipe;
+	struct urb		*inturb;
+	void			*intbuf;
+
+	struct urb		*readurb;
+	void			*readbuf;
+
+	struct usb_anchor	tx_submitted;
+	struct usb_ctrlrequest	*in_ctlreq;
+
+	struct bridge		*brdg;
+	struct platform_device	*pdev;
+
+	/* input control lines (DSR, CTS, CD, RI) */
+	unsigned int		cbits_tohost;
+
+	/* output control lines (DTR, RTS) */
+	unsigned int		cbits_tomdm;
+
+	/* counters */
+	unsigned int		snd_encap_cmd;
+	unsigned int		get_encap_res;
+	unsigned int		resp_avail;
+	unsigned int		set_ctrl_line_sts;
+	unsigned int		notify_ser_state;
+
+};
+
+static struct ctrl_bridge	*__dev[MAX_BRIDGE_DEVICES];
+
+/* counter used for indexing ctrl bridge devices */
+static int	ch_id;
+
+unsigned int ctrl_bridge_get_cbits_tohost(unsigned int id)
+{
+	struct ctrl_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[id];
+	if (!dev)
+		return -ENODEV;
+
+	return dev->cbits_tohost;
+}
+EXPORT_SYMBOL(ctrl_bridge_get_cbits_tohost);
+
+int ctrl_bridge_set_cbits(unsigned int id, unsigned int cbits)
+{
+	struct ctrl_bridge	*dev;
+	struct bridge		*brdg;
+	int			retval;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[id];
+	if (!dev)
+		return -ENODEV;
+
+	pr_debug("%s: dev[id] =%u cbits : %u\n", __func__, id, cbits);
+
+	brdg = dev->brdg;
+	if (!brdg)
+		return -ENODEV;
+
+	dev->cbits_tomdm = cbits;
+
+	retval = ctrl_bridge_write(id, NULL, 0);
+
+	/* if DTR is high, update latest modem info to host */
+	if (brdg && (cbits & ACM_CTRL_DTR) && brdg->ops.send_cbits)
+		brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
+
+	return retval;
+}
+EXPORT_SYMBOL(ctrl_bridge_set_cbits);
+
+static void resp_avail_cb(struct urb *urb)
+{
+	struct ctrl_bridge	*dev = urb->context;
+	struct usb_device	*udev;
+	int			status = 0;
+	int			resubmit_urb = 1;
+	struct bridge		*brdg = dev->brdg;
+
+	udev = interface_to_usbdev(dev->intf);
+	switch (urb->status) {
+	case 0:
+		/*success*/
+		dev->get_encap_res++;
+		if (brdg && brdg->ops.send_pkt)
+			brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
+				urb->actual_length);
+		break;
+
+	/*do not resubmit*/
+	case -ESHUTDOWN:
+	case -ENOENT:
+	case -ECONNRESET:
+		/* unplug */
+	case -EPROTO:
+		/*babble error*/
+		resubmit_urb = 0;
+	/*resubmit*/
+	case -EOVERFLOW:
+	default:
+		dev_dbg(&udev->dev, "%s: non zero urb status = %d\n",
+			__func__, urb->status);
+	}
+
+	if (resubmit_urb) {
+		/*re- submit int urb to check response available*/
+		status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
+		if (status)
+			dev_err(&udev->dev,
+				"%s: Error re-submitting Int URB %d\n",
+				__func__, status);
+	}
+}
+
+static void notification_available_cb(struct urb *urb)
+{
+	int				status;
+	struct usb_cdc_notification	*ctrl;
+	struct usb_device		*udev;
+	struct ctrl_bridge		*dev = urb->context;
+	struct bridge			*brdg = dev->brdg;
+	unsigned int			ctrl_bits;
+	unsigned char			*data;
+
+	udev = interface_to_usbdev(dev->intf);
+
+	switch (urb->status) {
+	case 0:
+		/*success*/
+		break;
+	case -ESHUTDOWN:
+	case -ENOENT:
+	case -ECONNRESET:
+	case -EPROTO:
+		 /* unplug */
+		 return;
+	case -EPIPE:
+		dev_err(&udev->dev, "%s: stall on int endpoint\n", __func__);
+		/* TBD : halt to be cleared in work */
+	case -EOVERFLOW:
+	default:
+		pr_debug_ratelimited("%s: non zero urb status = %d\n",
+					__func__, urb->status);
+		goto resubmit_int_urb;
+	}
+
+	ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
+	data = (unsigned char *)(ctrl + 1);
+
+	switch (ctrl->bNotificationType) {
+	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
+		dev->resp_avail++;
+		usb_fill_control_urb(dev->readurb, udev,
+					usb_rcvctrlpipe(udev, 0),
+					(unsigned char *)dev->in_ctlreq,
+					dev->readbuf,
+					DEFAULT_READ_URB_LENGTH,
+					resp_avail_cb, dev);
+
+		status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
+		if (status) {
+			dev_err(&udev->dev,
+				"%s: Error submitting Read URB %d\n",
+				__func__, status);
+			goto resubmit_int_urb;
+		}
+		return;
+	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+		dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ?
+					"connected to" : "disconnected from");
+		break;
+	case USB_CDC_NOTIFY_SERIAL_STATE:
+		dev->notify_ser_state++;
+		ctrl_bits = get_unaligned_le16(data);
+		dev_dbg(&udev->dev, "serial state: %d\n", ctrl_bits);
+		dev->cbits_tohost = ctrl_bits;
+		if (brdg && brdg->ops.send_cbits)
+			brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
+		break;
+	default:
+		dev_err(&udev->dev, "%s: unknown notification %d received:"
+			"index %d len %d data0 %d data1 %d",
+			__func__, ctrl->bNotificationType, ctrl->wIndex,
+			ctrl->wLength, data[0], data[1]);
+	}
+
+resubmit_int_urb:
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status)
+		dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
+		__func__, status);
+}
+
+int ctrl_bridge_start_read(struct ctrl_bridge *dev)
+{
+	int			retval = 0;
+	struct usb_device	*udev;
+
+	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;
+	}
+
+	retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
+	if (retval < 0)
+		dev_err(&udev->dev, "%s intr submit %d\n", __func__, retval);
+
+	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;
+
+	if (!brdg) {
+		err("bridge is null\n");
+		return -EINVAL;
+	}
+
+	if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[brdg->ch_id];
+	if (!dev) {
+		err("dev is null\n");
+		return -ENODEV;
+	}
+
+	dev->brdg = brdg;
+	dev->snd_encap_cmd = 0;
+	dev->get_encap_res = 0;
+	dev->resp_avail = 0;
+	dev->set_ctrl_line_sts = 0;
+	dev->notify_ser_state = 0;
+
+	return ctrl_bridge_start_read(dev);
+}
+EXPORT_SYMBOL(ctrl_bridge_open);
+
+void ctrl_bridge_close(unsigned int id)
+{
+	struct ctrl_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return;
+
+	dev  = __dev[id];
+	if (!dev && !dev->brdg)
+		return;
+
+	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+
+	ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
+	usb_unlink_anchored_urbs(&dev->tx_submitted);
+	ctrl_bridge_stop_read(dev);
+
+	dev->brdg = NULL;
+}
+EXPORT_SYMBOL(ctrl_bridge_close);
+
+static void ctrl_write_callback(struct urb *urb)
+{
+
+	if (urb->status) {
+		pr_debug("Write status/size %d/%d\n",
+			urb->status, urb->actual_length);
+	}
+
+	kfree(urb->transfer_buffer);
+	kfree(urb->setup_packet);
+	usb_free_urb(urb);
+}
+
+int ctrl_bridge_write(unsigned int id, char *data, size_t size)
+{
+	int			result;
+	struct urb		*writeurb;
+	struct usb_ctrlrequest	*out_ctlreq;
+	struct usb_device	*udev;
+	struct ctrl_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES) {
+		result = -EINVAL;
+		goto free_data;
+	}
+
+	dev = __dev[id];
+
+	if (!dev) {
+		result = -ENODEV;
+		goto free_data;
+	}
+
+	udev = interface_to_usbdev(dev->intf);
+
+	dev_dbg(&udev->dev, "%s:[id]:%u: write (%d bytes)\n",
+		__func__, id, size);
+
+	writeurb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!writeurb) {
+		dev_err(&udev->dev, "%s: error allocating read urb\n",
+			__func__);
+		result = -ENOMEM;
+		goto free_data;
+	}
+
+	out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
+	if (!out_ctlreq) {
+		dev_err(&udev->dev,
+			"%s: error allocating setup packet buffer\n",
+			__func__);
+		result = -ENOMEM;
+		goto free_urb;
+	}
+
+	/* CDC Send Encapsulated Request packet */
+	out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE);
+	if (!data && !size) {
+		out_ctlreq->bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
+		out_ctlreq->wValue = dev->cbits_tomdm;
+		dev->set_ctrl_line_sts++;
+	} else {
+		out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
+		out_ctlreq->wValue = 0;
+		dev->snd_encap_cmd++;
+	}
+	out_ctlreq->wIndex =
+		dev->intf->cur_altsetting->desc.bInterfaceNumber;
+	out_ctlreq->wLength = cpu_to_le16(size);
+
+	usb_fill_control_urb(writeurb, udev,
+				 usb_sndctrlpipe(udev, 0),
+				 (unsigned char *)out_ctlreq,
+				 (void *)data, size,
+				 ctrl_write_callback, NULL);
+
+	result = usb_autopm_get_interface_async(dev->intf);
+	if (result < 0) {
+		dev_err(&udev->dev, "%s: unable to resume interface: %d\n",
+			__func__, result);
+
+		/*
+		  * Revisit: if (result == -EPERM)
+		  * bridge_suspend(dev->intf, PMSG_SUSPEND);
+		  */
+
+		goto free_ctrlreq;
+	}
+
+	usb_anchor_urb(writeurb, &dev->tx_submitted);
+	result = usb_submit_urb(writeurb, GFP_ATOMIC);
+	if (result < 0) {
+		dev_err(&udev->dev, "%s: submit URB error %d\n",
+			__func__, result);
+		usb_autopm_put_interface_async(dev->intf);
+		goto unanchor_urb;
+	}
+
+	return size;
+
+unanchor_urb:
+	usb_unanchor_urb(writeurb);
+free_ctrlreq:
+	kfree(out_ctlreq);
+free_urb:
+	usb_free_urb(writeurb);
+free_data:
+	kfree(data);
+
+	return result;
+}
+EXPORT_SYMBOL(ctrl_bridge_write);
+
+int ctrl_bridge_suspend(unsigned int id)
+{
+	struct ctrl_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[id];
+	if (!dev)
+		return -ENODEV;
+
+	usb_kill_anchored_urbs(&dev->tx_submitted);
+
+	return ctrl_bridge_stop_read(dev);
+}
+
+int ctrl_bridge_resume(unsigned int id)
+{
+	struct ctrl_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[id];
+	if (!dev)
+		return -ENODEV;
+
+	return ctrl_bridge_start_read(dev);
+}
+
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	1024
+static ssize_t ctrl_bridge_read_stats(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	struct ctrl_bridge	*dev;
+	char			*buf;
+	int			ret;
+	int			i;
+	int			temp = 0;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < ch_id; i++) {
+		dev = __dev[i];
+		if (!dev)
+			continue;
+
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\nName#%s dev %p\n"
+				"snd encap cmd cnt: %u\n"
+				"get encap res cnt: %u\n"
+				"res available cnt: %u\n"
+				"set ctrlline sts cnt: %u\n"
+				"notify ser state cnt: %u\n"
+				"cbits_tomdm: %d\n"
+				"cbits_tohost: %d\n",
+				dev->pdev->name, dev,
+				dev->snd_encap_cmd,
+				dev->get_encap_res,
+				dev->resp_avail,
+				dev->set_ctrl_line_sts,
+				dev->notify_ser_state,
+				dev->cbits_tomdm,
+				dev->cbits_tohost);
+
+	}
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t ctrl_bridge_reset_stats(struct file *file,
+	const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct ctrl_bridge	*dev;
+	int			i;
+
+	for (i = 0; i < ch_id; i++) {
+		dev = __dev[i];
+		if (!dev)
+			continue;
+
+		dev->snd_encap_cmd = 0;
+		dev->get_encap_res = 0;
+		dev->resp_avail = 0;
+		dev->set_ctrl_line_sts = 0;
+		dev->notify_ser_state = 0;
+	}
+	return count;
+}
+
+const struct file_operations ctrl_stats_ops = {
+	.read = ctrl_bridge_read_stats,
+	.write = ctrl_bridge_reset_stats,
+};
+
+struct dentry	*ctrl_dent;
+struct dentry	*ctrl_dfile;
+static void ctrl_bridge_debugfs_init(void)
+{
+	ctrl_dent = debugfs_create_dir("ctrl_hsic_bridge", 0);
+	if (IS_ERR(ctrl_dent))
+		return;
+
+	ctrl_dfile =
+		debugfs_create_file("status", 0644, ctrl_dent, 0,
+			&ctrl_stats_ops);
+	if (!ctrl_dfile || IS_ERR(ctrl_dfile))
+		debugfs_remove(ctrl_dent);
+}
+
+static void ctrl_bridge_debugfs_exit(void)
+{
+	debugfs_remove(ctrl_dfile);
+	debugfs_remove(ctrl_dent);
+}
+
+#else
+static void ctrl_bridge_debugfs_init(void) { }
+static void ctrl_bridge_debugfs_exit(void) { }
+#endif
+
+int
+ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
+		int id)
+{
+	struct ctrl_bridge		*dev;
+	struct usb_device		*udev;
+	struct usb_endpoint_descriptor	*ep;
+	u16				wMaxPacketSize;
+	int				retval = 0;
+	int				interval;
+
+	udev = interface_to_usbdev(ifc);
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		dev_err(&udev->dev, "%s: unable to allocate dev\n",
+			__func__);
+		return -ENOMEM;
+	}
+	dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
+	if (!dev->pdev) {
+		dev_err(&dev->udev->dev,
+			"%s: unable to allocate platform device\n", __func__);
+		retval = -ENOMEM;
+		goto nomem;
+	}
+
+	dev->udev = udev;
+	dev->int_pipe = usb_rcvintpipe(udev,
+		int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+	dev->intf = ifc;
+
+	init_usb_anchor(&dev->tx_submitted);
+
+	/*use max pkt size from ep desc*/
+	ep = &dev->intf->cur_altsetting->endpoint[0].desc;
+
+	dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->inturb) {
+		dev_err(&udev->dev, "%s: error allocating int urb\n", __func__);
+		retval = -ENOMEM;
+		goto pdev_del;
+	}
+
+	wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
+
+	dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
+	if (!dev->intbuf) {
+		dev_err(&udev->dev, "%s: error allocating int buffer\n",
+			__func__);
+		retval = -ENOMEM;
+		goto free_inturb;
+	}
+
+	interval =
+		(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);
+
+	dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!dev->readurb) {
+		dev_err(&udev->dev, "%s: error allocating read urb\n",
+			__func__);
+		retval = -ENOMEM;
+		goto free_intbuf;
+	}
+
+	dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
+	if (!dev->readbuf) {
+		dev_err(&udev->dev, "%s: error allocating read buffer\n",
+			__func__);
+		retval = -ENOMEM;
+		goto free_rurb;
+	}
+
+	dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
+	if (!dev->in_ctlreq) {
+		dev_err(&udev->dev,
+			"%s:error allocating setup packet buffer\n",
+			__func__);
+		retval = -ENOMEM;
+		goto free_rbuf;
+	}
+
+	dev->in_ctlreq->bRequestType =
+			(USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
+	dev->in_ctlreq->bRequest  = USB_CDC_GET_ENCAPSULATED_RESPONSE;
+	dev->in_ctlreq->wValue = 0;
+	dev->in_ctlreq->wIndex =
+		dev->intf->cur_altsetting->desc.bInterfaceNumber;
+	dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
+
+	__dev[id] = dev;
+
+	platform_device_add(dev->pdev);
+
+	ch_id++;
+
+	return retval;
+
+free_rbuf:
+	kfree(dev->readbuf);
+free_rurb:
+	usb_free_urb(dev->readurb);
+free_intbuf:
+	kfree(dev->intbuf);
+free_inturb:
+	usb_free_urb(dev->inturb);
+pdev_del:
+	platform_device_del(dev->pdev);
+nomem:
+	kfree(dev);
+
+	return retval;
+}
+
+void ctrl_bridge_disconnect(unsigned int id)
+{
+	struct ctrl_bridge	*dev = __dev[id];
+
+	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+
+	kfree(dev->in_ctlreq);
+	kfree(dev->readbuf);
+	kfree(dev->intbuf);
+
+	usb_free_urb(dev->readurb);
+	usb_free_urb(dev->inturb);
+
+	platform_device_del(dev->pdev);
+	__dev[id] = NULL;
+	ch_id--;
+
+	kfree(dev);
+}
+
+static int __init ctrl_bridge_init(void)
+{
+	ctrl_bridge_debugfs_init();
+
+	return 0;
+}
+module_init(ctrl_bridge_init);
+
+static void __exit ctrl_bridge_exit(void)
+{
+	ctrl_bridge_debugfs_exit();
+}
+module_exit(ctrl_bridge_exit);
+
+MODULE_DESCRIPTION("Qualcomm modem control bridge driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
new file mode 100644
index 0000000..c41fcfb
--- /dev/null
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -0,0 +1,923 @@
+/* Copyright (c) 2011, 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/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/ratelimit.h>
+#include <mach/usb_bridge.h>
+
+#define MAX_RX_URBS			50
+#define RMNET_RX_BUFSIZE		2048
+
+#define STOP_SUBMIT_URB_LIMIT		400
+#define FLOW_CTRL_EN_THRESHOLD		500
+#define FLOW_CTRL_DISABLE		300
+#define FLOW_CTRL_SUPPORT		1
+
+static const char	*data_bridge_names[] = {
+	"dun_data_hsic0",
+	"rmnet_data_hsic0"
+};
+
+static struct workqueue_struct	*bridge_wq;
+
+static unsigned int	fctrl_support = FLOW_CTRL_SUPPORT;
+module_param(fctrl_support, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int	fctrl_en_thld = FLOW_CTRL_EN_THRESHOLD;
+module_param(fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int	fctrl_dis_thld = FLOW_CTRL_DISABLE;
+module_param(fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
+
+unsigned int	max_rx_urbs = MAX_RX_URBS;
+module_param(max_rx_urbs, uint, S_IRUGO | S_IWUSR);
+
+unsigned int	stop_submit_urb_limit = STOP_SUBMIT_URB_LIMIT;
+module_param(stop_submit_urb_limit, uint, S_IRUGO | S_IWUSR);
+
+#define TX_HALT   BIT(0)
+#define RX_HALT   BIT(1)
+#define SUSPENDED BIT(2)
+
+struct data_bridge {
+	struct usb_interface		*intf;
+	struct usb_device		*udev;
+	unsigned int			bulk_in;
+	unsigned int			bulk_out;
+
+	/* keep track of in-flight URBs */
+	struct usb_anchor		tx_active;
+	struct usb_anchor		rx_active;
+
+	/* keep track of outgoing URBs during suspend */
+	struct usb_anchor		delayed;
+
+	struct list_head		rx_idle;
+	struct sk_buff_head		rx_done;
+
+	struct workqueue_struct		*wq;
+	struct work_struct		process_rx_w;
+
+	struct bridge			*brdg;
+
+	/* work queue function for handling halt conditions */
+	struct work_struct		kevent;
+
+	unsigned long			flags;
+
+	struct platform_device		*pdev;
+
+	/* counters */
+	atomic_t			pending_txurbs;
+	unsigned int			txurb_drp_cnt;
+	unsigned long			to_host;
+	unsigned long			to_modem;
+	unsigned int			tx_throttled_cnt;
+	unsigned int			tx_unthrottled_cnt;
+	unsigned int			rx_throttled_cnt;
+	unsigned int			rx_unthrottled_cnt;
+};
+
+static struct data_bridge	*__dev[MAX_BRIDGE_DEVICES];
+
+/* counter used for indexing data bridge devices */
+static int	ch_id;
+
+static int submit_rx_urb(struct data_bridge *dev, struct urb *urb,
+		gfp_t flags);
+
+static inline  bool rx_halted(struct data_bridge *dev)
+{
+	return test_bit(RX_HALT, &dev->flags);
+}
+
+static inline bool rx_throttled(struct bridge *brdg)
+{
+	return test_bit(RX_THROTTLED, &brdg->flags);
+}
+
+int data_bridge_unthrottle_rx(unsigned int id)
+{
+	struct data_bridge	*dev;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[id];
+	if (!dev && !dev->brdg)
+		return -ENODEV;
+
+	dev->rx_unthrottled_cnt++;
+	queue_work(dev->wq, &dev->process_rx_w);
+
+	return 0;
+}
+EXPORT_SYMBOL(data_bridge_unthrottle_rx);
+
+static void data_bridge_process_rx(struct work_struct *work)
+{
+	int			retval;
+	unsigned long		flags;
+	struct urb		*rx_idle;
+	struct sk_buff		*skb;
+	struct data_bridge	*dev =
+		container_of(work, struct data_bridge, process_rx_w);
+
+	struct bridge		*brdg = dev->brdg;
+
+	if (!brdg || !brdg->ops.send_pkt || rx_halted(dev))
+		return;
+
+	while (!rx_throttled(brdg) && (skb = skb_dequeue(&dev->rx_done))) {
+		dev->to_host++;
+		/* hand off sk_buff to client,they'll need to free it */
+		retval = brdg->ops.send_pkt(brdg->ctx, skb, skb->len);
+		if (retval == -ENOTCONN || retval == -EINVAL) {
+			return;
+		} else if (retval == -EBUSY) {
+			dev->rx_throttled_cnt++;
+			break;
+		}
+	}
+
+	spin_lock_irqsave(&dev->rx_done.lock, flags);
+	if (dev->rx_done.qlen > stop_submit_urb_limit && rx_throttled(brdg)) {
+		spin_unlock_irqrestore(&dev->rx_done.lock, flags);
+		return;
+	}
+
+	while (!list_empty(&dev->rx_idle)) {
+
+		rx_idle = list_first_entry(&dev->rx_idle, struct urb, urb_list);
+		list_del(&rx_idle->urb_list);
+		spin_unlock_irqrestore(&dev->rx_done.lock, flags);
+		retval = submit_rx_urb(dev, rx_idle, GFP_KERNEL);
+		spin_lock_irqsave(&dev->rx_done.lock, flags);
+		if (retval)
+			break;
+	}
+	spin_unlock_irqrestore(&dev->rx_done.lock, flags);
+}
+
+static void data_bridge_read_cb(struct urb *urb)
+{
+	struct bridge		*brdg;
+	struct sk_buff		*skb = urb->context;
+	struct data_bridge	*dev = *(struct data_bridge **)skb->cb;
+	bool			queue = 0;
+
+	brdg = dev->brdg;
+
+	skb_put(skb, urb->actual_length);
+
+	switch (urb->status) {
+	case 0: /* success */
+		queue = 1;
+		spin_lock(&dev->rx_done.lock);
+		__skb_queue_tail(&dev->rx_done, skb);
+		spin_unlock(&dev->rx_done.lock);
+		break;
+
+	/*do not resubmit*/
+	case -EPIPE:
+		set_bit(RX_HALT, &dev->flags);
+		dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+		schedule_work(&dev->kevent);
+		/* FALLTHROUGH */
+	case -ESHUTDOWN:
+	case -ENOENT: /* suspended */
+	case -ECONNRESET: /* unplug */
+	case -EPROTO:
+		dev_kfree_skb_any(skb);
+		break;
+
+	/*resubmit */
+	case -EOVERFLOW: /*babble error*/
+	default:
+		queue = 1;
+		dev_kfree_skb_any(skb);
+		pr_debug_ratelimited("%s: non zero urb status = %d\n",
+			__func__, urb->status);
+		break;
+	}
+
+	spin_lock(&dev->rx_done.lock);
+	list_add_tail(&urb->urb_list, &dev->rx_idle);
+	spin_unlock(&dev->rx_done.lock);
+
+	if (queue)
+		queue_work(dev->wq, &dev->process_rx_w);
+}
+
+static int submit_rx_urb(struct data_bridge *dev, struct urb *rx_urb,
+	gfp_t flags)
+{
+	struct sk_buff	*skb;
+	int		retval = -EINVAL;
+
+	skb = alloc_skb(RMNET_RX_BUFSIZE, flags);
+	if (!skb) {
+		usb_free_urb(rx_urb);
+		return -ENOMEM;
+	}
+
+	*((struct data_bridge **)skb->cb) = dev;
+
+	usb_fill_bulk_urb(rx_urb, dev->udev, dev->bulk_in,
+			  skb->data, RMNET_RX_BUFSIZE,
+			  data_bridge_read_cb, skb);
+
+	if (test_bit(SUSPENDED, &dev->flags))
+		goto suspended;
+
+	usb_anchor_urb(rx_urb, &dev->rx_active);
+	retval = usb_submit_urb(rx_urb, flags);
+	if (retval)
+		goto fail;
+
+	return 0;
+fail:
+	usb_unanchor_urb(rx_urb);
+suspended:
+	dev_kfree_skb_any(skb);
+	usb_free_urb(rx_urb);
+	return retval;
+}
+
+static int data_bridge_prepare_rx(struct data_bridge *dev)
+{
+	int		i;
+	struct urb	*rx_urb;
+
+	for (i = 0; i < max_rx_urbs; i++) {
+		rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!rx_urb)
+			return -ENOMEM;
+
+		list_add_tail(&rx_urb->urb_list, &dev->rx_idle);
+	}
+	 return 0;
+}
+
+int data_bridge_open(struct bridge *brdg)
+{
+	struct data_bridge	*dev;
+
+	if (!brdg) {
+		err("bridge is null\n");
+		return -EINVAL;
+	}
+
+	if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
+		return -EINVAL;
+
+	dev = __dev[brdg->ch_id];
+	if (!dev) {
+		err("dev is null\n");
+		return -ENODEV;
+	}
+
+	dev_dbg(&dev->udev->dev, "%s: dev:%p\n", __func__, dev);
+
+	dev->brdg = brdg;
+	atomic_set(&dev->pending_txurbs, 0);
+	dev->to_host = 0;
+	dev->to_modem = 0;
+	dev->txurb_drp_cnt = 0;
+	dev->tx_throttled_cnt = 0;
+	dev->tx_unthrottled_cnt = 0;
+	dev->rx_throttled_cnt = 0;
+	dev->rx_unthrottled_cnt = 0;
+
+	queue_work(dev->wq, &dev->process_rx_w);
+
+	return 0;
+}
+EXPORT_SYMBOL(data_bridge_open);
+
+void data_bridge_close(unsigned int id)
+{
+	struct data_bridge	*dev;
+	struct sk_buff		*skb;
+	unsigned long		flags;
+
+	if (id >= MAX_BRIDGE_DEVICES)
+		return;
+
+	dev  = __dev[id];
+	if (!dev && !dev->brdg)
+		return;
+
+	dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+
+	usb_unlink_anchored_urbs(&dev->tx_active);
+	usb_unlink_anchored_urbs(&dev->rx_active);
+	usb_unlink_anchored_urbs(&dev->delayed);
+
+	spin_lock_irqsave(&dev->rx_done.lock, flags);
+	while ((skb = __skb_dequeue(&dev->rx_done)))
+		dev_kfree_skb_any(skb);
+	spin_unlock_irqrestore(&dev->rx_done.lock, flags);
+
+	dev->brdg = NULL;
+}
+EXPORT_SYMBOL(data_bridge_close);
+
+static void defer_kevent(struct work_struct *work)
+{
+	int			status;
+	struct data_bridge	*dev =
+		container_of(work, struct data_bridge, kevent);
+
+	if (!dev)
+		return;
+
+	if (test_bit(TX_HALT, &dev->flags)) {
+		usb_unlink_anchored_urbs(&dev->tx_active);
+
+		status = usb_autopm_get_interface(dev->intf);
+		if (status < 0) {
+			dev_err(&dev->udev->dev,
+				"can't acquire interface, status %d\n", status);
+			return;
+		}
+
+		status = usb_clear_halt(dev->udev, dev->bulk_out);
+		usb_autopm_put_interface(dev->intf);
+		if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
+			dev_err(&dev->udev->dev,
+				"can't clear tx halt, status %d\n", status);
+		else
+			clear_bit(TX_HALT, &dev->flags);
+	}
+
+	if (test_bit(RX_HALT, &dev->flags)) {
+		usb_unlink_anchored_urbs(&dev->rx_active);
+
+		status = usb_autopm_get_interface(dev->intf);
+		if (status < 0) {
+			dev_err(&dev->udev->dev,
+				"can't acquire interface, status %d\n", status);
+			return;
+		}
+
+		status = usb_clear_halt(dev->udev, dev->bulk_in);
+		usb_autopm_put_interface(dev->intf);
+		if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
+			dev_err(&dev->udev->dev,
+				"can't clear rx halt, status %d\n", status);
+		else {
+			clear_bit(RX_HALT, &dev->flags);
+			if (dev->brdg)
+				queue_work(dev->wq, &dev->process_rx_w);
+		}
+	}
+}
+
+static void data_bridge_write_cb(struct urb *urb)
+{
+	struct sk_buff		*skb = urb->context;
+	struct data_bridge	*dev = *(struct data_bridge **)skb->cb;
+	struct bridge		*brdg = dev->brdg;
+	int			pending;
+
+	pr_debug("%s: dev:%p\n", __func__, dev);
+
+	switch (urb->status) {
+	case 0: /*success*/
+		break;
+	case -EPIPE:
+		set_bit(TX_HALT, &dev->flags);
+		dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+		schedule_work(&dev->kevent);
+		/* FALLTHROUGH */
+	case -ESHUTDOWN:
+	case -ENOENT: /* suspended */
+	case -ECONNRESET: /* unplug */
+	case -EOVERFLOW: /*babble error*/
+		/* FALLTHROUGH */
+	default:
+		pr_debug_ratelimited("%s: non zero urb status = %d\n",
+					__func__, urb->status);
+	}
+
+	usb_free_urb(urb);
+	dev_kfree_skb_any(skb);
+
+	pending = atomic_dec_return(&dev->pending_txurbs);
+
+	/*flow ctrl*/
+	if (brdg && fctrl_support && pending <= fctrl_dis_thld &&
+		test_and_clear_bit(TX_THROTTLED, &brdg->flags)) {
+		pr_debug_ratelimited("%s: disable flow ctrl: pend urbs:%u\n",
+			__func__, pending);
+		dev->tx_unthrottled_cnt++;
+		if (brdg->ops.unthrottle_tx)
+			brdg->ops.unthrottle_tx(brdg->ctx);
+	}
+
+	usb_autopm_put_interface_async(dev->intf);
+}
+
+int data_bridge_write(unsigned int id, struct sk_buff *skb)
+{
+	int			result;
+	int			size = skb->len;
+	int			pending;
+	struct urb		*txurb;
+	struct data_bridge	*dev = __dev[id];
+	struct bridge		*brdg;
+
+	if (!dev || !dev->brdg || !usb_get_intfdata(dev->intf))
+		return -ENODEV;
+
+	brdg = dev->brdg;
+
+	dev_dbg(&dev->udev->dev, "%s: write (%d bytes)\n", __func__, skb->len);
+
+	result = usb_autopm_get_interface(dev->intf);
+	if (result < 0) {
+		dev_err(&dev->udev->dev, "%s: resume failure\n", __func__);
+		goto error;
+	}
+
+	txurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!txurb) {
+		dev_err(&dev->udev->dev, "%s: error allocating read urb\n",
+			__func__);
+		result = -ENOMEM;
+		goto error;
+	}
+
+	/* store dev pointer in skb */
+	*((struct data_bridge **)skb->cb) = dev;
+
+	usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out,
+			skb->data, skb->len, data_bridge_write_cb, skb);
+
+	if (test_bit(SUSPENDED, &dev->flags)) {
+		usb_anchor_urb(txurb, &dev->delayed);
+		goto free_urb;
+	}
+
+	pending = atomic_inc_return(&dev->pending_txurbs);
+	usb_anchor_urb(txurb, &dev->tx_active);
+
+	result = usb_submit_urb(txurb, GFP_KERNEL);
+	if (result < 0) {
+		usb_unanchor_urb(txurb);
+		atomic_dec(&dev->pending_txurbs);
+		dev_err(&dev->udev->dev, "%s: submit URB error %d\n",
+			__func__, result);
+		goto free_urb;
+	}
+
+	dev->to_modem++;
+	dev_dbg(&dev->udev->dev, "%s: pending_txurbs: %u\n", __func__, pending);
+
+	/* flow control: last urb submitted but return -EBUSY */
+	if (fctrl_support && pending > fctrl_en_thld) {
+		set_bit(TX_THROTTLED, &brdg->flags);
+		dev->tx_throttled_cnt++;
+		pr_debug_ratelimited("%s: enable flow ctrl pend txurbs:%u\n",
+					__func__, pending);
+		return -EBUSY;
+	}
+
+	return size;
+
+free_urb:
+	usb_free_urb(txurb);
+error:
+	dev->txurb_drp_cnt++;
+	usb_autopm_put_interface(dev->intf);
+
+	return result;
+}
+EXPORT_SYMBOL(data_bridge_write);
+
+static int data_bridge_resume(struct data_bridge *dev)
+{
+	struct urb	*urb;
+	int		retval;
+
+	while ((urb = usb_get_from_anchor(&dev->delayed))) {
+		usb_anchor_urb(urb, &dev->tx_active);
+		atomic_inc(&dev->pending_txurbs);
+		retval = usb_submit_urb(urb, GFP_ATOMIC);
+		if (retval < 0) {
+			atomic_dec(&dev->pending_txurbs);
+			usb_unanchor_urb(urb);
+
+			/* TODO: need to free urb data */
+			usb_scuttle_anchored_urbs(&dev->delayed);
+			break;
+		}
+		dev->to_modem++;
+		dev->txurb_drp_cnt--;
+	}
+
+	clear_bit(SUSPENDED, &dev->flags);
+
+	if (dev->brdg)
+		queue_work(dev->wq, &dev->process_rx_w);
+
+	return 0;
+}
+
+static int bridge_resume(struct usb_interface *iface)
+{
+	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);
+	}
+	return retval;
+}
+
+static int data_bridge_suspend(struct data_bridge *dev, pm_message_t message)
+{
+	if (atomic_read(&dev->pending_txurbs) &&
+		(message.event & PM_EVENT_AUTO))
+		return -EBUSY;
+
+	set_bit(SUSPENDED, &dev->flags);
+
+	usb_kill_anchored_urbs(&dev->tx_active);
+	usb_kill_anchored_urbs(&dev->rx_active);
+
+	return 0;
+}
+
+static int bridge_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	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__);
+	}
+	return retval;
+}
+
+static int data_bridge_probe(struct usb_interface *iface,
+		struct usb_host_endpoint *bulk_in,
+		struct usb_host_endpoint *bulk_out, int id)
+{
+	struct data_bridge	*dev;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		err("%s: unable to allocate dev\n", __func__);
+		return -ENOMEM;
+	}
+
+	dev->pdev = platform_device_alloc(data_bridge_names[id], id);
+	if (!dev->pdev) {
+		err("%s: unable to allocate platform device\n", __func__);
+		kfree(dev);
+		return -ENOMEM;
+	}
+
+	init_usb_anchor(&dev->tx_active);
+	init_usb_anchor(&dev->rx_active);
+	init_usb_anchor(&dev->delayed);
+
+	INIT_LIST_HEAD(&dev->rx_idle);
+	skb_queue_head_init(&dev->rx_done);
+
+	dev->wq = bridge_wq;
+
+	dev->udev = interface_to_usbdev(iface);
+	dev->intf = iface;
+
+	dev->bulk_in = usb_rcvbulkpipe(dev->udev,
+		bulk_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+	dev->bulk_out = usb_sndbulkpipe(dev->udev,
+		bulk_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
+
+	usb_set_intfdata(iface, dev);
+
+	INIT_WORK(&dev->kevent, defer_kevent);
+	INIT_WORK(&dev->process_rx_w, data_bridge_process_rx);
+
+	__dev[id] = dev;
+
+	/*allocate list of rx urbs*/
+	data_bridge_prepare_rx(dev);
+
+	platform_device_add(dev->pdev);
+
+	return 0;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+#define DEBUG_BUF_SIZE	1024
+static ssize_t data_bridge_read_stats(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	struct data_bridge	*dev;
+	char			*buf;
+	int			ret;
+	int			i;
+	int			temp = 0;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (i = 0; i < ch_id; i++) {
+		dev = __dev[i];
+		if (!dev)
+			continue;
+
+		temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
+				"\nName#%s dev %p\n"
+				"pending tx urbs:    %u\n"
+				"tx urb drp cnt:     %u\n"
+				"to host:            %lu\n"
+				"to mdm:             %lu\n"
+				"tx throttled cnt:   %u\n"
+				"tx unthrottled cnt: %u\n"
+				"rx throttled cnt:   %u\n"
+				"rx unthrottled cnt: %u\n"
+				"rx done skb qlen:   %u\n"
+				"suspended:          %d\n"
+				"TX_HALT:            %d\n"
+				"RX_HALT:            %d\n",
+				dev->pdev->name, dev,
+				atomic_read(&dev->pending_txurbs),
+				dev->txurb_drp_cnt,
+				dev->to_host,
+				dev->to_modem,
+				dev->tx_throttled_cnt,
+				dev->tx_unthrottled_cnt,
+				dev->rx_throttled_cnt,
+				dev->rx_unthrottled_cnt,
+				dev->rx_done.qlen,
+				test_bit(SUSPENDED, &dev->flags),
+				test_bit(TX_HALT, &dev->flags),
+				test_bit(RX_HALT, &dev->flags));
+
+	}
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
+
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t data_bridge_reset_stats(struct file *file,
+	const char __user *buf, size_t count, loff_t *ppos)
+{
+	struct data_bridge	*dev;
+	int			i;
+
+	for (i = 0; i < ch_id; i++) {
+		dev = __dev[i];
+		if (!dev)
+			continue;
+
+		dev->to_host = 0;
+		dev->to_modem = 0;
+		dev->txurb_drp_cnt = 0;
+		dev->tx_throttled_cnt = 0;
+		dev->tx_unthrottled_cnt = 0;
+		dev->rx_throttled_cnt = 0;
+		dev->rx_unthrottled_cnt = 0;
+	}
+	return count;
+}
+
+const struct file_operations data_stats_ops = {
+	.read = data_bridge_read_stats,
+	.write = data_bridge_reset_stats,
+};
+
+struct dentry	*data_dent;
+struct dentry	*data_dfile;
+static void data_bridge_debugfs_init(void)
+{
+	data_dent = debugfs_create_dir("data_hsic_bridge", 0);
+	if (IS_ERR(data_dent))
+		return;
+
+	data_dfile = debugfs_create_file("status", 0644, data_dent, 0,
+			&data_stats_ops);
+	if (!data_dfile || IS_ERR(data_dfile))
+		debugfs_remove(data_dent);
+}
+
+static void data_bridge_debugfs_exit(void)
+{
+	debugfs_remove(data_dfile);
+	debugfs_remove(data_dent);
+}
+
+#else
+static void data_bridge_debugfs_init(void) { }
+static void data_bridge_debugfs_exit(void) { }
+#endif
+
+static int __devinit
+bridge_probe(struct usb_interface *iface, const struct usb_device_id *id)
+{
+	struct usb_host_endpoint	*endpoint = NULL;
+	struct usb_host_endpoint	*bulk_in = NULL;
+	struct usb_host_endpoint	*bulk_out = NULL;
+	struct usb_host_endpoint	*int_in = NULL;
+	struct usb_device		*udev;
+	int				i;
+	int				status = 0;
+	int				numends;
+	int				iface_num;
+
+	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+
+	if (iface->num_altsetting != 1) {
+		err("%s invalid num_altsetting %u\n",
+				__func__, iface->num_altsetting);
+		return -EINVAL;
+	}
+
+	udev = interface_to_usbdev(iface);
+	usb_get_dev(udev);
+
+	if (iface_num != DUN_IFACE_NUM && iface_num != TETHERED_RMNET_IFACE_NUM)
+		return 0;
+
+	numends = iface->cur_altsetting->desc.bNumEndpoints;
+	for (i = 0; i < numends; i++) {
+		endpoint = iface->cur_altsetting->endpoint + i;
+		if (!endpoint) {
+			dev_err(&udev->dev, "%s: invalid endpoint %u\n",
+					__func__, i);
+			status = -EINVAL;
+			goto out;
+		}
+
+		if (usb_endpoint_is_bulk_in(&endpoint->desc))
+			bulk_in = endpoint;
+		else if (usb_endpoint_is_bulk_out(&endpoint->desc))
+			bulk_out = endpoint;
+		else if (usb_endpoint_is_int_in(&endpoint->desc))
+			int_in = endpoint;
+	}
+
+	if (!bulk_in || !bulk_out || !int_in) {
+		dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
+		status = -EINVAL;
+		goto out;
+	}
+
+	status = data_bridge_probe(iface, bulk_in, bulk_out, ch_id);
+	if (status < 0) {
+		dev_err(&udev->dev, "data_bridge_probe failed %d\n", status);
+		goto out;
+	}
+
+	status = ctrl_bridge_probe(iface, int_in, ch_id);
+	if (status < 0) {
+		dev_err(&udev->dev, "ctrl_bridge_probe failed %d\n", status);
+		goto free_data_bridge;
+	}
+	ch_id++;
+
+	return 0;
+
+free_data_bridge:
+	platform_device_del(__dev[ch_id]->pdev);
+	usb_set_intfdata(iface, NULL);
+	kfree(__dev[ch_id]);
+	__dev[ch_id] = NULL;
+out:
+	usb_put_dev(udev);
+
+	return status;
+}
+
+static void bridge_disconnect(struct usb_interface *intf)
+{
+	struct data_bridge	*dev = usb_get_intfdata(intf);
+	struct list_head	*head;
+	struct urb		*rx_urb;
+	unsigned long		flags;
+	int			iface_num;
+
+	if (!dev) {
+		err("%s: data device not found\n", __func__);
+		return;
+	}
+
+	iface_num = intf->cur_altsetting->desc.bInterfaceNumber;
+	if (iface_num != DUN_IFACE_NUM && iface_num != TETHERED_RMNET_IFACE_NUM)
+		return;
+
+	ch_id--;
+	ctrl_bridge_disconnect(ch_id);
+	platform_device_del(dev->pdev);
+	usb_set_intfdata(intf, NULL);
+	__dev[ch_id] = NULL;
+
+	cancel_work_sync(&dev->process_rx_w);
+	cancel_work_sync(&dev->kevent);
+
+	/*free rx urbs*/
+	head = &dev->rx_idle;
+	spin_lock_irqsave(&dev->rx_done.lock, flags);
+	while (!list_empty(head)) {
+		rx_urb = list_entry(head->next, struct urb, urb_list);
+		list_del(&rx_urb->urb_list);
+		usb_free_urb(rx_urb);
+	}
+	spin_unlock_irqrestore(&dev->rx_done.lock, flags);
+
+	usb_put_dev(dev->udev);
+	kfree(dev);
+}
+
+static const struct usb_device_id bridge_ids[] = {
+	  { USB_DEVICE(0x5c6, 0x9001) },
+};
+
+MODULE_DEVICE_TABLE(usb, bridge_ids);
+
+static struct usb_driver bridge_driver = {
+	.name =			"mdm_bridge",
+	.probe =		bridge_probe,
+	.disconnect =		bridge_disconnect,
+	.id_table =		bridge_ids,
+	.suspend =		bridge_suspend,
+	.resume =		bridge_resume,
+	.supports_autosuspend =	1,
+};
+
+static int __init bridge_init(void)
+{
+	int	ret;
+
+	ret = usb_register(&bridge_driver);
+	if (ret) {
+		err("%s: unable to register mdm_bridge driver", __func__);
+		return ret;
+	}
+
+	bridge_wq  = create_singlethread_workqueue("mdm_bridge");
+	if (!bridge_wq) {
+		usb_deregister(&bridge_driver);
+		pr_err("%s: Unable to create workqueue:bridge\n", __func__);
+		return -ENOMEM;
+	}
+
+	data_bridge_debugfs_init();
+
+	return 0;
+}
+
+static void __exit bridge_exit(void)
+{
+	data_bridge_debugfs_exit();
+	destroy_workqueue(bridge_wq);
+	usb_deregister(&bridge_driver);
+}
+
+module_init(bridge_init);
+module_exit(bridge_exit);
+
+MODULE_DESCRIPTION("Qualcomm modem data bridge driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index 714099a..be3a279d 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -1226,11 +1226,17 @@
 {
 	struct msm_otg *dev = the_msm_otg;
 
-	if (!atomic_read(&dev->in_lpm) || !online)
-		return;
+	/*
+	 * Process disconnect only for wallcharger
+	 * during fast plug-out plug-in at the
+	 * AC source side.
+	 */
+	if (online)
+		set_bit(B_SESS_VLD, &dev->inputs);
+	else
+		clear_bit(B_SESS_VLD, &dev->inputs);
 
 	wake_lock(&dev->wlock);
-	set_bit(B_SESS_VLD, &dev->inputs);
 	queue_work(dev->wq, &dev->sm_work);
 }
 
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 3467e0d..4a4bd15 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -49,6 +49,8 @@
 #define MSM_HDMI_SAMPLE_RATE_MAX		7
 #define MSM_HDMI_SAMPLE_RATE_FORCE_32BIT	0x7FFFFFFF
 
+static int msm_hdmi_sample_rate = MSM_HDMI_SAMPLE_RATE_48KHZ;
+
 struct workqueue_struct *hdmi_work_queue;
 struct hdmi_msm_state_type *hdmi_msm_state;
 
@@ -2670,7 +2672,30 @@
 	for (i = 0; i < ksv_bytes - 1; i++) {
 		/* Write KSV byte and do not set DONE bit[0] */
 		HDMI_OUTP_ND(0x0244, kvs_fifo[i] << 16);
+
+		/* Once 64 bytes have been written, we need to poll for
+		 * HDCP_SHA_BLOCK_DONE before writing any further
+		 */
+		if (i && !((i+1)%64)) {
+			timeout_count = 100;
+			while (!(HDMI_INP_ND(0x0240) & 0x1)
+					&& (--timeout_count)) {
+				DEV_DBG("HDCP Auth Part II: Waiting for the "
+					"computation of the current 64 byte to "
+					"complete. HDCP_SHA_STATUS=%08x. "
+					"timeout_count=%d\n",
+					 HDMI_INP_ND(0x0240), timeout_count);
+				msleep(20);
+			}
+			if (!timeout_count) {
+				ret = -ETIMEDOUT;
+				DEV_ERR("%s(%d): timedout", __func__, __LINE__);
+				goto error;
+			}
+		}
+
 	}
+
 	/* Write l to DONE bit[0] */
 	HDMI_OUTP_ND(0x0244, (kvs_fifo[ksv_bytes - 1] << 16) | 0x1);
 
@@ -2678,8 +2703,9 @@
 	[4] COMP_DONE */
 	/* Now wait for HDCP_SHA_COMP_DONE */
 	timeout_count = 100;
-	while ((0x10 != (HDMI_INP_ND(0x0240) & 0x10)) && timeout_count--)
+	while ((0x10 != (HDMI_INP_ND(0x0240) & 0xFFFFFF10)) && --timeout_count)
 		msleep(20);
+
 	if (!timeout_count) {
 		ret = -ETIMEDOUT;
 		DEV_ERR("%s(%d): timedout", __func__, __LINE__);
@@ -2690,8 +2716,10 @@
 	[20] V_MATCHES */
 	timeout_count = 100;
 	while (((HDMI_INP_ND(0x011C) & (1 << 20)) != (1 << 20))
-	    && timeout_count--)
+	    && --timeout_count) {
 		msleep(20);
+	}
+
 	if (!timeout_count) {
 		ret = -ETIMEDOUT;
 		DEV_ERR("%s(%d): timedout", __func__, __LINE__);
@@ -3331,6 +3359,23 @@
 }
 #endif
 
+int hdmi_msm_audio_get_sample_rate(void)
+{
+	return msm_hdmi_sample_rate;
+}
+EXPORT_SYMBOL(hdmi_msm_audio_get_sample_rate);
+
+void hdmi_msm_audio_sample_rate_reset(int rate)
+{
+	msm_hdmi_sample_rate = rate;
+
+	if (hdmi_msm_has_hdcp())
+		hdcp_deauthenticate();
+	else
+		hdmi_msm_turn_on();
+}
+EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
+
 static void hdmi_msm_audio_setup(void)
 {
 	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
@@ -3344,7 +3389,7 @@
 	DEV_DBG("Not setting ACP, ISRC1, ISRC2 packets\n");
 	hdmi_msm_audio_acr_setup(TRUE,
 		external_common_state->video_resolution,
-		MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
+		msm_hdmi_sample_rate, channels);
 	hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
 
 	/* Turn on Audio FIFO and SAM DROP ISR */
@@ -3682,7 +3727,27 @@
 static void hdmi_msm_turn_on(void)
 {
 	uint32 hpd_ctrl;
+	uint32 audio_pkt_ctrl, audio_cfg;
+	/*
+	 * Number of wait iterations for QDSP to disable Audio Engine
+	 * before resetting HDMI core
+	 */
+	int i = 10;
+	audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+	audio_cfg = HDMI_INP_ND(0x01D0);
 
+	/*
+	 * Checking BIT[0] of AUDIO PACKET CONTROL and
+	 * AUDIO CONFIGURATION register
+	 */
+	while (((audio_pkt_ctrl & 0x00000001) || (audio_cfg & 0x00000001))
+		&& (i--)) {
+		audio_pkt_ctrl = HDMI_INP_ND(0x0020);
+		audio_cfg = HDMI_INP_ND(0x01D0);
+		DEV_DBG("%d times :: HDMI AUDIO PACKET is %08x and "
+			"AUDIO CFG is %08x", i, audio_pkt_ctrl, audio_cfg);
+		msleep(20);
+	}
 	hdmi_msm_reset_core();
 	hdmi_msm_init_phy(external_common_state->video_resolution);
 	/* HDMI_USEC_REFTIMER[0x0208] */
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index a511e3c..2eb08b8 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -320,16 +320,29 @@
 	ulong intr_dma_e;
 	ulong intr_overlay0;
 	ulong intr_overlay1;
+	ulong intr_vsync_p;	/* Primary interface */
 	ulong intr_underrun_p;	/* Primary interface */
+	ulong intr_vsync_e;	/* external interface */
 	ulong intr_underrun_e;	/* external interface */
+	ulong intr_histogram;
+	ulong intr_rd_ptr;
+	ulong dsi_mdp_start;
+	ulong dsi_clk_on;
+	ulong dsi_clk_off;
 	ulong intr_dsi;
-	ulong kickoff_mddi;
-	ulong kickoff_lcdc;
-	ulong kickoff_dtv;
-	ulong kickoff_atv;
-	ulong kickoff_dsi;
-	ulong kickoff_writeback;
-	ulong writeback;	/* blt */
+	ulong intr_dsi_mdp;
+	ulong intr_dsi_cmd;
+	ulong intr_dsi_err;
+	ulong kickoff_ov0;
+	ulong kickoff_ov1;
+	ulong kickoff_dmap;
+	ulong kickoff_dmae;
+	ulong kickoff_dmas;
+	ulong blt_dsi_cmd;	/* blt */
+	ulong blt_dsi_video;	/* blt */
+	ulong blt_lcdc;	/* blt */
+	ulong blt_dtv;	/* blt */
+	ulong blt_mddi;	/* blt */
 	ulong overlay_set[MDP4_MIXER_MAX];
 	ulong overlay_unset[MDP4_MIXER_MAX];
 	ulong overlay_play[MDP4_MIXER_MAX];
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 770424a..aecf554 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -65,7 +65,6 @@
 {
 	if (mipi_dsi_clk_on) {
 		if (dsi_state == ST_DSI_PLAYING) {
-			mdp4_stat.dsi_clkoff++;
 			mipi_dsi_turn_off_clks();
 			mdp4_overlay_dsi_state_set(ST_DSI_CLK_OFF);
 		}
@@ -325,7 +324,7 @@
 		dsi_pipe->ov_cnt = 0;
 		dsi_pipe->dmap_cnt = 0;
 		dsi_pipe->blt_addr = dsi_pipe->blt_base;
-		mdp4_stat.writeback++;
+		mdp4_stat.blt_dsi_cmd++;
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		return 0;
 	}
@@ -465,6 +464,7 @@
 	mdp4_blt_xy_update(dsi_pipe);
 	/* kick off dmap */
 	outpdw(MDP_BASE + 0x000c, 0x0);
+	mdp4_stat.kickoff_dmap++;
 	/* trigger dsi cmd engine */
 	mipi_dsi_cmd_mdp_start();
 
@@ -525,6 +525,7 @@
 	mdp_enable_irq(MDP_DMA2_TERM);	/* enable intr */
 	/* kick off dmap */
 	outpdw(MDP_BASE + 0x000c, 0x0);
+	mdp4_stat.kickoff_dmap++;
 	/* trigger dsi cmd engine */
 	mipi_dsi_cmd_mdp_start();
 	mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
@@ -670,6 +671,7 @@
 	/* start OVERLAY pipe */
 	spin_unlock_irqrestore(&mdp_spin_lock, flag);
 	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+	mdp4_stat.kickoff_ov0++;
 }
 
 void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
@@ -686,9 +688,6 @@
 
 		mdp4_dsi_cmd_kickoff_ui(mfd, dsi_pipe);
 
-
-		mdp4_stat.kickoff_dsi++;
-
 	/* signal if pan function is waiting for the update completion */
 		if (mfd->pan_waiting) {
 			mfd->pan_waiting = FALSE;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 1a5cb65..63beb88 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -498,6 +498,7 @@
 		mb();	/* make sure all registers updated */
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+		mdp4_stat.kickoff_ov0++;
 		mb();
 	}
 }
@@ -525,6 +526,7 @@
 		mb();	/* make sure all registers updated */
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+		mdp4_stat.kickoff_ov0++;
 		mb();
 		mdp4_overlay_dsi_video_wait4event(mfd, INTR_DMA_P_DONE);
 	} else {
@@ -589,6 +591,7 @@
 		dsi_pipe->blt_cnt = 0;
 		dsi_pipe->ov_cnt = 0;
 		dsi_pipe->dmap_cnt = 0;
+		mdp4_stat.blt_dsi_video++;
 		change++;
 	} else if (enable == 0 && dsi_pipe->blt_addr) {
 		dsi_pipe->blt_addr = 0;
@@ -698,5 +701,4 @@
 	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
-	mdp4_stat.kickoff_dsi++;
 }
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 636d350..d0c86d0 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -464,7 +464,5 @@
 		mfd->ov_end = true;
 	}
 	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
-
-	mdp4_stat.kickoff_dtv++;
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index f44a409..a8e39d0 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -422,6 +422,7 @@
 		mb();	/* make sure all registers updated */
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
+		mdp4_stat.kickoff_ov0++;
 		mb();
 		mdp4_overlay_lcdc_wait4event(mfd, INTR_DMA_P_DONE);
 	} else {
@@ -485,6 +486,7 @@
 		lcdc_pipe->blt_cnt = 0;
 		lcdc_pipe->ov_cnt = 0;
 		lcdc_pipe->dmap_cnt = 0;
+		mdp4_stat.blt_lcdc++;
 	} else if (enable == 0 && lcdc_pipe->blt_addr) {
 		lcdc_pipe->blt_addr = 0;
 		change++;
@@ -572,5 +574,4 @@
 	mdp4_overlay_reg_flush(pipe, 1);
 	mdp4_overlay_lcdc_vsync_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
-	mdp4_stat.kickoff_lcdc++;
 }
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 928ac32..83959df 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -475,6 +475,7 @@
 	mfd->dma->busy = TRUE;
 	/* start OVERLAY pipe */
 	mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
+	mdp4_stat.kickoff_ov0++;
 }
 
 void mdp4_dma_s_update_lcd(struct msm_fb_data_type *mfd,
@@ -557,6 +558,7 @@
 	mfd->ibuf_flushed = TRUE;
 	/* start dma_s pipe */
 	mdp_pipe_kickoff(MDP_DMA_S_TERM, mfd);
+	mdp4_stat.kickoff_dmas++;
 
 	/* wait until DMA finishes the current job */
 	wait_for_completion(&mfd->dma->comp);
@@ -593,8 +595,6 @@
 		} else	/* no dams dmap switch  */
 			mdp4_mddi_kickoff_ui(mfd, mddi_pipe);
 
-		mdp4_stat.kickoff_mddi++;
-
 	/* signal if pan function is waiting for the update completion */
 		if (mfd->pan_waiting) {
 			mfd->pan_waiting = FALSE;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index f96c7ea..f51427c 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -400,6 +400,7 @@
 
 	panel = mdp4_overlay_panel_list();
 	if (isr & INTR_PRIMARY_VSYNC) {
+		mdp4_stat.intr_vsync_p++;
 		dma = &dma2_data;
 		spin_lock(&mdp_spin_lock);
 		mdp_intr_mask &= ~INTR_PRIMARY_VSYNC;
@@ -415,6 +416,7 @@
 	}
 #ifdef CONFIG_FB_MSM_DTV
 	if (isr & INTR_EXTERNAL_VSYNC) {
+		mdp4_stat.intr_vsync_e++;
 		dma = &dma_e_data;
 		spin_lock(&mdp_spin_lock);
 		mdp_intr_mask &= ~INTR_EXTERNAL_VSYNC;
@@ -548,6 +550,7 @@
 		spin_unlock(&mdp_spin_lock);
 	}
 	if (isr & INTR_DMA_P_HISTOGRAM) {
+		mdp4_stat.intr_histogram++;
 		isr = inpdw(MDP_DMA_P_HIST_INTR_STATUS);
 		mask = inpdw(MDP_DMA_P_HIST_INTR_ENABLE);
 		outpdw(MDP_DMA_P_HIST_INTR_CLEAR, isr);
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
index b89e8c7..9ae1d9c 100644
--- a/drivers/video/msm/mdp_debugfs.c
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -272,7 +272,6 @@
 	int tot = 0;
 	int dlen;
 	char *bp;
-	unsigned long flag;
 
 
 	if (*ppos)
@@ -281,124 +280,210 @@
 	bp = debug_buf;
 	dlen = sizeof(debug_buf);
 
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	len = snprintf(bp, dlen, "intr_total:    %08lu\n",
+	len = snprintf(bp, dlen, "\nmdp:\n");
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "int_total: %08lu\t",
 					mdp4_stat.intr_tot);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "intr_dma_p:    %08lu\n",
-					mdp4_stat.intr_dma_p);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "intr_dma_s:    %08lu\n",
-					mdp4_stat.intr_dma_s);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "intr_dma_e:    %08lu\n",
-					mdp4_stat.intr_dma_e);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "intr_overlay0: %08lu\n",
+
+	len = snprintf(bp, dlen, "int_overlay0: %08lu\t",
 					mdp4_stat.intr_overlay0);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "intr_overlay1: %08lu\n",
+	len = snprintf(bp, dlen, "int_overlay1: %08lu\n",
 					mdp4_stat.intr_overlay1);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "unerrun_primary:  %08lu\n",
+
+	len = snprintf(bp, dlen, "int_dmap: %08lu\t",
+					mdp4_stat.intr_dma_p);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "int_dmas: %08lu\t",
+					mdp4_stat.intr_dma_s);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "int_dmae:  %08lu\n",
+					mdp4_stat.intr_dma_e);
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "primary:   vsync: %08lu\t",
+					mdp4_stat.intr_vsync_p);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "underrun: %08lu\n",
 					mdp4_stat.intr_underrun_p);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "unerrun_external:  %08lu\n\n",
+	len = snprintf(bp, dlen, "external:  vsync: %08lu\t",
+					mdp4_stat.intr_vsync_e);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "underrun: %08lu\n",
 					mdp4_stat.intr_underrun_e);
 
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "intr_dsi  :    %08lu\n\n",
-					mdp4_stat.intr_dsi);
+	len = snprintf(bp, dlen, "histogram: %08lu\t",
+					mdp4_stat.intr_histogram);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "read_ptr: %08lu\n\n",
+					mdp4_stat.intr_rd_ptr);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "dsi:\n");
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "int_total: %08lu\tmdp_start: %08lu\n",
+			mdp4_stat.intr_dsi, mdp4_stat.dsi_mdp_start);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "int_cmd: %08lu\t",
+					mdp4_stat.intr_dsi_cmd);
 
 	bp += len;
 	dlen -= len;
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-	len = snprintf(bp, dlen, "kickoff_mddi:      %08lu\n",
-					mdp4_stat.kickoff_mddi);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "kickoff_lcdc:      %08lu\n",
-					mdp4_stat.kickoff_lcdc);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "kickoff_dtv:       %08lu\n",
-					mdp4_stat.kickoff_dtv);
+	len = snprintf(bp, dlen, "int_mdp: %08lu\t",
+					mdp4_stat.intr_dsi_mdp);
 
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "kickoff_atv:       %08lu\n",
-					mdp4_stat.kickoff_atv);
+
+	len = snprintf(bp, dlen, "int_err: %08lu\n",
+					mdp4_stat.intr_dsi_err);
+
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "kickoff_dsi:       %08lu\n\n",
-					mdp4_stat.kickoff_dsi);
+	len = snprintf(bp, dlen, "clk_on : %08lu\t",
+					mdp4_stat.dsi_clk_on);
+
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "writeback:      %08lu\n",
-					mdp4_stat.writeback);
+	len = snprintf(bp, dlen, "clk_off: %08lu\n\n",
+					mdp4_stat.dsi_clk_off);
+
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay0_set:   %08lu\n",
+	len = snprintf(bp, dlen, "kickoff:\n");
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "overlay0: %08lu\t",
+					mdp4_stat.kickoff_ov0);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "dmap: %08lu\t",
+					mdp4_stat.kickoff_dmap);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "dmas: %08lu\n",
+					mdp4_stat.kickoff_dmas);
+
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "overlay1: %08lu\t",
+					mdp4_stat.kickoff_ov1);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "dmae: %08lu\n\n",
+					mdp4_stat.kickoff_dmae);
+
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "overlay0_play:\n");
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "set:   %08lu\t",
 					mdp4_stat.overlay_set[0]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay0_unset: %08lu\n",
+	len = snprintf(bp, dlen, "unset: %08lu\t",
 					mdp4_stat.overlay_unset[0]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay0_play:  %08lu\n",
+	len = snprintf(bp, dlen, "play:  %08lu\n",
 					mdp4_stat.overlay_play[0]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay1_set:   %08lu\n",
+
+	len = snprintf(bp, dlen, "overlay1_play:\n");
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "set:   %08lu\t",
 					mdp4_stat.overlay_set[1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay1_unset: %08lu\n",
+	len = snprintf(bp, dlen, "unset: %08lu\t",
 					mdp4_stat.overlay_unset[1]);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "overlay1_play:  %08lu\n\n",
+	len = snprintf(bp, dlen, "play:  %08lu\n\n",
 					mdp4_stat.overlay_play[1]);
 
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "pipe_rgb1:  %08lu\n", mdp4_stat.pipe[0]);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "pipe_rgb2:  %08lu\n", mdp4_stat.pipe[1]);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "pipe_vg1:   %08lu\n", mdp4_stat.pipe[2]);
-	bp += len;
-	dlen -= len;
-	len = snprintf(bp, dlen, "pipe_vg2:   %08lu\n\n", mdp4_stat.pipe[3]);
 
+	len = snprintf(bp, dlen, "frame_push:\n");
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "dsi_clkoff: %08lu\n\n", mdp4_stat.dsi_clkoff);
+	len = snprintf(bp, dlen, "rgb1:  %08lu\t\t", mdp4_stat.pipe[0]);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "rgb2:  %08lu\n", mdp4_stat.pipe[1]);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "vg1:   %08lu\t\t", mdp4_stat.pipe[2]);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "vg2:   %08lu\n", mdp4_stat.pipe[3]);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
+	bp += len;
+	dlen -= len;
+	len = snprintf(bp, dlen, "err_format: %08lu\n\n", mdp4_stat.err_format);
+	bp += len;
+	dlen -= len;
 
+	len = snprintf(bp, dlen, "writeback:\n");
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_mixer:  %08lu\n", mdp4_stat.err_mixer);
+
+	len = snprintf(bp, dlen, "dsi_cmd: %08lu\t",
+					mdp4_stat.blt_dsi_cmd);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_size:   %08lu\n", mdp4_stat.err_size);
+
+	len = snprintf(bp, dlen, "dsi_video: %08lu\n",
+					mdp4_stat.blt_dsi_video);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_scale:  %08lu\n", mdp4_stat.err_scale);
+
+	len = snprintf(bp, dlen, "lcdc: %08lu\t",
+					mdp4_stat.blt_lcdc);
 	bp += len;
 	dlen -= len;
-	len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
+
+	len = snprintf(bp, dlen, "dtv: %08lu\t",
+					mdp4_stat.blt_dtv);
+	bp += len;
+	dlen -= len;
+
+	len = snprintf(bp, dlen, "mddi: %08lu\n\n",
+					mdp4_stat.blt_mddi);
 	bp += len;
 	dlen -= len;
 
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 8d07e56..f2e2f10 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -51,6 +51,39 @@
 static struct list_head pre_kickoff_list;
 static struct list_head post_kickoff_list;
 
+enum {
+	STAT_DSI_START,
+	STAT_DSI_ERROR,
+	STAT_DSI_CMD,
+	STAT_DSI_MDP
+};
+
+#ifdef CONFIG_FB_MSM_MDP40
+void mipi_dsi_mdp_stat_inc(int which)
+{
+	switch (which) {
+	case STAT_DSI_START:
+		mdp4_stat.dsi_mdp_start++;
+		break;
+	case STAT_DSI_ERROR:
+		mdp4_stat.intr_dsi_err++;
+		break;
+	case STAT_DSI_CMD:
+		mdp4_stat.intr_dsi_cmd++;
+		break;
+	case STAT_DSI_MDP:
+		mdp4_stat.intr_dsi_mdp++;
+		break;
+	default:
+		break;
+	}
+}
+#else
+void mipi_dsi_mdp_stat_inc(int which)
+{
+}
+#endif
+
 void mipi_dsi_init(void)
 {
 	init_completion(&dsi_dma_comp);
@@ -986,6 +1019,7 @@
 				__func__, current->pid);
 }
 
+
 void mipi_dsi_cmd_mdp_start(void)
 {
 	unsigned long flag;
@@ -994,6 +1028,8 @@
 	if (!in_interrupt())
 		mipi_dsi_pre_kickoff_action();
 
+	mipi_dsi_mdp_stat_inc(STAT_DSI_START);
+
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
 	mipi_dsi_enable_irq();
 	dsi_mdp_busy = TRUE;
@@ -1438,6 +1474,7 @@
 #endif
 
 	if (isr & DSI_INTR_ERROR) {
+		mipi_dsi_mdp_stat_inc(STAT_DSI_ERROR);
 		mipi_dsi_error();
 	}
 
@@ -1448,10 +1485,12 @@
 	}
 
 	if (isr & DSI_INTR_CMD_DMA_DONE) {
+		mipi_dsi_mdp_stat_inc(STAT_DSI_CMD);
 		complete(&dsi_dma_comp);
 	}
 
 	if (isr & DSI_INTR_CMD_MDP_DONE) {
+		mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
 		spin_lock(&dsi_mdp_lock);
 		dsi_mdp_busy = FALSE;
 		spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index ba93df76..52a10ab 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -12,6 +12,8 @@
  */
 #include <linux/clk.h>
 #include "msm_fb.h"
+#include "mdp.h"
+#include "mdp4.h"
 #include "mipi_dsi.h"
 #include "hdmi_msm.h"
 #include <mach/msm_iomap.h>
@@ -555,6 +557,7 @@
 	mipi_dsi_clk_ctrl(&dsicore_clk, 1);
 	clk_enable(dsi_byte_div_clk);
 	clk_enable(dsi_esc_clk);
+	mdp4_stat.dsi_clk_on++;
 }
 
 void mipi_dsi_clk_disable(void)
@@ -565,6 +568,7 @@
 	mipi_dsi_clk_ctrl(&dsicore_clk, 0);
 	/* DSIPHY_PLL_CTRL_0, disable dsi pll */
 	MIPI_OUTP(MIPI_DSI_BASE + 0x0200, 0x0);
+	mdp4_stat.dsi_clk_off++;
 }
 
 void mipi_dsi_phy_ctrl(int on)
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 1a606b5..e1b9e73 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -423,6 +423,7 @@
 header-y += msm_audio_qcp.h
 header-y += msm_audio_amrnb.h
 header-y += msm_audio_voicememo.h
+header-y += msm_audio_sbc.h
 header-y += msm_ipc.h
 header-y += msm_charm.h
 header-y += tzcom.h
diff --git a/include/linux/atmel_maxtouch.h b/include/linux/atmel_maxtouch.h
index c582529..012e68b 100644
--- a/include/linux/atmel_maxtouch.h
+++ b/include/linux/atmel_maxtouch.h
@@ -283,7 +283,7 @@
 #endif
 
 /**
- * struct mxt_platform_data - includes platform specific informatio
+ * struct maxtouch_platform_data - includes platform specific informatio
  * related to Atmel maXTouch touchscreen controller.
  * 
  * @numtouch:           Number of simultaneous touches supported
@@ -298,7 +298,7 @@
  * @max_y:              Reported Y range
  */
  
-struct mxt_platform_data {
+struct maxtouch_platform_data {
 	u8    numtouch;	/* Number of touches to report	*/
 	int   (*init_platform_hw)(struct i2c_client *client);
 	int   (*exit_platform_hw)(struct i2c_client *client);
diff --git a/include/linux/earlysuspend.h b/include/linux/earlysuspend.h
old mode 100755
new mode 100644
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 7de40d4..89ac992 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -438,6 +438,7 @@
 /* struct ion_flush_data - data passed to ion for flushing caches
  *
  * @handle:	handle with data to flush
+ * @fd:		fd to flush
  * @vaddr:	userspace virtual address mapped with mmap
  * @offset:	offset into the handle to flush
  * @length:	length of handle to flush
@@ -448,6 +449,7 @@
  */
 struct ion_flush_data {
 	struct ion_handle *handle;
+	int fd;
 	void *vaddr;
 	unsigned int offset;
 	unsigned int length;
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index a4c23b0..f0a3278 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -44,6 +44,7 @@
 #define PM8XXX_REVISION_8921_1p0	1
 #define PM8XXX_REVISION_8921_1p1	2
 #define PM8XXX_REVISION_8921_2p0	3
+#define PM8XXX_REVISION_8921_3p0	4
 
 #define PM8XXX_REVISION_8821_TEST	0
 #define PM8XXX_REVISION_8821_1p0	1
diff --git a/include/linux/mfd/pm8xxx/pm8921-adc.h b/include/linux/mfd/pm8xxx/pm8921-adc.h
deleted file mode 100644
index c66ae84..0000000
--- a/include/linux/mfd/pm8xxx/pm8921-adc.h
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * Copyright (c) 2011, 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.
- */
-/*
- * Qualcomm PMIC 8921 ADC driver header file
- *
- */
-
-#ifndef __PM8921_ADC_H
-#define __PM8921_ADC_H
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-
-/**
- * enum pm8921_adc_channels - PM8921 AMUX arbiter channels
- * %CHANNEL_VCOIN: Backup voltage for certain register set
- * %CHANNEL_VBAT: Battery voltage
- * %CHANNEL_DCIN: Charger input voltage without internal OVP
- * %CHANNEL_ICHG: Charge-current monitor
- * %CHANNEL_VPH_PWR: Main system power
- * %CHANNEL_IBAT: Battery charge current
- * %CHANNEL_MPP_1: 16:1 pre-mux unity scale MPP input
- * %CHANNEL_MPP_2: 16:1 pre-mux 1/3 scale MPP input
- * %CHANNEL_BATT_THERM: Battery temperature
- * %CHANNEL_BATT_ID: Battery detection
- * %CHANNEL_USBIN: Charger input voltage with internal OVP
- * %CHANNEL_DIE_TEMP: Pmic_die temperature
- * %CHANNEL_625MV: 625mv reference channel
- * %CHANNEL_125V: 1.25v reference channel
- * %CHANNEL_CHG_TEMP: Charger temperature
- * %CHANNEL_MUXOFF: Channel to reduce input load on the mux
- * %CHANNEL_NONE: Do not use this channel
- */
-enum pm8921_adc_channels {
-	CHANNEL_VCOIN = 0,
-	CHANNEL_VBAT,
-	CHANNEL_DCIN,
-	CHANNEL_ICHG,
-	CHANNEL_VPH_PWR,
-	CHANNEL_IBAT,
-	CHANNEL_MPP_1,
-	CHANNEL_MPP_2,
-	CHANNEL_BATT_THERM,
-	CHANNEL_BATT_ID,
-	CHANNEL_USBIN,
-	CHANNEL_DIE_TEMP,
-	CHANNEL_625MV,
-	CHANNEL_125V,
-	CHANNEL_CHG_TEMP,
-	CHANNEL_MUXOFF,
-	CHANNEL_NONE,
-	ADC_MPP_1_ATEST_8 = 20,
-	ADC_MPP_1_USB_SNS_DIV20,
-	ADC_MPP_1_DCIN_SNS_DIV20,
-	ADC_MPP_1_AMUX3,
-	ADC_MPP_1_AMUX4,
-	ADC_MPP_1_AMUX5,
-	ADC_MPP_1_AMUX6,
-	ADC_MPP_1_AMUX7,
-	ADC_MPP_1_AMUX8,
-	ADC_MPP_1_ATEST_1,
-	ADC_MPP_1_ATEST_2,
-	ADC_MPP_1_ATEST_3,
-	ADC_MPP_1_ATEST_4,
-	ADC_MPP_1_ATEST_5,
-	ADC_MPP_1_ATEST_6,
-	ADC_MPP_1_ATEST_7,
-	ADC_MPP_1_CHANNEL_NONE,
-	ADC_MPP_2_ATEST_8 = 40,
-	ADC_MPP_2_USB_SNS_DIV20,
-	ADC_MPP_2_DCIN_SNS_DIV20,
-	ADC_MPP_2_AMUX3,
-	ADC_MPP_2_AMUX4,
-	ADC_MPP_2_AMUX5,
-	ADC_MPP_2_AMUX6,
-	ADC_MPP_2_AMUX7,
-	ADC_MPP_2_AMUX8,
-	ADC_MPP_2_ATEST_1,
-	ADC_MPP_2_ATEST_2,
-	ADC_MPP_2_ATEST_3,
-	ADC_MPP_2_ATEST_4,
-	ADC_MPP_2_ATEST_5,
-	ADC_MPP_2_ATEST_6,
-	ADC_MPP_2_ATEST_7,
-	ADC_MPP_2_CHANNEL_NONE,
-};
-
-#define PM8921_ADC_PMIC_0	0x0
-
-#define PM8921_CHANNEL_ADC_625_MV	625
-#define PM8921_CHANNEL_MPP_SCALE1_IDX	20
-#define PM8921_CHANNEL_MPP_SCALE3_IDX	40
-
-#define PM8921_AMUX_MPP_3	0x3
-#define PM8921_AMUX_MPP_4	0x4
-#define PM8921_AMUX_MPP_5	0x5
-#define PM8921_AMUX_MPP_6	0x6
-#define PM8921_AMUX_MPP_7	0x7
-#define PM8921_AMUX_MPP_8	0x8
-
-#define PM8921_ADC_DEV_NAME	"pm8921-adc"
-
-/**
- * enum pm8921_adc_decimation_type - Sampling rate supported
- * %ADC_DECIMATION_TYPE1: 512
- * %ADC_DECIMATION_TYPE2: 1K
- * %ADC_DECIMATION_TYPE3: 2K
- * %ADC_DECIMATION_TYPE4: 4k
- * %ADC_DECIMATION_NONE: Do not use this Sampling type
- *
- * The Sampling rate is specific to each channel of the PM8921 ADC arbiter.
- */
-enum pm8921_adc_decimation_type {
-	ADC_DECIMATION_TYPE1 = 0,
-	ADC_DECIMATION_TYPE2,
-	ADC_DECIMATION_TYPE3,
-	ADC_DECIMATION_TYPE4,
-	ADC_DECIMATION_NONE,
-};
-
-/**
- * enum pm8921_adc_calib_type - PM8921 ADC Calibration type
- * %ADC_CALIB_ABSOLUTE: Use 625mV and 1.25V reference channels
- * %ADC_CALIB_RATIOMETRIC: Use reference Voltage/GND
- * %ADC_CALIB_CONFIG_NONE: Do not use this calibration type
- *
- * Use the input reference voltage depending on the calibration type
- * to calcluate the offset and gain parameters. The calibration is
- * specific to each channel of the PM8921 ADC.
- */
-enum pm8921_adc_calib_type {
-	ADC_CALIB_ABSOLUTE = 0,
-	ADC_CALIB_RATIOMETRIC,
-	ADC_CALIB_NONE,
-};
-
-/**
- * enum pm8921_adc_channel_scaling_param - pre-scaling AMUX ratio
- * %CHAN_PATH_SCALING1: ratio of {1, 1}
- * %CHAN_PATH_SCALING2: ratio of {1, 3}
- * %CHAN_PATH_SCALING3: ratio of {1, 4}
- * %CHAN_PATH_SCALING4: ratio of {1, 6}
- * %CHAN_PATH_NONE: Do not use this pre-scaling ratio type
- *
- * The pre-scaling is applied for signals to be within the voltage range
- * of the ADC.
- */
-enum pm8921_adc_channel_scaling_param {
-	CHAN_PATH_SCALING1 = 0,
-	CHAN_PATH_SCALING2,
-	CHAN_PATH_SCALING3,
-	CHAN_PATH_SCALING4,
-	CHAN_PATH_SCALING_NONE,
-};
-
-/**
- * enum pm8921_adc_amux_input_rsv - HK/XOADC reference voltage
- * %AMUX_RSV0: XO_IN/XOADC_GND
- * %AMUX_RSV1: PMIC_IN/XOADC_GND
- * %AMUX_RSV2: PMIC_IN/BMS_CSP
- * %AMUX_RSV3: not used
- * %AMUX_RSV4: XOADC_GND/XOADC_GND
- * %AMUX_RSV5: XOADC_VREF/XOADC_GND
- * %AMUX_NONE: Do not use this input reference voltage selection
- */
-enum pm8921_adc_amux_input_rsv {
-	AMUX_RSV0 = 0,
-	AMUX_RSV1,
-	AMUX_RSV2,
-	AMUX_RSV3,
-	AMUX_RSV4,
-	AMUX_RSV5,
-	AMUX_NONE,
-};
-
-/**
- * enum pm8921_adc_premux_mpp_scale_type - 16:1 pre-mux scale ratio
- * %PREMUX_MPP_SCALE_0: No scaling to the input signal
- * %PREMUX_MPP_SCALE_1: Unity scaling selected by the user for MPP input
- * %PREMUX_MPP_SCALE_1_DIV3: 1/3 pre-scale to the input MPP signal
- * %PREMUX_MPP_NONE: Do not use this pre-scale mpp type
- */
-enum pm8921_adc_premux_mpp_scale_type {
-	PREMUX_MPP_SCALE_0 = 0,
-	PREMUX_MPP_SCALE_1,
-	PREMUX_MPP_SCALE_1_DIV3,
-	PREMUX_MPP_NONE,
-};
-
-/**
- * enum pm8921_adc_scale_fn_type - Scaling function for pm8921 pre calibrated
- *				   digital data relative to ADC reference
- * %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage
- * %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters
- * %ADC_SCALE_PMIC_THERM: Returns result in milli degree's Centigrade
- * %ADC_SCALE_XTERN_CHGR_CUR: Returns current across 0.1 ohm resistor
- * %ADC_SCALE_XOTHERM: Returns XO thermistor voltage in degree's Centigrade
- * %ADC_SCALE_NONE: Do not use this scaling type
- */
-enum pm8921_adc_scale_fn_type {
-	ADC_SCALE_DEFAULT = 0,
-	ADC_SCALE_BATT_THERM,
-	ADC_SCALE_PA_THERM,
-	ADC_SCALE_PMIC_THERM,
-	ADC_SCALE_XOTHERM,
-	ADC_SCALE_NONE,
-};
-
-/**
- * struct pm8921_adc_linear_graph - Represent ADC characteristics
- * @offset: Offset with respect to the actual curve
- * @dy: Numerator slope to calculate the gain
- * @dx: Denominator slope to calculate the gain
- * @adc_vref: A/D word of the Voltage reference used for the channel
- * @adc_gnd: A/D word of the Ground reference used for the channel
- *
- * Each ADC device has different offset and gain parameters which are computed
- * to calibrate the device.
- */
-struct pm8921_adc_linear_graph {
-	int32_t offset;
-	int32_t dy;
-	int32_t dx;
-	int32_t adc_vref;
-	int32_t adc_gnd;
-};
-
-/**
- * struct pm8921_adc_map_pt - Map the graph representation for ADC channel
- * @x: Represent the ADC digitized code
- * @y: Represent the physical data which can be temperature, voltage,
- *     resistance
- */
-struct pm8921_adc_map_pt {
-	int32_t x;
-	int32_t y;
-};
-
-/**
- * struct pm8921_adc_scaling_ratio - Represent scaling ratio for adc input
- * @num: Numerator scaling parameter
- * @den: Denominator scaling parameter
- */
-struct pm8921_adc_scaling_ratio {
-	int32_t num;
-	int32_t den;
-};
-
-/**
- * struct pm8921_adc_properties - Represent the ADC properties
- * @adc_reference: Reference voltage for PM8921 ADC
- * @bitresolution: ADC bit resolution for PM8921 ADC
- * @biploar: Polarity for PM8921 ADC
- */
-struct pm8921_adc_properties {
-	uint32_t	adc_vdd_reference;
-	uint32_t	bitresolution;
-	bool		bipolar;
-};
-
-/**
- * struct pm8921_adc_chan_properties - Represent channel properties of the ADC
- * @offset_gain_numerator: The inverse numerator of the gain applied to the
- *			   input channel
- * @offset_gain_denominator: The inverse denominator of the gain applied to the
- *			     input channel
- * @adc_graph: ADC graph for the channel of struct type pm8921_adc_linear_graph
- */
-struct pm8921_adc_chan_properties {
-	uint32_t			offset_gain_numerator;
-	uint32_t			offset_gain_denominator;
-	struct pm8921_adc_linear_graph	adc_graph[2];
-};
-
-/**
- * struct pm8921_adc_chan_result - Represent the result of the PM8921 ADC
- * @chan: The channel number of the requested conversion
- * @adc_code: The pre-calibrated digital output of a given ADC relative to the
- *	      the ADC reference
- * @measurement: In units specific for a given ADC; most ADC uses reference
- *		 voltage but some ADC uses reference current. This measurement
- *		 here is a number relative to a reference of a given ADC
- * @physical: The data meaningful for each individual channel whether it is
- *	      voltage, current, temperature, etc.
- */
-struct pm8921_adc_chan_result {
-	uint32_t	chan;
-	int32_t		adc_code;
-	int64_t		measurement;
-	int64_t		physical;
-};
-
-#if defined(CONFIG_SENSORS_PM8921_ADC)					\
-			|| defined(CONFIG_SENSORS_PM8921_ADC_MODULE)
-/**
- * pm8921_adc_scale_default() - Scales the pre-calibrated digital output
- *		of an ADC to the ADC reference and compensates for the
- *		gain and offset.
- * @adc_code:	pre-calibrated digital ouput of the ADC.
- * @adc_prop:	adc properties of the pm8921 adc such as bit resolution,
- *		reference voltage.
- * @chan_prop:	individual channel properties to compensate the i/p scaling,
- *		slope and offset.
- * @chan_rslt:	Physical result to be stored.
- */
-int32_t pm8921_adc_scale_default(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt);
-/**
- * pm8921_adc_scale_tdkntcg_therm() - Scales the pre-calibrated digital output
- *		of an ADC to the ADC reference and compensates for the
- *		gain and offset. Returns the temperature of the xo therm in mili
-		degC.
- * @adc_code:	pre-calibrated digital ouput of the ADC.
- * @adc_prop:	adc properties of the pm8921 adc such as bit resolution,
- *		reference voltage.
- * @chan_prop:	individual channel properties to compensate the i/p scaling,
- *		slope and offset.
- * @chan_rslt:	physical result to be stored.
- */
-int32_t pm8921_adc_tdkntcg_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt);
-/**
- * pm8921_adc_scale_batt_therm() - Scales the pre-calibrated digital output
- *		of an ADC to the ADC reference and compensates for the
- *		gain and offset. Returns the temperature in degC.
- * @adc_code:	pre-calibrated digital ouput of the ADC.
- * @adc_prop:	adc properties of the pm8921 adc such as bit resolution,
- *		reference voltage.
- * @chan_prop:	individual channel properties to compensate the i/p scaling,
- *		slope and offset.
- * @chan_rslt:	physical result to be stored.
- */
-int32_t pm8921_adc_scale_batt_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt);
-/**
- * pm8921_adc_scale_pa_therm() - Scales the pre-calibrated digital output
- *		of an ADC to the ADC reference and compensates for the
- *		gain and offset. Returns the temperature in degC.
- * @adc_code:	pre-calibrated digital ouput of the ADC.
- * @adc_prop:	adc properties of the pm8921 adc such as bit resolution,
- *		reference voltage.
- * @chan_prop:	individual channel properties to compensate the i/p scaling,
- *		slope and offset.
- * @chan_rslt:	physical result to be stored.
- */
-int32_t pm8921_adc_scale_pa_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt);
-/**
- * pm8921_adc_scale_pmic_therm() - Scales the pre-calibrated digital output
- *		of an ADC to the ADC reference and compensates for the
- *		gain and offset. Performs the AMUX out as 2mv/K and returns
- *		the temperature in mili degC.
- * @adc_code:	pre-calibrated digital ouput of the ADC.
- * @adc_prop:	adc properties of the pm8921 adc such as bit resolution,
- *		reference voltage.
- * @chan_prop:	individual channel properties to compensate the i/p scaling,
- *		slope and offset.
- * @chan_rslt:	physical result to be stored.
- */
-int32_t pm8921_adc_scale_pmic_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt);
-#else
-static inline int32_t pm8921_adc_scale_default(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt)
-{ return -ENXIO; }
-static inline int32_t pm8921_adc_tdkntcg_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt)
-{ return -ENXIO; }
-static inline int32_t pm8921_adc_scale_batt_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt)
-{ return -ENXIO; }
-static inline int32_t pm8921_adc_scale_pa_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt)
-{ return -ENXIO; }
-static inline int32_t pm8921_adc_scale_pmic_therm(int32_t adc_code,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop,
-			struct pm8921_adc_chan_result *chan_rslt)
-{ return -ENXIO; }
-#endif
-
-/**
- * struct pm8921_adc_scale_fn - Scaling function prototype
- * @chan: Function pointer to one of the scaling functions
- *	which takes the adc properties, channel properties,
- *	and returns the physical result
- */
-struct pm8921_adc_scale_fn {
-	int32_t (*chan) (int32_t,
-		const struct pm8921_adc_properties *,
-		const struct pm8921_adc_chan_properties *,
-		struct pm8921_adc_chan_result *);
-};
-
-/**
- * struct pm8921_adc_amux - AMUX properties for individual channel
- * @name: Channel name
- * @channel_name: Channel in integer used from pm8921_adc_channels
- * @chan_path_prescaling: Channel scaling performed on the input signal
- * @adc_rsv: Input reference Voltage/GND selection to the ADC
- * @adc_decimation: Sampling rate desired for the channel
- * adc_scale_fn: Scaling function to convert to the data meaningful for
- *		 each individual channel whether it is voltage, current,
- *		 temperature, etc and compensates the channel properties
- */
-struct pm8921_adc_amux {
-	char					*name;
-	enum pm8921_adc_channels		channel_name;
-	enum pm8921_adc_channel_scaling_param	chan_path_prescaling;
-	enum pm8921_adc_amux_input_rsv		adc_rsv;
-	enum pm8921_adc_decimation_type		adc_decimation;
-	enum pm8921_adc_scale_fn_type		adc_scale_fn;
-};
-
-/**
- * struct pm8921_adc_arb_btm_param - PM8921 ADC BTM parameters to set threshold
- *				     temperature for client notification
- * @low_thr_temp: low temperature threshold request for notification
- * @high_thr_temp: high temperature threshold request for notification
- * @low_thr_voltage: low temperature converted to voltage by arbiter driver
- * @high_thr_voltage: high temperature converted to voltage by arbiter driver
- * @interval: Interval period to check for temperature notification
- * @btm_warm_fn: Remote function call for warm threshold.
- * @btm_cool_fn: Remote function call for cold threshold.
- *
- * BTM client passes the parameters to be set for the
- * temperature threshold notifications. The client is
- * responsible for setting the new threshold
- * levels once the thresholds are reached
- */
-struct pm8921_adc_arb_btm_param {
-	int32_t		low_thr_temp;
-	int32_t		high_thr_temp;
-	uint64_t	low_thr_voltage;
-	uint64_t	high_thr_voltage;
-	int32_t		interval;
-	void		(*btm_warm_fn) (bool);
-	void		(*btm_cool_fn) (bool);
-};
-
-int32_t pm8921_adc_batt_scaler(struct pm8921_adc_arb_btm_param *,
-			const struct pm8921_adc_properties *adc_prop,
-			const struct pm8921_adc_chan_properties *chan_prop);
-/**
- * struct pm8921_adc_platform_data - PM8921 ADC platform data
- * @adc_prop: ADC specific parameters, voltage and channel setup
- * @adc_channel: Channel properties of the ADC arbiter
- * @adc_num_board_channel: Number of channels added in the board file
- * @adc_mpp_base: PM8921 MPP0 base passed from board file. This is used
- *		  to offset the PM8921 MPP passed to configure the
- *		  the MPP to AMUX mapping.
- */
-struct pm8921_adc_platform_data {
-	struct pm8921_adc_properties	*adc_prop;
-	struct pm8921_adc_amux		*adc_channel;
-	uint32_t			adc_num_board_channel;
-	uint32_t			adc_mpp_base;
-};
-
-/* Public API */
-#if defined(CONFIG_SENSORS_PM8921_ADC)				\
-			|| defined(CONFIG_SENSORS_PM8921_ADC_MODULE)
-/**
- * pm8921_adc_read() - Performs ADC read on the channel.
- * @channel:	Input channel to perform the ADC read.
- * @result:	Structure pointer of type adc_chan_result
- *		in which the ADC read results are stored.
- */
-uint32_t pm8921_adc_read(enum pm8921_adc_channels channel,
-				struct pm8921_adc_chan_result *result);
-/**
- * pm8921_adc_mpp_config_read() - Configure's the PM8921 MPP
- *		to AMUX6 and performs an ADC read.
- * @mpp_num	PM8921 MPP number to configure to AMUX6.
- * @channel:	Input channel to perform the ADC read.
- *		a) 'ADC_MPP_1_AMUX6' if the input voltage is less than 1.8V
- *		b) 'ADC_MPP_2_AMUX6' if the input voltage is greater then 1.8V
- *		the input voltage is pre-divided by 3 and passed to the ADC.
- *		The appropriate scaling function needs to be selected to let
- *		the driver know a post scaling is required before returning
- *		the result.
- * @result:	Structure pointer of type adc_chan_result
- *		in which the ADC read results are stored.
- */
-uint32_t pm8921_adc_mpp_config_read(uint32_t mpp_num,
-				enum pm8921_adc_channels channel,
-				struct pm8921_adc_chan_result *result);
-/**
- * pm8921_adc_btm_start() - Configure the BTM registers and start
-			monitoring the BATT_THERM channel for
-			threshold warm/cold temperature set
-			by the Battery client. The btm_start
-			api is to be used after calling the
-			pm8921_btm_configure() api which sets
-			the temperature thresholds, interval
-			and functions to call when warm/cold
-			events are triggered.
- * @param:	none.
- */
-uint32_t pm8921_adc_btm_start(void);
-
-/**
- * pm8921_adc_btm_end() - Configures the BTM registers to stop
- *			monitoring the BATT_THERM channel for
- *			warm/cold events and disables the
- *			interval timer.
- * @param:	none.
- */
-uint32_t pm8921_adc_btm_end(void);
-
-/**
- * pm8921_adc_btm_configure() - Configures the BATT_THERM channel
- *			parameters for warm/cold thresholds.
- *			Sets the interval timer for perfoming
- *			reading the temperature done by the HW.
- * @btm_param:		Structure pointer of type adc_arb_btm_param *
- *			which client provides for threshold warm/cold,
- *			interval and functions to call when warm/cold
- *			events are triggered.
- */
-uint32_t pm8921_adc_btm_configure(struct pm8921_adc_arb_btm_param *);
-#else
-static inline uint32_t pm8921_adc_read(uint32_t channel,
-				struct pm8921_adc_chan_result *result)
-{ return -ENXIO; }
-static inline uint32_t pm8921_adc_mpp_config_read(uint32_t mpp_num,
-				enum pm8921_adc_channels channel,
-				struct pm8921_adc_chan_result *result)
-{ return -ENXIO; }
-static inline uint32_t pm8921_adc_btm_start(void)
-{ return -ENXIO; }
-static inline uint32_t pm8921_adc_btm_end(void)
-{ return -ENXIO; }
-static inline uint32_t pm8921_adc_btm_configure(
-		struct pm8921_adc_arb_btm_param *param)
-{ return -ENXIO; }
-#endif
-
-#endif /* PM8921_ADC_H */
diff --git a/include/linux/mfd/pm8xxx/pm8921.h b/include/linux/mfd/pm8xxx/pm8921.h
index 2c931b6..d4cdc3c 100644
--- a/include/linux/mfd/pm8xxx/pm8921.h
+++ b/include/linux/mfd/pm8xxx/pm8921.h
@@ -31,7 +31,7 @@
 #include <linux/input/pmic8xxx-keypad.h>
 #include <linux/regulator/pm8921-regulator.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
-#include <linux/mfd/pm8xxx/pm8921-adc.h>
+#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
 #include <linux/mfd/pm8xxx/pm8921-bms.h>
 #include <linux/leds-pm8xxx.h>
 #include <linux/mfd/pm8xxx/vibrator.h>
@@ -126,7 +126,7 @@
 	struct pm8xxx_misc_platform_data	*misc_pdata;
 	struct pm8921_regulator_platform_data	*regulator_pdatas;
 	int					num_regulators;
-	struct pm8921_adc_platform_data		*adc_pdata;
+	struct pm8xxx_adc_platform_data		*adc_pdata;
 	struct pm8xxx_led_platform_data		*leds_pdata;
 	struct pm8xxx_vibrator_platform_data	*vibrator_pdata;
 	struct pm8xxx_ccadc_platform_data	*ccadc_pdata;
diff --git a/include/linux/mfd/pm8xxx/tm.h b/include/linux/mfd/pm8xxx/tm.h
index 5eeefd9..6974754 100644
--- a/include/linux/mfd/pm8xxx/tm.h
+++ b/include/linux/mfd/pm8xxx/tm.h
@@ -25,7 +25,7 @@
 enum pm8xxx_tm_adc_type {
 	PM8XXX_TM_ADC_NONE,	/* Estimates temp based on overload level. */
 	PM8XXX_TM_ADC_PM8058_ADC,
-	PM8XXX_TM_ADC_PM8921_ADC,
+	PM8XXX_TM_ADC_PM8XXX_ADC,
 };
 
 struct pm8xxx_tm_core_data {
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
old mode 100755
new mode 100644
diff --git a/include/linux/msm_audio_sbc.h b/include/linux/msm_audio_sbc.h
index 0a7602a..c1de751 100644
--- a/include/linux/msm_audio_sbc.h
+++ b/include/linux/msm_audio_sbc.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
 #ifndef __MSM_AUDIO_SBC_H
 #define __MSM_AUDIO_SBC_H
 
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 273850f..1f898b0 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -25,6 +25,14 @@
 #define KGSL_FLAGS_RESERVED2   0x00000080
 #define KGSL_FLAGS_SOFT_RESET  0x00000100
 
+/* Clock flags to show which clocks should be controled by a given platform */
+#define KGSL_CLK_SRC	0x00000001
+#define KGSL_CLK_CORE	0x00000002
+#define KGSL_CLK_IFACE	0x00000004
+#define KGSL_CLK_MEM	0x00000008
+#define KGSL_CLK_MEM_IFACE 0x00000010
+#define KGSL_CLK_AXI	0x00000020
+
 #define KGSL_MAX_PWRLEVELS 5
 
 #define KGSL_CONVERT_TO_MBPS(val) \
@@ -130,30 +138,15 @@
 #define KGSL_2D1_REG_MEMORY	"kgsl_2d1_reg_memory"
 #define KGSL_2D1_IRQ		"kgsl_2d1_irq"
 
-struct kgsl_grp_clk_name {
-	const char *clk;
-	const char *pclk;
-};
-
-struct kgsl_device_pwr_data {
+struct kgsl_device_platform_data {
 	struct kgsl_pwrlevel pwrlevel[KGSL_MAX_PWRLEVELS];
 	int init_level;
 	int num_levels;
 	int (*set_grp_async)(void);
 	unsigned int idle_timeout;
 	unsigned int nap_allowed;
-};
-
-struct kgsl_clk_data {
-	struct kgsl_grp_clk_name name;
+	unsigned int clk_map;
 	struct msm_bus_scale_pdata *bus_scale_table;
-};
-
-struct kgsl_device_platform_data {
-	struct kgsl_device_pwr_data pwr_data;
-	struct kgsl_clk_data clk;
-	/* imem_clk_name is for 3d only, not used in 2d devices */
-	struct kgsl_grp_clk_name imem_clk_name;
 	const char *iommu_user_ctx_name;
 	const char *iommu_priv_ctx_name;
 };
diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h
old mode 100755
new mode 100644
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index d9687ba..dbdb651 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -727,13 +727,19 @@
 #define RSB_CALIB_SIZE    4
 #define CALIB_DATA_OFSET  2
 #define CALIB_MODE_OFSET  1
-
 #define MAX_CALIB_SIZE 75
-struct hci_fm_set_cal_req {
+struct hci_fm_set_cal_req_proc {
 	__u8    mode;
-	/*Max calibration data size*/
-	__u8    data[MAX_CALIB_SIZE];
+	/*Max process calibration data size*/
+	__u8    data[PROCS_CALIB_SIZE];
 } __packed;
+
+struct hci_fm_set_cal_req_dc {
+	__u8    mode;
+	/*Max DC calibration data size*/
+	__u8    data[DC_CALIB_SIZE];
+} __packed;
+
 struct hci_cc_do_calibration_rsp {
 	__u8 status;
 	__u8 mode;
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
index 53fea37..0a2849a 100644
--- a/include/net/bluetooth/amp.h
+++ b/include/net/bluetooth/amp.h
@@ -45,9 +45,6 @@
 	__le16     reason;
 } __packed;
 
-#define HCI_A2MP_ID(id)     ((id)+0x10)  /* convert HCI dev index to AMP ID */
-#define A2MP_HCI_ID(id)     ((id)-0x10)  /* convert AMP ID to HCI dev index */
-
 struct a2mp_discover_req {
 	__le16     mtu;
 	__le16     ext_feat;
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
new file mode 100644
index 0000000..2fd1604
--- /dev/null
+++ b/include/sound/compress_driver.h
@@ -0,0 +1,150 @@
+/*
+ *  compress_driver.h - compress offload driver definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_DRIVER_H
+#define __COMPRESS_DRIVER_H
+
+#include <sound/compress_offload.h>
+#include <sound/asound.h>
+#include <sound/pcm.h>
+
+struct snd_compr_ops;
+
+/**
+ * struct snd_compr_runtime: runtime stream description
+ * @state: stream state
+ * @ops: pointer to DSP callbacks
+ * @buffer: pointer to kernel buffer, valid only when not in mmap mode or
+ *	DSP doesn't implement copy
+ * @buffer_size: size of the above buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ * @hw_pointer: offset of last location in buffer where DSP copied data
+ * @app_pointer: offset of last location in buffer where app wrote data
+ * @sleep: poll sleep
+ */
+struct snd_compr_runtime {
+	snd_pcm_state_t state;
+	struct snd_compr_ops *ops;
+	void *buffer;
+	size_t buffer_size;
+	size_t fragment_size;
+	unsigned int fragments;
+	size_t hw_pointer;
+	size_t app_pointer;
+	wait_queue_head_t sleep;
+};
+
+/**
+ * struct snd_compr_stream: compressed stream
+ * @name: device name
+ * @ops: pointer to DSP callbacks
+ * @runtime: pointer to runtime structure
+ * @device: device pointer
+ * @direction: stream direction, playback/recording
+ * @private_data: pointer to DSP private data
+ */
+struct snd_compr_stream {
+	const char *name;
+	struct snd_compr_ops *ops;
+	struct snd_compr_runtime *runtime;
+	struct snd_compr *device;
+	unsigned int direction;
+	void *private_data;
+};
+
+/**
+ * struct snd_compr_ops: compressed path DSP operations
+ * @open: Open the compressed stream
+ * This callback is mandatory and shall keep dsp ready to receive the stream
+ * parameter
+ * @free: Close the compressed stream, mandatory
+ * @set_params: Sets the compressed stream parameters, mandatory
+ * This can be called in during stream creation only to set codec params
+ * and the stream properties
+ * @get_params: retrieve the codec parameters, mandatory
+ * @trigger: Trigger operations like start, pause, resume, drain, stop.
+ * This callback is mandatory
+ * @pointer: Retrieve current h/w pointer information. Mandatory
+ * @copy: Copy the compressed data to/from userspace, Optional
+ * Can't be implemented if DSP supports mmap
+ * @mmap: DSP mmap method to mmap DSP memory
+ * @ack: Ack for DSP when data is written to audio buffer, Optional
+ * Not valid if copy is implemented
+ * @get_caps: Retrieve DSP capabilities, mandatory
+ * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory
+ */
+struct snd_compr_ops {
+	int (*open)(struct snd_compr_stream *stream);
+	int (*free)(struct snd_compr_stream *stream);
+	int (*set_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*get_params)(struct snd_compr_stream *stream,
+			struct snd_compr_params *params);
+	int (*trigger)(struct snd_compr_stream *stream, int cmd);
+	int (*pointer)(struct snd_compr_stream *stream,
+			struct snd_compr_tstamp *tstamp);
+	int (*copy)(struct snd_compr_stream *stream, const char __user *buf,
+		       size_t count);
+	int (*mmap)(struct snd_compr_stream *stream,
+			struct vm_area_struct *vma);
+	int (*ack)(struct snd_compr_stream *stream);
+	int (*get_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_caps *caps);
+	int (*get_codec_caps) (struct snd_compr_stream *stream,
+			struct snd_compr_codec_caps *codec);
+};
+
+/**
+ * struct snd_compr: Compressed device
+ * @name: DSP device name
+ * @dev: Device pointer
+ * @lock: device lock
+ * @ops: pointer to DSP callbacks
+ * @private_data: pointer to DSP pvt data
+ */
+struct snd_compr {
+	const char *name;
+	struct device *dev;
+	struct mutex lock;
+	struct snd_compr_ops *ops;
+	struct list_head list;
+	void *private_data;
+};
+
+/* compress device register APIs */
+int snd_compress_register(struct snd_compr *device);
+int snd_compress_deregister(struct snd_compr *device);
+
+/* dsp driver callback apis
+ * For playback: driver should call snd_compress_fragment_elapsed() to let the
+ * framework know that a fragment has been consumed from the ring buffer
+ * For recording: we may want to know when a frame is available or when
+ * at least one frame is available for userspace, a different
+ * snd_compress_frame_elapsed() callback should be used
+ */
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream);
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream);
+
+#endif
diff --git a/include/sound/compress_offload.h b/include/sound/compress_offload.h
new file mode 100644
index 0000000..423264d
--- /dev/null
+++ b/include/sound/compress_offload.h
@@ -0,0 +1,137 @@
+/*
+ *  compress_offload.h - compress offload header definations
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#ifndef __COMPRESS_OFFLOAD_H
+#define __COMPRESS_OFFLOAD_H
+
+#include <linux/types.h>
+/**
+ * struct snd_compressed_buffer:compressed buffer
+ * @fragment_size: size of buffer fragment in bytes
+ * @fragments: number of such fragments
+ */
+struct snd_compressed_buffer {
+	size_t fragment_size;
+	int fragments;
+};
+
+/* */
+struct snd_compr_params {
+	struct snd_compressed_buffer buffer;
+	struct snd_codec codec;
+};
+
+/**
+ * struct snd_compr_tstamp: timestamp descriptor
+ * @copied_bytes: Number of bytes offset in ring buffer to DSP
+ * @copied_total: Total number of bytes copied from ring buffer to DSP
+ * @decoded: Frames decoded by DSP
+ * @rendered: Frames rendered by DSP into a mixer or an audio output
+ * @sampling_rate: sampling rate of audio
+ */
+struct snd_compr_tstamp {
+	size_t copied_bytes;
+	size_t copied_total;
+	size_t decoded;
+	size_t rendered;
+	__u32 sampling_rate;
+};
+
+/**
+ * struct snd_compr_avail: avail descriptor
+ * @avail: Number of bytes available in ring buffer for writing/reading
+ * @tstamp: timestamp infomation
+ */
+struct snd_compr_avail {
+	size_t avail;
+	struct snd_compr_tstamp tstamp;
+};
+
+/**
+ * struct snd_compr_caps: caps descriptor
+ * @codecs: pointer to array of codecs
+ * @min_fragment_size: minimum fragment supported by DSP
+ * @max_fragment_size: maximum fragment supported by DSP
+ * @min_fragments: min fragments supported by DSP
+ * @max_fragments: max fragments supported by DSP
+ * @num_codecs: number of codecs supported
+ * @reserved: reserved field
+ */
+struct snd_compr_caps {
+	__u32 num_codecs;
+	__u32 min_fragment_size;
+	__u32 max_fragment_size;
+	__u32 min_fragments;
+	__u32 max_fragments;
+	__u32 codecs[MAX_NUM_CODECS];
+	__u32 reserved[11];
+};
+
+/**
+ * struct snd_compr_codec_caps: query capability of codec
+ * @codec: codec for which capability is queried
+ * @num_descriptors: number of codec descriptors
+ * @descriptor: array of codec capability descriptor
+ */
+struct snd_compr_codec_caps {
+	__u32 codec;
+	__u32 num_descriptors;
+	struct snd_codec_desc descriptor[MAX_NUM_CODEC_DESCRIPTORS];
+};
+
+/**
+ * compress path ioctl definitions
+ * SNDRV_COMPRESS_GET_CAPS: Query capability of DSP
+ * SNDRV_COMPRESS_GET_CODEC_CAPS: Query capability of a codec
+ * SNDRV_COMPRESS_SET_PARAMS: Set codec and stream parameters
+ * Note: only codec params can be changed runtime and stream params cant be
+ * SNDRV_COMPRESS_GET_PARAMS: Query codec and stream params
+ * SNDRV_COMPRESS_TSTAMP: get the current timestamp value
+ * SNDRV_COMPRESS_AVAIL: get the current buffer avail value.
+ * This also queries the tstamp properties
+ * SNDRV_COMPRESS_PAUSE: Pause the running stream
+ * SNDRV_COMPRESS_RESUME: resume a paused stream
+ * SNDRV_COMPRESS_START: Start a stream
+ * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content
+ * and the buffers currently with DSP
+ * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that
+ */
+#define SNDRV_COMPRESS_GET_CAPS		_IOWR('C', 0x00, struct snd_compr_caps *)
+#define SNDRV_COMPRESS_GET_CODEC_CAPS	_IOWR('C', 0x01, struct snd_compr_codec_caps *)
+#define SNDRV_COMPRESS_SET_PARAMS	_IOW('C', 0x02, struct snd_compr_params *)
+#define SNDRV_COMPRESS_GET_PARAMS	_IOR('C', 0x03, struct snd_compr_params *)
+#define SNDRV_COMPRESS_TSTAMP		_IOR('C', 0x10, struct snd_compr_tstamp *)
+#define SNDRV_COMPRESS_AVAIL		_IOR('C', 0x11, struct snd_compr_avail *)
+#define SNDRV_COMPRESS_PAUSE		_IO('C', 0x20)
+#define SNDRV_COMPRESS_RESUME		_IO('C', 0x21)
+#define SNDRV_COMPRESS_START		_IO('C', 0x22)
+#define SNDRV_COMPRESS_STOP		_IO('C', 0x23)
+#define SNDRV_COMPRESS_DRAIN		_IO('C', 0x24)
+/*
+ * TODO
+ * 1. add mmap support
+ *
+ */
+#define SND_COMPR_TRIGGER_DRAIN 7 /*FIXME move this to pcm.h */
+#endif
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
new file mode 100644
index 0000000..5080e13
--- /dev/null
+++ b/include/sound/snd_compress_params.h
@@ -0,0 +1,392 @@
+/*
+ *  snd_compress_params.h - codec types and parameters for compressed data
+ *  streaming interface
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *              Vinod Koul <vinod.koul@linux.intel.com>
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The definitions in this file are derived from the OpenMAX AL version 1.1
+ * and OpenMAX IL v 1.1.2 header files which contain the copyright notice below.
+ *
+ * Copyright (c) 2007-2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and/or associated documentation files (the
+ * "Materials "), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+
+
+/* AUDIO CODECS SUPPORTED */
+#define MAX_NUM_CODECS 32
+#define MAX_NUM_CODEC_DESCRIPTORS 32
+#define MAX_NUM_BITRATES 32
+
+/* Codecs are listed linearly to allow for extensibility */
+#define SND_AUDIOCODEC_PCM                   ((__u32) 0x00000001)
+#define SND_AUDIOCODEC_MP3                   ((__u32) 0x00000002)
+#define SND_AUDIOCODEC_AMR                   ((__u32) 0x00000003)
+#define SND_AUDIOCODEC_AMRWB                 ((__u32) 0x00000004)
+#define SND_AUDIOCODEC_AMRWBPLUS             ((__u32) 0x00000005)
+#define SND_AUDIOCODEC_AAC                   ((__u32) 0x00000006)
+#define SND_AUDIOCODEC_WMA                   ((__u32) 0x00000007)
+#define SND_AUDIOCODEC_REAL                  ((__u32) 0x00000008)
+#define SND_AUDIOCODEC_VORBIS                ((__u32) 0x00000009)
+#define SND_AUDIOCODEC_FLAC                  ((__u32) 0x0000000A)
+#define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
+#define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
+#define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
+
+/*
+ * Profile and modes are listed with bit masks. This allows for a
+ * more compact representation of fields that will not evolve
+ * (in contrast to the list of codecs)
+ */
+
+#define SND_AUDIOPROFILE_PCM                 ((__u32) 0x00000001)
+
+/* MP3 modes are only useful for encoders */
+#define SND_AUDIOCHANMODE_MP3_MONO           ((__u32) 0x00000001)
+#define SND_AUDIOCHANMODE_MP3_STEREO         ((__u32) 0x00000002)
+#define SND_AUDIOCHANMODE_MP3_JOINTSTEREO    ((__u32) 0x00000004)
+#define SND_AUDIOCHANMODE_MP3_DUAL           ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_AMR                 ((__u32) 0x00000001)
+
+/* AMR modes are only useful for encoders */
+#define SND_AUDIOMODE_AMR_DTX_OFF            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMR_VAD1               ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMR_VAD2               ((__u32) 0x00000004)
+
+#define SND_AUDIOSTREAMFORMAT_UNDEFINED	     ((__u32) 0x00000000)
+#define SND_AUDIOSTREAMFORMAT_CONFORMANCE    ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_IF1            ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_IF2            ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_FSF            ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_RTPPAYLOAD     ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_ITU            ((__u32) 0x00000020)
+
+#define SND_AUDIOPROFILE_AMRWB               ((__u32) 0x00000001)
+
+/* AMRWB modes are only useful for encoders */
+#define SND_AUDIOMODE_AMRWB_DTX_OFF          ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AMRWB_VAD1             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AMRWB_VAD2             ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_AMRWBPLUS           ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_AAC                 ((__u32) 0x00000001)
+
+/* AAC modes are required for encoders and decoders */
+#define SND_AUDIOMODE_AAC_MAIN               ((__u32) 0x00000001)
+#define SND_AUDIOMODE_AAC_LC                 ((__u32) 0x00000002)
+#define SND_AUDIOMODE_AAC_SSR                ((__u32) 0x00000004)
+#define SND_AUDIOMODE_AAC_LTP                ((__u32) 0x00000008)
+#define SND_AUDIOMODE_AAC_HE                 ((__u32) 0x00000010)
+#define SND_AUDIOMODE_AAC_SCALABLE           ((__u32) 0x00000020)
+#define SND_AUDIOMODE_AAC_ERLC               ((__u32) 0x00000040)
+#define SND_AUDIOMODE_AAC_LD                 ((__u32) 0x00000080)
+#define SND_AUDIOMODE_AAC_HE_PS              ((__u32) 0x00000100)
+#define SND_AUDIOMODE_AAC_HE_MPS             ((__u32) 0x00000200)
+
+/* AAC formats are required for encoders and decoders */
+#define SND_AUDIOSTREAMFORMAT_MP2ADTS        ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_MP4ADTS        ((__u32) 0x00000002)
+#define SND_AUDIOSTREAMFORMAT_MP4LOAS        ((__u32) 0x00000004)
+#define SND_AUDIOSTREAMFORMAT_MP4LATM        ((__u32) 0x00000008)
+#define SND_AUDIOSTREAMFORMAT_ADIF           ((__u32) 0x00000010)
+#define SND_AUDIOSTREAMFORMAT_MP4FF          ((__u32) 0x00000020)
+#define SND_AUDIOSTREAMFORMAT_RAW            ((__u32) 0x00000040)
+
+#define SND_AUDIOPROFILE_WMA7                ((__u32) 0x00000001)
+#define SND_AUDIOPROFILE_WMA8                ((__u32) 0x00000002)
+#define SND_AUDIOPROFILE_WMA9                ((__u32) 0x00000004)
+#define SND_AUDIOPROFILE_WMA10               ((__u32) 0x00000008)
+
+#define SND_AUDIOMODE_WMA_LEVEL1             ((__u32) 0x00000001)
+#define SND_AUDIOMODE_WMA_LEVEL2             ((__u32) 0x00000002)
+#define SND_AUDIOMODE_WMA_LEVEL3             ((__u32) 0x00000004)
+#define SND_AUDIOMODE_WMA_LEVEL4             ((__u32) 0x00000008)
+#define SND_AUDIOMODE_WMAPRO_LEVELM0         ((__u32) 0x00000010)
+#define SND_AUDIOMODE_WMAPRO_LEVELM1         ((__u32) 0x00000020)
+#define SND_AUDIOMODE_WMAPRO_LEVELM2         ((__u32) 0x00000040)
+#define SND_AUDIOMODE_WMAPRO_LEVELM3         ((__u32) 0x00000080)
+
+#define SND_AUDIOSTREAMFORMAT_WMA_ASF        ((__u32) 0x00000001)
+/*
+ * Some implementations strip the ASF header and only send ASF packets
+ * to the DSP
+ */
+#define SND_AUDIOSTREAMFORMAT_WMA_NOASF_HDR  ((__u32) 0x00000002)
+
+#define SND_AUDIOPROFILE_REALAUDIO           ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_REALAUDIO_G2           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_REALAUDIO_8            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_REALAUDIO_10           ((__u32) 0x00000004)
+#define SND_AUDIOMODE_REALAUDIO_SURROUND     ((__u32) 0x00000008)
+
+#define SND_AUDIOPROFILE_VORBIS              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_VORBIS                 ((__u32) 0x00000001)
+
+#define SND_AUDIOPROFILE_FLAC                ((__u32) 0x00000001)
+
+/*
+ * Define quality levels for FLAC encoders, from LEVEL0 (fast)
+ * to LEVEL8 (best)
+ */
+#define SND_AUDIOMODE_FLAC_LEVEL0            ((__u32) 0x00000001)
+#define SND_AUDIOMODE_FLAC_LEVEL1            ((__u32) 0x00000002)
+#define SND_AUDIOMODE_FLAC_LEVEL2            ((__u32) 0x00000004)
+#define SND_AUDIOMODE_FLAC_LEVEL3            ((__u32) 0x00000008)
+#define SND_AUDIOMODE_FLAC_LEVEL4            ((__u32) 0x00000010)
+#define SND_AUDIOMODE_FLAC_LEVEL5            ((__u32) 0x00000020)
+#define SND_AUDIOMODE_FLAC_LEVEL6            ((__u32) 0x00000040)
+#define SND_AUDIOMODE_FLAC_LEVEL7            ((__u32) 0x00000080)
+#define SND_AUDIOMODE_FLAC_LEVEL8            ((__u32) 0x00000100)
+
+#define SND_AUDIOSTREAMFORMAT_FLAC           ((__u32) 0x00000001)
+#define SND_AUDIOSTREAMFORMAT_FLAC_OGG       ((__u32) 0x00000002)
+
+/* IEC61937 payloads without CUVP and preambles */
+#define SND_AUDIOPROFILE_IEC61937            ((__u32) 0x00000001)
+/* IEC61937 with S/PDIF preambles+CUVP bits in 32-bit containers */
+#define SND_AUDIOPROFILE_IEC61937_SPDIF      ((__u32) 0x00000002)
+
+/*
+ * IEC modes are mandatory for decoders. Format autodetection
+ * will only happen on the DSP side with mode 0. The PCM mode should
+ * not be used, the PCM codec should be used instead.
+ */
+#define SND_AUDIOMODE_IEC_REF_STREAM_HEADER  ((__u32) 0x00000000)
+#define SND_AUDIOMODE_IEC_LPCM		     ((__u32) 0x00000001)
+#define SND_AUDIOMODE_IEC_AC3		     ((__u32) 0x00000002)
+#define SND_AUDIOMODE_IEC_MPEG1		     ((__u32) 0x00000004)
+#define SND_AUDIOMODE_IEC_MP3		     ((__u32) 0x00000008)
+#define SND_AUDIOMODE_IEC_MPEG2		     ((__u32) 0x00000010)
+#define SND_AUDIOMODE_IEC_AACLC		     ((__u32) 0x00000020)
+#define SND_AUDIOMODE_IEC_DTS		     ((__u32) 0x00000040)
+#define SND_AUDIOMODE_IEC_ATRAC		     ((__u32) 0x00000080)
+#define SND_AUDIOMODE_IEC_SACD		     ((__u32) 0x00000100)
+#define SND_AUDIOMODE_IEC_EAC3		     ((__u32) 0x00000200)
+#define SND_AUDIOMODE_IEC_DTS_HD	     ((__u32) 0x00000400)
+#define SND_AUDIOMODE_IEC_MLP		     ((__u32) 0x00000800)
+#define SND_AUDIOMODE_IEC_DST		     ((__u32) 0x00001000)
+#define SND_AUDIOMODE_IEC_WMAPRO	     ((__u32) 0x00002000)
+#define SND_AUDIOMODE_IEC_REF_CXT            ((__u32) 0x00004000)
+#define SND_AUDIOMODE_IEC_HE_AAC	     ((__u32) 0x00008000)
+#define SND_AUDIOMODE_IEC_HE_AAC2	     ((__u32) 0x00010000)
+#define SND_AUDIOMODE_IEC_MPEG_SURROUND	     ((__u32) 0x00020000)
+
+#define SND_AUDIOPROFILE_G723_1              ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G723_1_ANNEX_A         ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G723_1_ANNEX_B         ((__u32) 0x00000002)
+#define SND_AUDIOMODE_G723_1_ANNEX_C         ((__u32) 0x00000004)
+
+#define SND_AUDIOPROFILE_G729                ((__u32) 0x00000001)
+
+#define SND_AUDIOMODE_G729_ANNEX_A           ((__u32) 0x00000001)
+#define SND_AUDIOMODE_G729_ANNEX_B           ((__u32) 0x00000002)
+
+/* <FIXME: multichannel encoders aren't supported for now. Would need
+   an additional definition of channel arrangement> */
+
+/* VBR/CBR definitions */
+#define SND_RATECONTROLMODE_CONSTANTBITRATE  ((__u32) 0x00000001)
+#define SND_RATECONTROLMODE_VARIABLEBITRATE  ((__u32) 0x00000002)
+
+/* Encoder options */
+
+struct snd_enc_wma {
+	__u32 super_block_align; /* WMA Type-specific data */
+};
+
+
+/**
+ * struct snd_enc_vorbis
+ * @quality: Sets encoding quality to n, between -1 (low) and 10 (high).
+ * In the default mode of operation, the quality level is 3.
+ * Normal quality range is 0 - 10.
+ * @managed: Boolean. Set  bitrate  management  mode. This turns off the
+ * normal VBR encoding, but allows hard or soft bitrate constraints to be
+ * enforced by the encoder. This mode can be slower, and may also be
+ * lower quality. It is primarily useful for streaming.
+ * @max_bit_rate: Enabled only if managed is TRUE
+ * @min_bit_rate: Enabled only if managed is TRUE
+ * @downmix: Boolean. Downmix input from stereo to mono (has no effect on
+ * non-stereo streams). Useful for lower-bitrate encoding.
+ *
+ * These options were extracted from the OpenMAX IL spec and Gstreamer vorbisenc
+ * properties
+ *
+ * For best quality users should specify VBR mode and set quality levels.
+ */
+
+struct snd_enc_vorbis {
+	int quality;
+	__u32 managed;
+	__u32 max_bit_rate;
+	__u32 min_bit_rate;
+	__u32 downmix;
+};
+
+
+/**
+ * struct snd_enc_real
+ * @quant_bits: number of coupling quantization bits in the stream
+ * @start_region: coupling start region in the stream
+ * @num_regions: number of regions value
+ *
+ * These options were extracted from the OpenMAX IL spec
+ */
+
+struct snd_enc_real {
+	__u32 quant_bits;
+	__u32 start_region;
+	__u32 num_regions;
+};
+
+/**
+ * struct snd_enc_flac
+ * @num: serial number, valid only for OGG formats
+ *	needs to be set by application
+ * @gain: Add replay gain tags
+ *
+ * These options were extracted from the FLAC online documentation
+ * at http://flac.sourceforge.net/documentation_tools_flac.html
+ *
+ * To make the API simpler, it is assumed that the user will select quality
+ * profiles. Additional options that affect encoding quality and speed can
+ * be added at a later stage if needed.
+ *
+ * By default the Subset format is used by encoders.
+ *
+ * TAGS such as pictures, etc, cannot be handled by an offloaded encoder and are
+ * not supported in this API.
+ */
+
+struct snd_enc_flac {
+	__u32 num;
+	__u32 gain;
+};
+
+struct snd_enc_generic {
+	__u32 bw;	/* encoder bandwidth */
+	int reserved[15];
+};
+
+union snd_codec_options {
+	struct snd_enc_wma wma;
+	struct snd_enc_vorbis vorbis;
+	struct snd_enc_real real;
+	struct snd_enc_flac flac;
+	struct snd_enc_generic generic;
+};
+
+/** struct snd_codec_desc - description of codec capabilities
+ * @max_ch: Maximum number of audio channels
+ * @sample_rates: Sampling rates in Hz, use SNDRV_PCM_RATE_xxx for this
+ * @bit_rate: Indexed array containing supported bit rates
+ * @num_bitrates: Number of valid values in bit_rate array
+ * @rate_control: value is specified by SND_RATECONTROLMODE defines.
+ * @profiles: Supported profiles. See SND_AUDIOPROFILE defines.
+ * @modes: Supported modes. See SND_AUDIOMODE defines
+ * @formats: Supported formats. See SND_AUDIOSTREAMFORMAT defines
+ * @reserved: reserved for future use
+ *
+ * This structure provides a scalar value for profiles, modes and stream
+ * format fields.
+ * If an implementation supports multiple combinations, they will be listed as
+ * codecs with different descriptors, for example there would be 2 descriptors
+ * for AAC-RAW and AAC-ADTS.
+ * This entails some redundancy but makes it easier to avoid invalid
+ * configurations.
+ *
+ */
+
+struct snd_codec_desc {
+	__u32 max_ch;
+	__u32 sample_rates;
+	__u32 bit_rate[MAX_NUM_BITRATES];
+	__u32 num_bitrates;
+	__u32 rate_control;
+	__u32 profiles;
+	__u32 modes;
+	__u32 formats;
+	__u32 reserved[16];
+};
+
+/** struct snd_codec
+ * @id: Identifies the supported audio encoder/decoder.
+ *		See SND_AUDIOCODEC macros.
+ * @ch_in: Number of input audio channels
+ * @ch_out: Number of output channels. In case of contradiction between
+ *		this field and the channelMode field, the channelMode field
+ *		overrides.
+ * @sample_rate: Audio sample rate of input data
+ * @bit_rate: Bitrate of encoded data. May be ignored by decoders
+ * @rate_control: Encoding rate control. See SND_RATECONTROLMODE defines.
+ *               Encoders may rely on profiles for quality levels.
+ *		 May be ignored by decoders.
+ * @profile: Mandatory for encoders, can be mandatory for specific
+ *		decoders as well. See SND_AUDIOPROFILE defines.
+ * @level: Supported level (Only used by WMA at the moment)
+ * @ch_mode: Channel mode for encoder. See SND_AUDIOCHANMODE defines
+ * @format: Format of encoded bistream. Mandatory when defined.
+ *		See SND_AUDIOSTREAMFORMAT defines.
+ * @align: Block alignment in bytes of an audio sample.
+ *		Only required for PCM or IEC formats.
+ * @options: encoder-specific settings
+ * @reserved: reserved for future use
+ */
+
+struct snd_codec {
+	__u32 id;
+	__u32 ch_in;
+	__u32 ch_out;
+	__u32 sample_rate;
+	__u32 bit_rate;
+	__u32 rate_control;
+	__u32 profile;
+	__u32 level;
+	__u32 ch_mode;
+	__u32 format;
+	__u32 align;
+	union snd_codec_options options;
+	__u32 reserved[3];
+};
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index a9205e3..2043c08 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -885,10 +885,13 @@
 			     struct hrtimer_clock_base *base,
 			     unsigned long newstate, int reprogram)
 {
+	struct timerqueue_node *next_timer;
 	if (!(timer->state & HRTIMER_STATE_ENQUEUED))
 		goto out;
 
-	if (&timer->node == timerqueue_getnext(&base->active)) {
+	next_timer = timerqueue_getnext(&base->active);
+	timerqueue_del(&base->active, &timer->node);
+	if (&timer->node == next_timer) {
 #ifdef CONFIG_HIGH_RES_TIMERS
 		/* Reprogram the clock event device. if enabled */
 		if (reprogram && hrtimer_hres_active()) {
@@ -901,7 +904,6 @@
 		}
 #endif
 	}
-	timerqueue_del(&base->active, &timer->node);
 	if (!timerqueue_getnext(&base->active))
 		base->cpu_base->active_bases &= ~(1 << base->index);
 out:
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 8487c49..709dc6d 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -753,7 +753,8 @@
 hotremove_migrate_alloc(struct page *page, unsigned long private, int **x)
 {
 	/* This should be improooooved!! */
-	return alloc_page(GFP_HIGHUSER_MOVABLE);
+	return alloc_page(GFP_HIGHUSER_MOVABLE | __GFP_NORETRY | __GFP_NOWARN |
+				__GFP_NOMEMALLOC);
 }
 
 #define NR_OFFLINE_AT_ONCE_PAGES	(256)
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index af8ee26..4918caa 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -255,7 +255,7 @@
 		read_lock(&mgr->ctx_list_lock);
 		list_for_each_entry(ctx, &mgr->ctx_list, list) {
 			struct hci_dev *ctx_hdev;
-			ctx_hdev = hci_dev_get(A2MP_HCI_ID(ctx->id));
+			ctx_hdev = hci_dev_get(ctx->id);
 			if ((ctx_hdev == hdev) && (ctx->evt_type & evt_type)) {
 				switch (evt_type) {
 				case AMP_HCI_CMD_STATUS:
@@ -356,7 +356,7 @@
 		if (hdev) {
 			if ((hdev->amp_type != HCI_BREDR) &&
 			test_bit(HCI_UP, &hdev->flags)) {
-				(cl + num_ctrls)->id  = HCI_A2MP_ID(hdev->id);
+				(cl + num_ctrls)->id  = hdev->id;
 				(cl + num_ctrls)->type = hdev->amp_type;
 				(cl + num_ctrls)->status = hdev->amp_status;
 				++num_ctrls;
@@ -459,7 +459,7 @@
 	rsp.status = 1;
 
 	BT_DBG("id %d", id);
-	hdev = hci_dev_get(A2MP_HCI_ID(id));
+	hdev = hci_dev_get(id);
 
 	if (hdev && hdev->amp_type != HCI_BREDR) {
 		rsp.status = 0;
@@ -510,14 +510,14 @@
 	int result = -EINVAL;
 
 	BT_DBG("lcon %p", lcon);
+	hdev = hci_dev_get(id);
+	if (!hdev)
+		goto ap_finished;
+	BT_DBG("hdev %p", hdev);
 	mgr = get_create_amp_mgr(lcon, NULL);
 	if (!mgr)
 		goto ap_finished;
 	BT_DBG("mgr %p", mgr);
-	hdev = hci_dev_get(A2MP_HCI_ID(id));
-	if (!hdev)
-		goto ap_finished;
-	BT_DBG("hdev %p", hdev);
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
 					&mgr->l2cap_conn->hcon->dst);
 	if (conn) {
@@ -534,6 +534,8 @@
 	return;
 
 ap_finished:
+	if (hdev)
+		hci_dev_put(hdev);
 	l2cap_amp_physical_complete(result, id, remote_id, sk);
 }
 
@@ -553,7 +555,7 @@
 		return -ENOMEM;
 	ctx->id = req->id;
 	ctx->d.gaa.req_ident = hdr->ident;
-	ctx->hdev = hci_dev_get(A2MP_HCI_ID(ctx->id));
+	ctx->hdev = hci_dev_get(ctx->id);
 	if (ctx->hdev)
 		ctx->d.gaa.assoc = kmalloc(ctx->hdev->amp_assoc_size,
 						GFP_ATOMIC);
@@ -826,7 +828,7 @@
 	ctx->d.apl.len_so_far = 0;
 	ctx->d.apl.rem_len = skb->len;
 	skb_pull(skb, skb->len);
-	ctx->hdev = hci_dev_get(A2MP_HCI_ID(ctx->id));
+	ctx->hdev = hci_dev_get(ctx->id);
 	start_ctx(mgr, ctx);
 	return 0;
 }
@@ -1122,7 +1124,7 @@
 				if (hdev) {
 					struct hci_conn *conn;
 					ctx->hdev = hdev;
-					ctx->id = HCI_A2MP_ID(hdev->id);
+					ctx->id = hdev->id;
 					ctx->d.cpl.remote_id = cl->id;
 					conn = hci_conn_hash_lookup_ba(hdev,
 					    ACL_LINK,
@@ -1425,7 +1427,7 @@
 	rsp.status = 0;
 	BT_DBG("local_id %d remote_id %d",
 		(int) rsp.local_id, (int) rsp.remote_id);
-	hdev = hci_dev_get(A2MP_HCI_ID(rsp.local_id));
+	hdev = hci_dev_get(rsp.local_id);
 	if (!hdev) {
 		rsp.status = 1; /* Invalid Controller ID */
 		goto dpl_finished;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index abc3ef7..d63dd1a 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3158,21 +3158,23 @@
 	struct hci_conn *hcon;
 	struct hci_chan *chan;
 
-	hdev = hci_dev_get(A2MP_HCI_ID(amp_id));
+	hdev = hci_dev_get(amp_id);
 	if (!hdev)
 		return NULL;
 
 	BT_DBG("hdev %s", hdev->name);
 
 	hcon = hci_conn_hash_lookup_ba(hdev, ACL_LINK, pi->conn->dst);
-	if (!hcon)
-		return NULL;
+	if (!hcon) {
+		chan = NULL;
+		goto done;
+	}
 
 	chan = hci_chan_list_lookup_id(hdev, hcon->handle);
 	if (chan) {
 		l2cap_aggregate(chan, pi);
 		hci_chan_hold(chan);
-		return chan;
+		goto done;
 	}
 
 	if (bt_sk(pi)->parent) {
@@ -3186,6 +3188,8 @@
 					(struct hci_ext_fs *) &pi->local_fs,
 					(struct hci_ext_fs *) &pi->remote_fs);
 	}
+done:
+	hci_dev_put(hdev);
 	return chan;
 }
 
@@ -3743,6 +3747,12 @@
 
 	BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
 
+	/* Initialize rfc in case no rfc option is received */
+	rfc.mode = pi->mode;
+	rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+	rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+	rfc.max_pdu_size = L2CAP_DEFAULT_MAX_PDU_SIZE;
+
 	while (len >= L2CAP_CONF_OPT_SIZE) {
 		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
 
@@ -3837,6 +3847,12 @@
 
 	BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
 
+	/* Initialize rfc in case no rfc option is received */
+	rfc.mode = pi->mode;
+	rfc.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+	rfc.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+	rfc.max_pdu_size = L2CAP_DEFAULT_MAX_PDU_SIZE;
+
 	if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
 		return;
 
@@ -4727,7 +4743,7 @@
 		struct hci_dev *hdev;
 
 		/* Validate AMP controller id */
-		hdev = hci_dev_get(A2MP_HCI_ID(req->amp_id));
+		hdev = hci_dev_get(req->amp_id);
 		if (!hdev || !test_bit(HCI_UP, &hdev->flags)) {
 			struct l2cap_create_chan_rsp rsp;
 
@@ -4805,7 +4821,7 @@
 
 	if (req->dest_amp_id) {
 		struct hci_dev *hdev;
-		hdev = hci_dev_get(A2MP_HCI_ID(req->dest_amp_id));
+		hdev = hci_dev_get(req->dest_amp_id);
 		if (!hdev || !test_bit(HCI_UP, &hdev->flags)) {
 			if (hdev)
 				hci_dev_put(hdev);
@@ -4813,6 +4829,7 @@
 			result = L2CAP_MOVE_CHAN_REFUSED_CONTROLLER;
 			goto send_move_response;
 		}
+		hci_dev_put(hdev);
 	}
 
 	if (((pi->amp_move_state != L2CAP_AMP_STATE_STABLE &&
diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
new file mode 100644
index 0000000..987594a
--- /dev/null
+++ b/sound/compress_offload/core.c
@@ -0,0 +1,658 @@
+/*
+ *  core.c - compress offload core
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
+ *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  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.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <sound/snd_compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - Integrate with alsa, compressed devices should register as alsa devices
+ *	as /dev/snd_compr_xxx
+ * - Integrate with ASoC:
+ *	Opening compressed path should also start the codec dai
+ *   TBD how the cpu dai will be viewed and started.
+ *	ASoC should always be optional part
+ *	(we should be able to use this framework in non asoc systems
+ * - Multiple node representation
+ *	driver should be able to register multiple nodes
+ * - Version numbering for API
+ */
+
+static DEFINE_MUTEX(device_mutex);
+static LIST_HEAD(device_list);
+static LIST_HEAD(misc_list);
+
+/*
+ * currently we are using misc device for registration and exposing ioctls
+ * this is temporary and will be moved to snd
+ * the device should be registered as /dev/snd_compr.....
+ */
+
+struct snd_compr_misc {
+	struct miscdevice misc;
+	struct list_head list;
+	struct snd_compr *compr;
+};
+
+struct snd_ioctl_data {
+	struct snd_compr_misc *misc;
+	unsigned long caps;
+	unsigned int minor;
+	struct snd_compr_stream stream;
+};
+
+static struct snd_compr_misc *snd_compr_get_device(unsigned int minor)
+{
+	struct snd_compr_misc *misc;
+
+	list_for_each_entry(misc, &misc_list, list) {
+		if (minor == misc->misc.minor)
+			return misc;
+	}
+	return NULL;
+}
+
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+	unsigned int minor = iminor(inode);
+	struct snd_compr_misc *misc = snd_compr_get_device(minor);
+	struct snd_ioctl_data *data;
+	struct snd_compr_runtime *runtime;
+	unsigned int direction;
+	int ret;
+
+	mutex_lock(&device_mutex);
+	if (f->f_flags & O_WRONLY)
+		direction = SNDRV_PCM_STREAM_PLAYBACK;
+	else {
+		ret = -ENXIO;
+		goto out;
+	}
+	/* curently only encoded playback is supported, above needs to be
+	 * removed once we have recording support */
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	data->misc = misc;
+	data->minor = minor;
+	data->stream.ops = misc->compr->ops;
+	data->stream.direction = direction;
+	data->stream.private_data = misc->compr->private_data;
+	data->stream.device = misc->compr;
+	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+	if (!runtime) {
+		ret = -ENOMEM;
+		kfree(data);
+		goto out;
+	}
+	runtime->state = SNDRV_PCM_STATE_OPEN;
+	init_waitqueue_head(&runtime->sleep);
+	data->stream.runtime = runtime;
+	f->private_data = (void *)data;
+	ret = misc->compr->ops->open(&data->stream);
+	if (ret) {
+		kfree(runtime);
+		kfree(data);
+		goto out;
+	}
+out:
+	mutex_unlock(&device_mutex);
+	return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	mutex_lock(&device_mutex);
+	data->stream.ops->free(&data->stream);
+	kfree(data->stream.runtime->buffer);
+	kfree(data->stream.runtime);
+	kfree(data);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+		struct snd_compr_tstamp *tstamp)
+{
+	stream->ops->pointer(stream, tstamp);
+	stream->runtime->hw_pointer = tstamp->copied_bytes;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+		struct snd_compr_avail *avail)
+{
+	size_t avail_calc;
+
+	snd_compr_update_tstamp(stream, &avail->tstamp);
+	avail_calc = stream->runtime->app_pointer - stream->runtime->hw_pointer;
+	if (avail_calc < 0)
+		avail_calc = stream->runtime->buffer_size + avail_calc;
+	avail->avail = avail_calc;
+	return avail_calc;
+}
+
+static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+	struct snd_compr_avail avail;
+
+	return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_avail ioctl_avail;
+
+	snd_compr_calc_avail(stream, &ioctl_avail);
+
+	if (copy_to_user((unsigned long __user *)arg, &ioctl_avail, sizeof(ioctl_avail)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+	       const char __user *buf, size_t count)
+{
+	void *dstn;
+	size_t copy;
+
+	dstn = stream->runtime->buffer + stream->runtime->app_pointer;
+	if (count < stream->runtime->buffer_size - stream->runtime->app_pointer) {
+		if (copy_from_user(dstn, buf, count))
+			return -EFAULT;
+		stream->runtime->app_pointer += count;
+	} else {
+		copy = stream->runtime->buffer_size - stream->runtime->app_pointer;
+		if (copy_from_user(dstn, buf, copy))
+			return -EFAULT;
+		if (copy_from_user(stream->runtime->buffer, buf + copy, count - copy))
+			return -EFAULT;
+		stream->runtime->app_pointer = count - copy;
+	}
+	/* if DSP cares, let it know data has been written */
+	if (stream->ops->ack)
+		stream->ops->ack(stream);
+	return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+		size_t count, loff_t *offset)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+	size_t avail;
+	int retval;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	/* write is allowed when stream is running or has been steup */
+	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		mutex_unlock(&stream->device->lock);
+		return -EPERM;
+	}
+
+	avail = snd_compr_get_avail(stream);
+	/* calculate how much we can write to buffer */
+	if (avail > count)
+		avail = count;
+
+	if (stream->ops->copy)
+		retval = stream->ops->copy(stream, buf, avail);
+	else
+		retval = snd_compr_write_data(stream, buf, avail);
+
+	/* while initiating the stream, write should be called before START
+	 * call, so in setup move state */
+	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+	return -ENXIO;
+}
+
+unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = 0;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+
+	mutex_lock(&stream->device->lock);
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+		retval = -ENXIO;
+		goto out;
+	}
+	poll_wait(f, &stream->runtime->sleep, wait);
+
+	/* this would change after read is implemented, we would need to
+	 * check for direction here */
+	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+		retval = POLLOUT | POLLWRNORM;
+out:
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
+{
+	size_t avail;
+
+	if (stream->direction !=  SNDRV_PCM_STREAM_PLAYBACK)
+		return;
+	avail = snd_compr_get_avail(stream);
+	if (avail >= stream->runtime->fragment_size)
+		wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
+
+void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
+{
+	size_t avail;
+
+	if (stream->direction !=  SNDRV_PCM_STREAM_CAPTURE)
+		return;
+	avail = snd_compr_get_avail(stream);
+	if (avail)
+		wake_up(&stream->runtime->sleep);
+}
+EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
+
+static int snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_caps caps;
+
+	if (!stream->ops->get_caps)
+		return -ENXIO;
+
+	retval = stream->ops->get_caps(stream, &caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+		retval = -EFAULT;
+out:
+	return retval;
+}
+
+static int snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+	int retval;
+	struct snd_compr_codec_caps *caps;
+
+	if (!stream->ops->get_codec_caps)
+		return -ENXIO;
+
+	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+	if (!caps)
+		return -ENOMEM;
+
+	retval = stream->ops->get_codec_caps(stream, caps);
+	if (retval)
+		goto out;
+	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+		retval = -EFAULT;
+
+out:
+	kfree(caps);
+	return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+		struct snd_compr_params *params)
+{
+	unsigned int buffer_size;
+	void *buffer;
+
+	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+	if (stream->ops->copy) {
+		buffer = NULL;
+		/* if copy is defined the driver will be required to copy
+		 * the data from core
+		 */
+	} else {
+		buffer = kmalloc(buffer_size, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+	}
+	stream->runtime->fragment_size = params->buffer.fragment_size;
+	stream->runtime->fragments = params->buffer.fragments;
+	stream->runtime->buffer = buffer;
+	stream->runtime->buffer_size = buffer_size;
+	return 0;
+}
+
+static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+		/*
+		 * we should allow parameter change only when stream has been
+		 * opened not in other cases
+		 */
+		params = kmalloc(sizeof(*params), GFP_KERNEL);
+		if (!params)
+			return -ENOMEM;
+		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
+			return -EFAULT;
+		retval = snd_compr_allocate_buffer(stream, params);
+		if (retval) {
+			kfree(params);
+			return -ENOMEM;
+		}
+		retval = stream->ops->set_params(stream, params);
+		if (retval)
+			goto out;
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+	} else
+		return -EPERM;
+out:
+	kfree(params);
+	return retval;
+}
+
+static int snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_params *params;
+	int retval;
+
+	if (!stream->ops->get_params)
+		return -ENXIO;
+
+	params = kmalloc(sizeof(*params), GFP_KERNEL);
+	if (!params)
+		return -ENOMEM;
+	retval = stream->ops->get_params(stream, params);
+	if (retval)
+		goto out;
+	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+		retval = -EFAULT;
+
+out:
+	kfree(params);
+	return retval;
+}
+
+static int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+	struct snd_compr_tstamp tstamp;
+
+	snd_compr_update_tstamp(stream, &tstamp);
+	if (copy_to_user((struct snd_compr_tstamp __user *)arg, &tstamp, sizeof(tstamp)))
+		return -EFAULT;
+	return 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED)
+		return 0;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+	if (!retval)
+		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+	return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+	int retval;
+
+	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
+			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+		return -EPERM;
+	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+	if (!retval) {
+		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+		wake_up(&stream->runtime->sleep);
+	}
+	return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct snd_ioctl_data *data = f->private_data;
+	struct snd_compr_stream *stream;
+	int retval = -ENOTTY;
+
+	BUG_ON(!data);
+	stream = &data->stream;
+	mutex_lock(&stream->device->lock);
+	switch (_IOC_NR(cmd)) {
+	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+		retval = snd_compr_get_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+		retval = snd_compr_get_codec_caps(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+		retval = snd_compr_set_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+		retval = snd_compr_get_params(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+		retval = snd_compr_tstamp(stream, arg);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+		retval = snd_compr_ioctl_avail(stream, arg);
+	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+		retval = snd_compr_pause(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_RESUME):
+		retval = snd_compr_resume(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_START):
+		retval = snd_compr_start(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_STOP):
+		retval = snd_compr_stop(stream);
+		break;
+	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+		cmd = SND_COMPR_TRIGGER_DRAIN;
+		retval = snd_compr_drain(stream);
+		break;
+	}
+	mutex_unlock(&stream->device->lock);
+	return retval;
+}
+
+static const struct file_operations snd_comp_file = {
+	.owner =	THIS_MODULE,
+	.open =		snd_compr_open,
+	.release =	snd_compr_free,
+	.read =		snd_compr_read,
+	.write =	snd_compr_write,
+	.unlocked_ioctl = snd_compr_ioctl,
+	.mmap =		snd_compr_mmap,
+	.poll =		snd_compr_poll,
+};
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+	int ret;
+
+	struct snd_compr_misc *misc = kzalloc(sizeof(*misc), GFP_KERNEL);
+
+	misc->misc.name = device->name;
+	misc->misc.fops = &snd_comp_file;
+	misc->misc.minor = MISC_DYNAMIC_MINOR;
+	misc->compr = device;
+	ret = misc_register(&misc->misc);
+	if (ret) {
+		pr_err("couldn't register misc device\n");
+		kfree(misc);
+	} else {
+		pr_debug("Got minor %d\n", misc->misc.minor);
+		list_add_tail(&misc->list, &misc_list);
+	}
+	return ret;
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+	struct snd_compr_misc *misc, *__misc;
+
+	list_for_each_entry_safe(misc, __misc, &misc_list, list) {
+		if (device == misc->compr) {
+			misc_deregister(&misc->misc);
+			list_del(&device->list);
+			kfree(misc);
+		}
+	}
+	return 0;
+}
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+	int retval;
+
+	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+		return -EINVAL;
+	BUG_ON(!device->ops->open);
+	BUG_ON(!device->ops->free);
+	BUG_ON(!device->ops->set_params);
+	BUG_ON(!device->ops->get_params);
+	BUG_ON(!device->ops->trigger);
+	BUG_ON(!device->ops->pointer);
+	BUG_ON(!device->ops->get_caps);
+	BUG_ON(!device->ops->get_codec_caps);
+
+	INIT_LIST_HEAD(&device->list);
+	/* todo register the compressed streams */
+	/* todo integrate with asoc */
+
+	/* register a compressed card  TBD if this needs change */
+
+	pr_debug("Registering compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	/*  register a msic device for now */
+	retval = snd_compress_add_device(device);
+	if (!retval)
+		list_add_tail(&device->list, &device_list);
+	mutex_unlock(&device_mutex);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+	pr_debug("Removing compressed device %s\n", device->name);
+	mutex_lock(&device_mutex);
+	snd_compress_remove_device(device);
+	list_del(&device->list);
+	mutex_unlock(&device_mutex);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+	return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d330f7a..3b83532 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -62,6 +62,22 @@
 	u16 ctl_reg;
 };
 
+/* Codec supports 2 IIR filters */
+enum {
+	IIR1 = 0,
+	IIR2,
+	IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+	BAND1 = 0,
+	BAND2,
+	BAND3,
+	BAND4,
+	BAND5,
+	BAND_MAX,
+};
+
 struct tabla_priv {
 	struct snd_soc_codec *codec;
 	u32 adc_count;
@@ -204,6 +220,173 @@
 	return 0;
 }
 
+static int tabla_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, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+		(1 << band_idx);
+
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int tabla_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, (TABLA_A_CDC_IIR1_CTL + 16 * iir_idx),
+		(1 << band_idx), (value << band_idx));
+
+	pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+		iir_idx, band_idx, value);
+	return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx)
+{
+	/* Address does not automatically update if reading */
+	snd_soc_update_bits(codec,
+		(TABLA_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,
+		(TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24) |
+		(snd_soc_read(codec,
+		(TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx)) << 16) |
+		(snd_soc_read(codec,
+		(TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx)) << 8) |
+		(snd_soc_read(codec,
+		(TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx)))) &
+		0x3FFFFFFF;
+}
+
+static int tabla_get_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	ucontrol->value.integer.value[0] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+	ucontrol->value.integer.value[1] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+	ucontrol->value.integer.value[2] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+	ucontrol->value.integer.value[3] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+	ucontrol->value.integer.value[4] =
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[0],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[1],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[2],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[3],
+		__func__, iir_idx, band_idx,
+		(uint32_t)ucontrol->value.integer.value[4]);
+	return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+				int iir_idx, int band_idx,
+				int coeff_idx, uint32_t value)
+{
+	/* Mask top 3 bits, 6-8 are reserved */
+	/* Update address manually each time */
+	snd_soc_update_bits(codec,
+		(TABLA_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,
+		(TABLA_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+		0x3F, (value >> 24) & 0x3F);
+
+	/* Isolate 8bits at a time */
+	snd_soc_update_bits(codec,
+		(TABLA_A_CDC_IIR1_COEF_B3_CTL + 16 * iir_idx),
+		0xFF, (value >> 16) & 0xFF);
+
+	snd_soc_update_bits(codec,
+		(TABLA_A_CDC_IIR1_COEF_B4_CTL + 16 * iir_idx),
+		0xFF, (value >> 8) & 0xFF);
+
+	snd_soc_update_bits(codec,
+		(TABLA_A_CDC_IIR1_COEF_B5_CTL + 16 * iir_idx),
+		0xFF, value & 0xFF);
+}
+
+static int tabla_put_iir_band_audio_mixer(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int iir_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->reg;
+	int band_idx = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+
+	set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+				ucontrol->value.integer.value[0]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+				ucontrol->value.integer.value[1]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+				ucontrol->value.integer.value[2]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+				ucontrol->value.integer.value[3]);
+	set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+				ucontrol->value.integer.value[4]);
+
+	pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+		"%s: IIR #%d band #%d b1 = 0x%x\n"
+		"%s: IIR #%d band #%d b2 = 0x%x\n"
+		"%s: IIR #%d band #%d a1 = 0x%x\n"
+		"%s: IIR #%d band #%d a2 = 0x%x\n",
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+		__func__, iir_idx, band_idx,
+		get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+	return 0;
+}
+
 static const char *tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
 static const struct soc_enum tabla_ear_pa_gain_enum[] = {
 		SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
@@ -342,6 +525,7 @@
 	SOC_SINGLE_TLV("ADC6 Volume", TABLA_A_TX_5_6_EN, 1, 3, 0, analog_gain),
 
 	SOC_SINGLE("MICBIAS1 CAPLESS Switch", TABLA_A_MICB_1_CTL, 4, 1, 1),
+	SOC_SINGLE("MICBIAS2 CAPLESS Switch", TABLA_A_MICB_2_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS3 CAPLESS Switch", TABLA_A_MICB_3_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS4 CAPLESS Switch", TABLA_A_MICB_4_CTL, 4, 1, 1),
 
@@ -384,6 +568,48 @@
 	SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
 	SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
 	SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
+
+	SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+	SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+	tabla_get_iir_enable_audio_mixer, tabla_put_iir_enable_audio_mixer),
+
+	SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
+	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+	tabla_get_iir_band_audio_mixer, tabla_put_iir_band_audio_mixer),
 };
 
 static const char *rx_mix1_text[] = {
@@ -1988,6 +2214,11 @@
 	if ((reg >= TABLA_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
 		return 1;
 
+	/* IIR Coeff registers are not cacheable */
+	if ((reg >= TABLA_A_CDC_IIR1_COEF_B1_CTL) &&
+		(reg <= TABLA_A_CDC_IIR2_COEF_B5_CTL))
+		return 1;
+
 	return 0;
 }
 
@@ -2168,7 +2399,7 @@
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B10_CTL, 0xFF);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B9_CTL, 0x20);
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08);
+	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0xF8);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
@@ -2762,7 +2993,6 @@
 	 */
 	priv->buttons_pressed |= SND_JACK_BTN_0;
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x09);
 	msleep(100);
 
 	schedule_delayed_work(&priv->btn0_dwork, msecs_to_jiffies(400));
@@ -2822,7 +3052,6 @@
 		priv->buttons_pressed &= ~SND_JACK_BTN_0;
 	}
 
-	snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x08);
 	tabla_codec_start_hs_polling(codec);
 
 	return IRQ_HANDLED;
diff --git a/sound/soc/msm/msm8660-apq-wm8903.c b/sound/soc/msm/msm8660-apq-wm8903.c
index af72872..a163006 100644
--- a/sound/soc/msm/msm8660-apq-wm8903.c
+++ b/sound/soc/msm/msm8660-apq-wm8903.c
@@ -9,8 +9,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- *TODO:
- *  - Audio stream capture support
  */
 
 #include <linux/clk.h>
@@ -34,11 +32,11 @@
 #define MSM_GPIO_CLASS_D0_EN  80
 #define MSM_GPIO_CLASS_D1_EN  81
 
-#define MSM8660_SPK_ON    1
-#define MSM8660_SPK_OFF   0
 #define MSM_CDC_MIC_I2S_MCLK 108
 
 static int msm8660_spk_func;
+static int msm8660_headset_func;
+static int msm8660_headphone_func;
 
 static struct clk *mic_bit_clk;
 static struct clk *spkr_osr_clk;
@@ -56,6 +54,11 @@
 	NONE
 };
 
+enum {
+	FUNC_OFF,
+	FUNC_ON,
+};
+
 static struct wm8903_vdd {
 	struct regulator *reg_id;
 	const char *name;
@@ -295,23 +298,19 @@
 		/* config WM8903 in Mater mode */
 		ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
 				SND_SOC_DAIFMT_I2S);
-		mic_bit_clk = clk_get(NULL, "i2s_mic_bit_clk");
-		if (IS_ERR(mic_bit_clk)) {
-			pr_err("Failed to get i2s_mic_bit_clk\n");
-			return PTR_ERR(mic_bit_clk);
-		}
-		clk_set_rate(mic_bit_clk, 0);
-		ret = clk_enable(mic_bit_clk);
 		if (ret != 0) {
-			pr_err("Unable to enable i2s_mic_bit_clk\n");
-			clk_put(mic_bit_clk);
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
+		/* config CPU in SLAVE mode */
+		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
+		if (ret != 0) {
+			pr_err("cpu_dai set_fmt error\n");
 			return ret;
 		}
 		spkr_osr_clk = clk_get(NULL, "i2s_spkr_osr_clk");
 		if (IS_ERR(spkr_osr_clk)) {
 			pr_err("Failed to get i2s_spkr_osr_clk\n");
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return PTR_ERR(spkr_osr_clk);
 		}
 		clk_set_rate(spkr_osr_clk, 48000 * 256);
@@ -319,8 +318,6 @@
 		if (ret != 0) {
 			pr_err("Unable to enable i2s_spkr_osr_clk\n");
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return ret;
 		}
 		spkr_bit_clk = clk_get(NULL, "i2s_spkr_bit_clk");
@@ -328,8 +325,6 @@
 			pr_err("Failed to get i2s_spkr_bit_clk\n");
 			clk_disable(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			return PTR_ERR(spkr_bit_clk);
 		}
 		clk_set_rate(spkr_bit_clk, 0);
@@ -338,15 +333,24 @@
 			pr_err("Unable to enable i2s_spkr_bit_clk\n");
 			clk_disable(spkr_osr_clk);
 			clk_put(spkr_osr_clk);
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
 			clk_put(spkr_bit_clk);
 			return ret;
 		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		/* config WM8903 in Mater mode */
+		ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_CBM_CFM |
+				SND_SOC_DAIFMT_I2S);
+		if (ret != 0) {
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
 		/* config CPU in SLAVE mode */
 		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM);
-		/* End of platform specific logic */
-	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (ret != 0) {
+			pr_err("codec_dai set_fmt error\n");
+			return ret;
+		}
+
 		mic_bit_clk = clk_get(NULL, "i2s_mic_bit_clk");
 		if (IS_ERR(mic_bit_clk)) {
 			pr_err("Failed to get i2s_mic_bit_clk\n");
@@ -359,7 +363,6 @@
 			clk_put(mic_bit_clk);
 			return ret;
 		}
-		msleep(30);
 	}
 	return ret;
 }
@@ -367,7 +370,9 @@
 static void msm8660_i2s_shutdown(struct snd_pcm_substream *substream)
 {
 	pr_debug("Enter %s\n", __func__);
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+			 substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		tx_hw_param_status = 0;
 		rx_hw_param_status = 0;
 		if (spkr_bit_clk) {
 			clk_disable(spkr_bit_clk);
@@ -384,25 +389,29 @@
 			clk_put(mic_bit_clk);
 			mic_bit_clk = NULL;
 		}
-	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-		tx_hw_param_status = 0;
-		msleep(30);
-		if (mic_bit_clk) {
-			clk_disable(mic_bit_clk);
-			clk_put(mic_bit_clk);
-			mic_bit_clk = NULL;
-		}
 	}
 }
 
 static void msm8660_ext_control(struct snd_soc_codec *codec)
 {
 	/* set the enpoints to their new connetion states */
-	if (msm8660_spk_func == MSM8660_SPK_ON)
+	if (msm8660_spk_func == FUNC_ON)
 		snd_soc_dapm_enable_pin(&codec->dapm, "Ext Spk");
 	else
 		snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
 
+	/* set the enpoints to their new connetion states */
+	if (msm8660_headset_func == FUNC_ON)
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headset Jack");
+	else
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headset Jack");
+
+	/* set the enpoints to their new connetion states */
+	if (msm8660_headphone_func == FUNC_ON)
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphone Jack");
+
 	/* signal a DAPM event */
 	snd_soc_dapm_sync(&codec->dapm);
 }
@@ -428,6 +437,48 @@
 	return 1;
 }
 
+static int msm8660_get_hs(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm8660_headset_func;
+	return 0;
+}
+
+static int msm8660_set_hs(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 (msm8660_headset_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm8660_headset_func = ucontrol->value.integer.value[0];
+	msm8660_ext_control(codec);
+	return 1;
+}
+
+static int msm8660_get_hph(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm8660_headphone_func;
+	return 0;
+}
+
+static int msm8660_set_hph(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 (msm8660_headphone_func == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm8660_headphone_func = ucontrol->value.integer.value[0];
+	msm8660_ext_control(codec);
+	return 1;
+}
+
 static int msm8660_spkramp_event(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *k, int event)
 {
@@ -446,22 +497,42 @@
 
 static const struct snd_soc_dapm_widget msm8660_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Ext Spk", msm8660_spkramp_event),
+	SND_SOC_DAPM_MIC("Headset Jack", NULL),
+	SND_SOC_DAPM_MIC("Headphone Jack", NULL),
+	/* to fix a bug in wm8903.c, where audio doesn't function
+	 * after suspend/resume
+	 */
+	SND_SOC_DAPM_SUPPLY("CLK_SYS_ENA", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
 	/* Match with wm8903 codec line out pin */
 	{"Ext Spk", NULL, "LINEOUTL"},
 	{"Ext Spk", NULL, "LINEOUTR"},
+	/* Headset connects to IN3L with Bias */
+	{"IN3L", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headset Jack"},
+	/* Headphone connects to IN3R with Bias */
+	{"IN3R", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headphone Jack"},
+	{"ADCL", NULL, "CLK_SYS_ENA"},
+	{"ADCR", NULL, "CLK_SYS_ENA"},
+	{"DACL", NULL, "CLK_SYS_ENA"},
+	{"DACR", NULL, "CLK_SYS_ENA"},
 };
 
-static const char *spk_function[] = {"Off", "On"};
+static const char *cmn_status[] = {"Off", "On"};
 static const struct soc_enum msm8660_enum[] = {
-	SOC_ENUM_SINGLE_EXT(2, spk_function),
+	SOC_ENUM_SINGLE_EXT(2, cmn_status),
 };
 
 static const struct snd_kcontrol_new wm8903_msm8660_controls[] = {
 	SOC_ENUM_EXT("Speaker Function", msm8660_enum[0], msm8660_get_spk,
 		msm8660_set_spk),
+	SOC_ENUM_EXT("Headset Function", msm8660_enum[0], msm8660_get_hs,
+		msm8660_set_hs),
+	SOC_ENUM_EXT("Headphone Function", msm8660_enum[0], msm8660_get_hph,
+		msm8660_set_hph),
 };
 
 static int msm8660_audrx_init(struct snd_soc_pcm_runtime *rtd)
@@ -470,6 +541,7 @@
 	int err;
 
 	snd_soc_dapm_disable_pin(&codec->dapm, "Ext Spk");
+	snd_soc_dapm_enable_pin(&codec->dapm, "CLK_SYS_ENA");
 
 	err = snd_soc_add_controls(codec, wm8903_msm8660_controls,
 				ARRAY_SIZE(wm8903_msm8660_controls));
diff --git a/sound/soc/soc-dsp.c b/sound/soc/soc-dsp.c
index bef84a1..6b0c215 100644
--- a/sound/soc/soc-dsp.c
+++ b/sound/soc/soc-dsp.c
@@ -482,6 +482,9 @@
 		struct snd_pcm_substream *be_substream =
 			snd_soc_dsp_get_substream(dsp_params->be, stream);
 
+		if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
+			continue;
+
 		/* is this op for this BE ? */
 		if (fe->dsp[stream].runtime_update &&
 				!dsp_params->be->dsp[stream].runtime_update)
@@ -490,9 +493,6 @@
 		if (--dsp_params->be->dsp[stream].users != 0)
 			continue;
 
-		if (dsp_params->state != SND_SOC_DSP_LINK_STATE_FREE)
-			continue;
-
 		dev_dbg(&dsp_params->be->dev, "dsp: close BE %s\n",
 			dsp_params->fe->dai_link->name);