Merge "qseecom: Add support for loading elf images" into msm-3.0
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 3cebfa0..595bdd3 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -6,6 +6,8 @@
 # To add a new book the only step required is to add the book to the
 # list of DOCBOOKS.
 
+TMPMEDIA=.tmpmedia
+
 DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
 	    writing_usb_driver.xml networking.xml \
@@ -14,7 +16,7 @@
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
 	    80211.xml debugobjects.xml sh.xml regulator.xml \
 	    alsa-driver-api.xml writing-an-alsa-driver.xml \
-	    tracepoint.xml media.xml drm.xml
+	    tracepoint.xml $(TMPMEDIA)/media.xml drm.xml
 
 ###
 # The build process is as follows (targets):
@@ -32,7 +34,7 @@
 
 ###
 # The targets that may be used.
-PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
+PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs mediaprep
 
 BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
 xmldocs: $(BOOKS)
@@ -45,27 +47,13 @@
 pdfdocs: $(PDF)
 
 HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
-htmldocs: $(HTML) xmldoclinks
+htmldocs: $(HTML)
 	$(call build_main_index)
 	$(call build_images)
 
 MAN := $(patsubst %.xml, %.9, $(BOOKS))
 mandocs: $(MAN)
 
-build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
-	       cp $(srctree)/Documentation/DocBook/dvb/*.png \
-	          $(srctree)/Documentation/DocBook/v4l/*.gif \
-		  $(objtree)/Documentation/DocBook/media/
-
-xmldoclinks:
-ifneq ($(objtree),$(srctree))
-	for dep in dvb media-entities.tmpl media-indices.tmpl v4l; do \
-		rm -f $(objtree)/Documentation/DocBook/$$dep \
-		&& ln -s $(srctree)/Documentation/DocBook/$$dep $(objtree)/Documentation/DocBook/ \
-		|| exit; \
-	done
-endif
-
 installmandocs: mandocs
 	mkdir -p /usr/local/man/man9/
 	install Documentation/DocBook/man/*.9.gz /usr/local/man/man9/
@@ -97,11 +85,11 @@
         ) > $(dir $@).$(notdir $@).cmd
 endef
 
-%.xml: %.tmpl xmldoclinks FORCE
+%.xml: %.tmpl FORCE
 	$(call if_changed_rule,docproc)
 
 ###
-#Read in all saved dependency files 
+#Read in all saved dependency files
 cmd_files := $(wildcard $(foreach f,$(BOOKS),$(dir $(f)).$(notdir $(f)).cmd))
 
 ifneq ($(cmd_files),)
@@ -150,7 +138,7 @@
 
 index = index.html
 main_idx = Documentation/DocBook/$(index)
-build_main_index = rm -rf $(main_idx) && \
+build_main_index = rm -rf $(main_idx); \
 		   echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \
 		   echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \
 		   cat $(HTML) >> $(main_idx)
@@ -240,7 +228,7 @@
 	$(patsubst %.xml, %.9,    $(DOCBOOKS)) \
 	$(index)
 
-clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
+clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man $(MEDIA_DIR)
 
 cleandocs:
 	$(Q)rm -f $(call objectify, $(clean-files))
@@ -250,3 +238,252 @@
 # information in a variable se we can use it in if_changed and friends.
 
 .PHONY: $(PHONY)
+
+
+#
+# Media build rules - Auto-generates media contents/indexes and *.h xml's
+#
+
+SHELL=/bin/bash
+
+MEDIA_DIR=$(objtree)/Documentation/DocBook/$(TMPMEDIA)
+
+V4L_SGMLS = \
+	$(shell ls $(srctree)/Documentation/DocBook/v4l/*.xml|perl -ne 'print "$$1 " if (m,.*/(.*)\n,)') \
+	capture.c.xml \
+	keytable.c.xml \
+	v4l2grab.c.xml
+
+DVB_SGMLS = \
+	$(shell ls $(srctree)/Documentation/DocBook/dvb/*.xml|perl -ne 'print "$$1 " if (m,.*/(.*)\n,)')
+
+MEDIA_TEMP =  media-entities.tmpl \
+	      media-indices.tmpl \
+	      videodev2.h.xml \
+	      frontend.h.xml
+
+MEDIA_SGMLS =  $(addprefix ./,$(V4L_SGMLS)) $(addprefix ./,$(DVB_SGMLS)) $(addprefix ./,$(MEDIA_TEMP))
+
+MEDIA_TEMP_OBJ := $(addprefix $(MEDIA_DIR)/,$(MEDIA_TEMP))
+
+FUNCS = \
+	close \
+	ioctl \
+	mmap \
+	munmap \
+	open \
+	poll \
+	read \
+	select \
+	write \
+
+IOCTLS = \
+	$(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/videodev2.h) \
+	$(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/media.h) \
+	$(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/v4l2-subdev.h) \
+	VIDIOC_SUBDEV_G_FRAME_INTERVAL \
+	VIDIOC_SUBDEV_S_FRAME_INTERVAL \
+	VIDIOC_SUBDEV_ENUM_MBUS_CODE \
+	VIDIOC_SUBDEV_ENUM_FRAME_SIZE \
+	VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL \
+
+TYPES = \
+	$(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h)
+
+ENUMS = \
+	$(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
+	$(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
+	$(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) \
+	$(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h)
+
+STRUCTS = \
+	$(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
+	$(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
+	$(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) \
+	$(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h)
+
+ERRORS = \
+	EACCES \
+	EAGAIN \
+	EBADF \
+	EBUSY \
+	EFAULT \
+	EIO \
+	EINTR \
+	EINVAL \
+	ENFILE \
+	ENOMEM \
+	ENOSPC \
+	ENOTTY \
+	ENXIO \
+	EMFILE \
+	EPERM \
+	ERANGE \
+	EPIPE \
+
+ESCAPE = \
+	-e "s/&/\\&amp;/g" \
+	-e "s/</\\&lt;/g" \
+	-e "s/>/\\&gt;/g"
+
+FILENAME = \
+	-e s,"^[^\/]*/",, \
+	-e s/"\\.xml"// \
+	-e s/"\\.tmpl"// \
+	-e s/\\\./-/g \
+	-e s/"^func-"// \
+	-e s/"^pixfmt-"// \
+	-e s/"^vidioc-"//
+
+# Generate references to these structs in videodev2.h.xml.
+DOCUMENTED = \
+	-e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
+	-e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
+	-e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+	-e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
+	-e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
+
+DVB_DOCUMENTED = \
+	-e "s,\(define \)\([A-Z0-9_]\+\)\(\s\+_IO\),\1\<link linkend=\"\2\">\2\<\/link\>\3,g" \
+	-e "s/\(linkend\=\"\)FE_SET_PROPERTY/\1FE_GET_PROPERTY/g"
+
+
+#
+# Media targets and dependencies
+#
+
+$(obj)/$(TMPMEDIA)/media.xml: $(obj)/media.tmpl $(MEDIA_TEMP_OBJ) FORCE
+	$(call if_changed_rule,docproc)
+
+$(MEDIA_DIR)/v4l2.xml:
+	@$($(quiet)gen_xml)
+	@(mkdir -p $(MEDIA_DIR))
+	@(cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(MEDIA_DIR)/)
+	@(ln -sf $(srctree)/Documentation/DocBook/v4l/*xml $(MEDIA_DIR)/)
+	@(ln -sf $(srctree)/Documentation/DocBook/dvb/*xml $(MEDIA_DIR)/)
+
+$(MEDIA_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_DIR)/v4l2.xml
+	@$($(quiet)gen_xml)
+	@(					\
+	echo "<programlisting>") > $@
+	@(					\
+	expand --tabs=8 < $< |			\
+	  sed $(ESCAPE) $(DOCUMENTED) |		\
+	  sed 's/i\.e\./&ie;/') >> $@
+	@(					\
+	echo "</programlisting>") >> $@
+
+$(MEDIA_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA_DIR)/v4l2.xml
+	@$($(quiet)gen_xml)
+	@(					\
+	echo "<programlisting>") > $@
+	@(					\
+	expand --tabs=8 < $< |			\
+	  sed $(ESCAPE) $(DVB_DOCUMENTED) |	\
+	  sed 's/i\.e\./&ie;/') >> $@
+	@(					\
+	echo "</programlisting>") >> $@
+
+$(MEDIA_DIR)/media-entities.tmpl: $(MEDIA_DIR)/v4l2.xml
+	@$($(quiet)gen_xml)
+	@(								\
+	echo "<!-- Generated file! Do not edit. -->") >$@
+	@(								\
+	echo -e "\n<!-- Functions -->") >>$@
+	@(								\
+	for ident in $(FUNCS) ; do					\
+	  entity=`echo $$ident | tr _ -` ;				\
+	  echo "<!ENTITY func-$$entity \"<link"				\
+	    "linkend='func-$$entity'><function>$$ident()</function></link>\">" \
+	  >>$@ ;							\
+	done)
+	@(								\
+	echo -e "\n<!-- Ioctls -->") >>$@
+	@(								\
+	for ident in $(IOCTLS) ; do					\
+	  entity=`echo $$ident | tr _ -` ;				\
+	  id=`grep "<refname>$$ident" $(MEDIA_DIR)/vidioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
+	  echo "<!ENTITY $$entity \"<link"				\
+	    "linkend='$$id'><constant>$$ident</constant></link>\">"	\
+	  >>$@ ;							\
+	done)
+	@(								\
+	echo -e "\n<!-- Types -->") >>$@
+	@(								\
+	for ident in $(TYPES) ; do					\
+	  entity=`echo $$ident | tr _ -` ;				\
+	  echo "<!ENTITY $$entity \"<link"				\
+	    "linkend='$$entity'>$$ident</link>\">" >>$@ ;		\
+	done)
+	@(								\
+	echo -e "\n<!-- Enums -->") >>$@
+	@(								\
+	for ident in $(ENUMS) ; do					\
+	  entity=`echo $$ident | sed -e "s/v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1/" | tr _ -` ; \
+	  echo "<!ENTITY $$entity \"enum&nbsp;<link"			\
+	    "linkend='$$entity'>$$ident</link>\">" >>$@ ;		\
+	done)
+	@(								\
+	echo -e "\n<!-- Structures -->") >>$@
+	@(								\
+	for ident in $(STRUCTS) ; do					\
+	  entity=`echo $$ident | tr _ - | sed s/v4l2-mpeg-vbi-ITV0/v4l2-mpeg-vbi-itv0-1/g` ; \
+	  echo "<!ENTITY $$entity \"struct&nbsp;<link"			\
+	    "linkend='$$entity'>$$ident</link>\">" >>$@ ;		\
+	done)
+	@(								\
+	echo -e "\n<!-- Error Codes -->") >>$@
+	@(								\
+	for ident in $(ERRORS) ; do					\
+	  echo "<!ENTITY $$ident \"<errorcode>$$ident</errorcode>"	\
+	    "error code\">" >>$@ ;					\
+	done)
+	@(								\
+	echo -e "\n<!-- Subsections -->") >>$@
+	@(								\
+	for file in $(MEDIA_SGMLS) ; do					\
+	  entity=`echo "$$file" | sed $(FILENAME) -e s/"^([^-]*)"/sub\1/` ; \
+	  if ! echo "$$file" |						\
+	    grep -q -E -e '^(func|vidioc|pixfmt)-' ; then		\
+	    echo "<!ENTITY sub-$$entity SYSTEM \"$$file\">" >>$@ ;	\
+	  fi ;								\
+	done)
+	@(								\
+	echo -e "\n<!-- Function Reference -->") >>$@
+	@(								\
+	for file in $(MEDIA_SGMLS) ; do					\
+	  if echo "$$file" |						\
+	    grep -q -E -e '(func|vidioc|pixfmt)-' ; then		\
+	    entity=`echo "$$file" |sed $(FILENAME)` ;			\
+	    echo "<!ENTITY $$entity SYSTEM \"$$file\">" >>$@ ;	\
+	  fi ;								\
+	done)
+
+# Jade can auto-generate a list-of-tables, which includes all structs,
+# but we only want data types, all types, and sorted please.
+$(MEDIA_DIR)/media-indices.tmpl: $(MEDIA_DIR)/v4l2.xml
+	@$($(quiet)gen_xml)
+	@(								\
+	echo "<!-- Generated file! Do not edit. -->") >$@
+	@(								\
+	echo -e "\n<index><title>List of Types</title>") >>$@
+	@(								\
+	for ident in $(TYPES) ; do					\
+	  id=`echo $$ident | tr _ -` ;					\
+	  echo "<indexentry><primaryie><link"				\
+	    "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+	done)
+	@(								\
+	for ident in $(ENUMS) ; do					\
+	  id=`echo $$ident | sed -e "s/v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1/" | tr _ -`; \
+	  echo "<indexentry><primaryie>enum&nbsp;<link"			\
+	    "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+	done)
+	@(								\
+	for ident in $(STRUCTS) ; do					\
+	  id=`echo $$ident | tr _ - | sed s/v4l2-mpeg-vbi-ITV0/v4l2-mpeg-vbi-itv0-1/g` ; \
+	  echo "<indexentry><primaryie>struct&nbsp;<link"		\
+	    "linkend='$$id'>$$ident</link></primaryie></indexentry>" >>$@ ; \
+	done)
+	@(								\
+	echo "</index>") >>$@
diff --git a/Documentation/DocBook/dvb/frontend.h.xml b/Documentation/DocBook/dvb/frontend.h.xml
deleted file mode 100644
index d792f78..0000000
--- a/Documentation/DocBook/dvb/frontend.h.xml
+++ /dev/null
@@ -1,428 +0,0 @@
-<programlisting>
-/*
- * frontend.h
- *
- * Copyright (C) 2000 Marcus Metzler &lt;marcus@convergence.de&gt;
- *                  Ralph  Metzler &lt;ralph@convergence.de&gt;
- *                  Holger Waechtler &lt;holger@convergence.de&gt;
- *                  Andre Draszik &lt;ad@convergence.de&gt;
- *                  for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * 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 Lesser 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 _DVBFRONTEND_H_
-#define _DVBFRONTEND_H_
-
-#include &lt;linux/types.h&gt;
-
-typedef enum fe_type {
-        FE_QPSK,
-        FE_QAM,
-        FE_OFDM,
-        FE_ATSC
-} fe_type_t;
-
-
-typedef enum fe_caps {
-        FE_IS_STUPID                    = 0,
-        FE_CAN_INVERSION_AUTO           = 0x1,
-        FE_CAN_FEC_1_2                  = 0x2,
-        FE_CAN_FEC_2_3                  = 0x4,
-        FE_CAN_FEC_3_4                  = 0x8,
-        FE_CAN_FEC_4_5                  = 0x10,
-        FE_CAN_FEC_5_6                  = 0x20,
-        FE_CAN_FEC_6_7                  = 0x40,
-        FE_CAN_FEC_7_8                  = 0x80,
-        FE_CAN_FEC_8_9                  = 0x100,
-        FE_CAN_FEC_AUTO                 = 0x200,
-        FE_CAN_QPSK                     = 0x400,
-        FE_CAN_QAM_16                   = 0x800,
-        FE_CAN_QAM_32                   = 0x1000,
-        FE_CAN_QAM_64                   = 0x2000,
-        FE_CAN_QAM_128                  = 0x4000,
-        FE_CAN_QAM_256                  = 0x8000,
-        FE_CAN_QAM_AUTO                 = 0x10000,
-        FE_CAN_TRANSMISSION_MODE_AUTO   = 0x20000,
-        FE_CAN_BANDWIDTH_AUTO           = 0x40000,
-        FE_CAN_GUARD_INTERVAL_AUTO      = 0x80000,
-        FE_CAN_HIERARCHY_AUTO           = 0x100000,
-        FE_CAN_8VSB                     = 0x200000,
-        FE_CAN_16VSB                    = 0x400000,
-        FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
-        FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
-        FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
-        FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
-        FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */
-        FE_CAN_MUTE_TS                  = 0x80000000  /* frontend can stop spurious TS data output */
-} fe_caps_t;
-
-
-struct dvb_frontend_info {
-        char       name[128];
-        fe_type_t  type;
-        __u32      frequency_min;
-        __u32      frequency_max;
-        __u32      frequency_stepsize;
-        __u32      frequency_tolerance;
-        __u32      symbol_rate_min;
-        __u32      symbol_rate_max;
-        __u32      symbol_rate_tolerance;       /* ppm */
-        __u32      notifier_delay;              /* DEPRECATED */
-        fe_caps_t  caps;
-};
-
-
-/**
- *  Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
- *  the meaning of this struct...
- */
-struct dvb_diseqc_master_cmd {
-        __u8 msg [6];   /*  { framing, address, command, data [3] } */
-        __u8 msg_len;   /*  valid values are 3...6  */
-};
-
-
-struct dvb_diseqc_slave_reply {
-        __u8 msg [4];   /*  { framing, data [3] } */
-        __u8 msg_len;   /*  valid values are 0...4, 0 means no msg  */
-        int  timeout;   /*  return from ioctl after timeout ms with */
-};                      /*  errorcode when no message was received  */
-
-
-typedef enum fe_sec_voltage {
-        SEC_VOLTAGE_13,
-        SEC_VOLTAGE_18,
-        SEC_VOLTAGE_OFF
-} fe_sec_voltage_t;
-
-
-typedef enum fe_sec_tone_mode {
-        SEC_TONE_ON,
-        SEC_TONE_OFF
-} fe_sec_tone_mode_t;
-
-
-typedef enum fe_sec_mini_cmd {
-        SEC_MINI_A,
-        SEC_MINI_B
-} fe_sec_mini_cmd_t;
-
-
-typedef enum fe_status {
-        FE_HAS_SIGNAL   = 0x01,   /* found something above the noise level */
-        FE_HAS_CARRIER  = 0x02,   /* found a DVB signal  */
-        FE_HAS_VITERBI  = 0x04,   /* FEC is stable  */
-        FE_HAS_SYNC     = 0x08,   /* found sync bytes  */
-        FE_HAS_LOCK     = 0x10,   /* everything's working... */
-        FE_TIMEDOUT     = 0x20,   /* no lock within the last ~2 seconds */
-        FE_REINIT       = 0x40    /* frontend was reinitialized,  */
-} fe_status_t;                    /* application is recommended to reset */
-                                  /* DiSEqC, tone and parameters */
-
-typedef enum fe_spectral_inversion {
-        INVERSION_OFF,
-        INVERSION_ON,
-        INVERSION_AUTO
-} fe_spectral_inversion_t;
-
-
-typedef enum fe_code_rate {
-        FEC_NONE = 0,
-        FEC_1_2,
-        FEC_2_3,
-        FEC_3_4,
-        FEC_4_5,
-        FEC_5_6,
-        FEC_6_7,
-        FEC_7_8,
-        FEC_8_9,
-        FEC_AUTO,
-        FEC_3_5,
-        FEC_9_10,
-} fe_code_rate_t;
-
-
-typedef enum fe_modulation {
-        QPSK,
-        QAM_16,
-        QAM_32,
-        QAM_64,
-        QAM_128,
-        QAM_256,
-        QAM_AUTO,
-        VSB_8,
-        VSB_16,
-        PSK_8,
-        APSK_16,
-        APSK_32,
-        DQPSK,
-} fe_modulation_t;
-
-typedef enum fe_transmit_mode {
-        TRANSMISSION_MODE_2K,
-        TRANSMISSION_MODE_8K,
-        TRANSMISSION_MODE_AUTO,
-        TRANSMISSION_MODE_4K,
-        TRANSMISSION_MODE_1K,
-        TRANSMISSION_MODE_16K,
-        TRANSMISSION_MODE_32K,
-} fe_transmit_mode_t;
-
-typedef enum fe_bandwidth {
-        BANDWIDTH_8_MHZ,
-        BANDWIDTH_7_MHZ,
-        BANDWIDTH_6_MHZ,
-        BANDWIDTH_AUTO,
-        BANDWIDTH_5_MHZ,
-        BANDWIDTH_10_MHZ,
-        BANDWIDTH_1_712_MHZ,
-} fe_bandwidth_t;
-
-
-typedef enum fe_guard_interval {
-        GUARD_INTERVAL_1_32,
-        GUARD_INTERVAL_1_16,
-        GUARD_INTERVAL_1_8,
-        GUARD_INTERVAL_1_4,
-        GUARD_INTERVAL_AUTO,
-        GUARD_INTERVAL_1_128,
-        GUARD_INTERVAL_19_128,
-        GUARD_INTERVAL_19_256,
-} fe_guard_interval_t;
-
-
-typedef enum fe_hierarchy {
-        HIERARCHY_NONE,
-        HIERARCHY_1,
-        HIERARCHY_2,
-        HIERARCHY_4,
-        HIERARCHY_AUTO
-} fe_hierarchy_t;
-
-
-struct dvb_qpsk_parameters {
-        __u32           symbol_rate;  /* symbol rate in Symbols per second */
-        fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
-};
-
-struct dvb_qam_parameters {
-        __u32           symbol_rate; /* symbol rate in Symbols per second */
-        fe_code_rate_t  fec_inner;   /* forward error correction (see above) */
-        fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_vsb_parameters {
-        fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_ofdm_parameters {
-        fe_bandwidth_t      bandwidth;
-        fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
-        fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
-        fe_modulation_t     constellation; /* modulation type (see above) */
-        fe_transmit_mode_t  transmission_mode;
-        fe_guard_interval_t guard_interval;
-        fe_hierarchy_t      hierarchy_information;
-};
-
-
-struct dvb_frontend_parameters {
-        __u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
-                             /* intermediate frequency in kHz for QPSK */
-        fe_spectral_inversion_t inversion;
-        union {
-                struct dvb_qpsk_parameters qpsk;
-                struct dvb_qam_parameters  qam;
-                struct dvb_ofdm_parameters ofdm;
-                struct dvb_vsb_parameters vsb;
-        } u;
-};
-
-
-struct dvb_frontend_event {
-        fe_status_t status;
-        struct dvb_frontend_parameters parameters;
-};
-
-/* S2API Commands */
-#define DTV_UNDEFINED           0
-#define DTV_TUNE                1
-#define DTV_CLEAR               2
-#define DTV_FREQUENCY           3
-#define DTV_MODULATION          4
-#define DTV_BANDWIDTH_HZ        5
-#define DTV_INVERSION           6
-#define DTV_DISEQC_MASTER       7
-#define DTV_SYMBOL_RATE         8
-#define DTV_INNER_FEC           9
-#define DTV_VOLTAGE             10
-#define DTV_TONE                11
-#define DTV_PILOT               12
-#define DTV_ROLLOFF             13
-#define DTV_DISEQC_SLAVE_REPLY  14
-
-/* Basic enumeration set for querying unlimited capabilities */
-#define DTV_FE_CAPABILITY_COUNT 15
-#define DTV_FE_CAPABILITY       16
-#define DTV_DELIVERY_SYSTEM     17
-
-/* ISDB-T and ISDB-Tsb */
-#define DTV_ISDBT_PARTIAL_RECEPTION     18
-#define DTV_ISDBT_SOUND_BROADCASTING    19
-
-#define DTV_ISDBT_SB_SUBCHANNEL_ID      20
-#define DTV_ISDBT_SB_SEGMENT_IDX        21
-#define DTV_ISDBT_SB_SEGMENT_COUNT      22
-
-#define DTV_ISDBT_LAYERA_FEC                    23
-#define DTV_ISDBT_LAYERA_MODULATION             24
-#define DTV_ISDBT_LAYERA_SEGMENT_COUNT          25
-#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING      26
-
-#define DTV_ISDBT_LAYERB_FEC                    27
-#define DTV_ISDBT_LAYERB_MODULATION             28
-#define DTV_ISDBT_LAYERB_SEGMENT_COUNT          29
-#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING      30
-
-#define DTV_ISDBT_LAYERC_FEC                    31
-#define DTV_ISDBT_LAYERC_MODULATION             32
-#define DTV_ISDBT_LAYERC_SEGMENT_COUNT          33
-#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING      34
-
-#define DTV_API_VERSION         35
-
-#define DTV_CODE_RATE_HP        36
-#define DTV_CODE_RATE_LP        37
-#define DTV_GUARD_INTERVAL      38
-#define DTV_TRANSMISSION_MODE   39
-#define DTV_HIERARCHY           40
-
-#define DTV_ISDBT_LAYER_ENABLED 41
-
-#define DTV_ISDBS_TS_ID         42
-
-#define DTV_DVBT2_PLP_ID	43
-
-#define DTV_MAX_COMMAND                         DTV_DVBT2_PLP_ID
-
-typedef enum fe_pilot {
-        PILOT_ON,
-        PILOT_OFF,
-        PILOT_AUTO,
-} fe_pilot_t;
-
-typedef enum fe_rolloff {
-        ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
-        ROLLOFF_20,
-        ROLLOFF_25,
-        ROLLOFF_AUTO,
-} fe_rolloff_t;
-
-typedef enum fe_delivery_system {
-        SYS_UNDEFINED,
-        SYS_DVBC_ANNEX_AC,
-        SYS_DVBC_ANNEX_B,
-        SYS_DVBT,
-        SYS_DSS,
-        SYS_DVBS,
-        SYS_DVBS2,
-        SYS_DVBH,
-        SYS_ISDBT,
-        SYS_ISDBS,
-        SYS_ISDBC,
-        SYS_ATSC,
-        SYS_ATSCMH,
-        SYS_DMBTH,
-        SYS_CMMB,
-        SYS_DAB,
-        SYS_DVBT2,
-} fe_delivery_system_t;
-
-struct dtv_cmds_h {
-        char    *name;          /* A display name for debugging purposes */
-
-        __u32   cmd;            /* A unique ID */
-
-        /* Flags */
-        __u32   set:1;          /* Either a set or get property */
-        __u32   buffer:1;       /* Does this property use the buffer? */
-        __u32   reserved:30;    /* Align */
-};
-
-struct dtv_property {
-        __u32 cmd;
-        __u32 reserved[3];
-        union {
-                __u32 data;
-                struct {
-                        __u8 data[32];
-                        __u32 len;
-                        __u32 reserved1[3];
-                        void *reserved2;
-                } buffer;
-        } u;
-        int result;
-} __attribute__ ((packed));
-
-/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
-#define DTV_IOCTL_MAX_MSGS 64
-
-struct dtv_properties {
-        __u32 num;
-        struct dtv_property *props;
-};
-
-#define <link linkend="FE_GET_PROPERTY">FE_SET_PROPERTY</link>            _IOW('o', 82, struct dtv_properties)
-#define <link linkend="FE_GET_PROPERTY">FE_GET_PROPERTY</link>            _IOR('o', 83, struct dtv_properties)
-
-
-/**
- * When set, this flag will disable any zigzagging or other "normal" tuning
- * behaviour. Additionally, there will be no automatic monitoring of the lock
- * status, and hence no frontend events will be generated. If a frontend device
- * is closed, this flag will be automatically turned off when the device is
- * reopened read-write.
- */
-#define FE_TUNE_MODE_ONESHOT 0x01
-
-
-#define <link linkend="FE_GET_INFO">FE_GET_INFO</link>                _IOR('o', 61, struct dvb_frontend_info)
-
-#define <link linkend="FE_DISEQC_RESET_OVERLOAD">FE_DISEQC_RESET_OVERLOAD</link>   _IO('o', 62)
-#define <link linkend="FE_DISEQC_SEND_MASTER_CMD">FE_DISEQC_SEND_MASTER_CMD</link>  _IOW('o', 63, struct dvb_diseqc_master_cmd)
-#define <link linkend="FE_DISEQC_RECV_SLAVE_REPLY">FE_DISEQC_RECV_SLAVE_REPLY</link> _IOR('o', 64, struct dvb_diseqc_slave_reply)
-#define <link linkend="FE_DISEQC_SEND_BURST">FE_DISEQC_SEND_BURST</link>       _IO('o', 65)  /* fe_sec_mini_cmd_t */
-
-#define <link linkend="FE_SET_TONE">FE_SET_TONE</link>                _IO('o', 66)  /* fe_sec_tone_mode_t */
-#define <link linkend="FE_SET_VOLTAGE">FE_SET_VOLTAGE</link>             _IO('o', 67)  /* fe_sec_voltage_t */
-#define <link linkend="FE_ENABLE_HIGH_LNB_VOLTAGE">FE_ENABLE_HIGH_LNB_VOLTAGE</link> _IO('o', 68)  /* int */
-
-#define <link linkend="FE_READ_STATUS">FE_READ_STATUS</link>             _IOR('o', 69, fe_status_t)
-#define <link linkend="FE_READ_BER">FE_READ_BER</link>                _IOR('o', 70, __u32)
-#define <link linkend="FE_READ_SIGNAL_STRENGTH">FE_READ_SIGNAL_STRENGTH</link>    _IOR('o', 71, __u16)
-#define <link linkend="FE_READ_SNR">FE_READ_SNR</link>                _IOR('o', 72, __u16)
-#define <link linkend="FE_READ_UNCORRECTED_BLOCKS">FE_READ_UNCORRECTED_BLOCKS</link> _IOR('o', 73, __u32)
-
-#define <link linkend="FE_SET_FRONTEND">FE_SET_FRONTEND</link>            _IOW('o', 76, struct dvb_frontend_parameters)
-#define <link linkend="FE_GET_FRONTEND">FE_GET_FRONTEND</link>            _IOR('o', 77, struct dvb_frontend_parameters)
-#define <link linkend="FE_SET_FRONTEND_TUNE_MODE">FE_SET_FRONTEND_TUNE_MODE</link>  _IO('o', 81) /* unsigned int */
-#define <link linkend="FE_GET_EVENT">FE_GET_EVENT</link>               _IOR('o', 78, struct dvb_frontend_event)
-
-#define <link linkend="FE_DISHNETWORK_SEND_LEGACY_CMD">FE_DISHNETWORK_SEND_LEGACY_CMD</link> _IO('o', 80) /* unsigned int */
-
-#endif /*_DVBFRONTEND_H_*/
-</programlisting>
diff --git a/Documentation/DocBook/media-indices.tmpl b/Documentation/DocBook/media-indices.tmpl
deleted file mode 100644
index 78d6031..0000000
--- a/Documentation/DocBook/media-indices.tmpl
+++ /dev/null
@@ -1,89 +0,0 @@
-<!-- Generated file! Do not edit. -->
-
-<index><title>List of Types</title>
-<indexentry><primaryie><link linkend='v4l2-std-id'>v4l2_std_id</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-buf-type'>v4l2_buf_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-colorspace'>v4l2_colorspace</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-ctrl-type'>v4l2_ctrl_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-exposure-auto-type'>v4l2_exposure_auto_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-field'>v4l2_field</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-memory'>v4l2_memory</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-emphasis'>v4l2_mpeg_audio_emphasis</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-encoding'>v4l2_mpeg_audio_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l1-bitrate'>v4l2_mpeg_audio_l1_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l2-bitrate'>v4l2_mpeg_audio_l2_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-l3-bitrate'>v4l2_mpeg_audio_l3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-mode'>v4l2_mpeg_audio_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-mode-extension'>v4l2_mpeg_audio_mode_extension</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-audio-sampling-freq'>v4l2_mpeg_audio_sampling_freq</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='chroma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='luma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-median-filter-type'>v4l2_mpeg_cx2341x_video_median_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-spatial-filter-mode'>v4l2_mpeg_cx2341x_video_spatial_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-cx2341x-video-temporal-filter-mode'>v4l2_mpeg_cx2341x_video_temporal_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-stream-type'>v4l2_mpeg_stream_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-stream-vbi-fmt'>v4l2_mpeg_stream_vbi_fmt</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-aspect'>v4l2_mpeg_video_aspect</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-bitrate-mode'>v4l2_mpeg_video_bitrate_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-priority'>v4l2_priority</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-tuner-type'>v4l2_tuner_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audio'>v4l2_audio</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-clip'>v4l2_clip</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-control'>v4l2_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-crop'>v4l2_crop</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-cropcap'>v4l2_cropcap</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-match'>v4l2_dbg_match</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dbg-register'>v4l2_dbg_register</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-preset'>v4l2_dv_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-dv-timings'>v4l2_dv_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx'>v4l2_enc_idx</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-ext-control'>v4l2_ext_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-ext-controls'>v4l2_ext_controls</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-format'>v4l2_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-fract'>v4l2_fract</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-framebuffer'>v4l2_framebuffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frequency'>v4l2_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmival-stepwise'>v4l2_frmival_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmivalenum'>v4l2_frmivalenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsize-discrete'>v4l2_frmsize_discrete</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsize-stepwise'>v4l2_frmsize_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-frmsizeenum'>v4l2_frmsizeenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-input'>v4l2_input</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-modulator'>v4l2_modulator</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-output'>v4l2_output</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-outputparm'>v4l2_outputparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-pix-format'>v4l2_pix_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-queryctrl'>v4l2_queryctrl</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-querymenu'>v4l2_querymenu</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-rect'>v4l2_rect</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-requestbuffers'>v4l2_requestbuffers</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-standard'>v4l2_standard</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-streamparm'>v4l2_streamparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-timecode'>v4l2_timecode</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-tuner'>v4l2_tuner</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-vbi-format'>v4l2_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct&nbsp;<link linkend='v4l2-window'>v4l2_window</link></primaryie></indexentry>
-</index>
diff --git a/Documentation/DocBook/v4l/videodev2.h.xml b/Documentation/DocBook/v4l/videodev2.h.xml
deleted file mode 100644
index c50536a..0000000
--- a/Documentation/DocBook/v4l/videodev2.h.xml
+++ /dev/null
@@ -1,1946 +0,0 @@
-<programlisting>
-/*
- *  Video for Linux Two header file
- *
- *  Copyright (C) 1999-2007 the contributors
- *
- *  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; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  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.
- *
- *  Alternatively you can redistribute this file under the terms of the
- *  BSD license as stated below:
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in
- *     the documentation and/or other materials provided with the
- *     distribution.
- *  3. The names of its contributors may not be used to endorse or promote
- *     products derived from this software without specific prior written
- *     permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *      Header file for v4l or V4L2 drivers and applications
- * with public API.
- * All kernel-specific stuff were moved to media/v4l2-dev.h, so
- * no #if __KERNEL tests are allowed here
- *
- *      See http://linuxtv.org for more info
- *
- *      Author: Bill Dirks &lt;bill@thedirks.org&gt;
- *              Justin Schoeman
- *              Hans Verkuil &lt;hverkuil@xs4all.nl&gt;
- *              et al.
- */
-#ifndef __LINUX_VIDEODEV2_H
-#define __LINUX_VIDEODEV2_H
-
-#ifdef __KERNEL__
-#include &lt;linux/time.h&gt;     /* need struct timeval */
-#else
-#include &lt;sys/time.h&gt;
-#endif
-#include &lt;linux/compiler.h&gt;
-#include &lt;linux/ioctl.h&gt;
-#include &lt;linux/types.h&gt;
-
-/*
- * Common stuff for both V4L1 and V4L2
- * Moved from videodev.h
- */
-#define VIDEO_MAX_FRAME               32
-#define VIDEO_MAX_PLANES               8
-
-#ifndef __KERNEL__
-
-/* These defines are V4L1 specific and should not be used with the V4L2 API!
-   They will be removed from this header in the future. */
-
-#define VID_TYPE_CAPTURE        1       /* Can capture */
-#define VID_TYPE_TUNER          2       /* Can tune */
-#define VID_TYPE_TELETEXT       4       /* Does teletext */
-#define VID_TYPE_OVERLAY        8       /* Overlay onto frame buffer */
-#define VID_TYPE_CHROMAKEY      16      /* Overlay by chromakey */
-#define VID_TYPE_CLIPPING       32      /* Can clip */
-#define VID_TYPE_FRAMERAM       64      /* Uses the frame buffer memory */
-#define VID_TYPE_SCALES         128     /* Scalable */
-#define VID_TYPE_MONOCHROME     256     /* Monochrome only */
-#define VID_TYPE_SUBCAPTURE     512     /* Can capture subareas of the image */
-#define VID_TYPE_MPEG_DECODER   1024    /* Can decode MPEG streams */
-#define VID_TYPE_MPEG_ENCODER   2048    /* Can encode MPEG streams */
-#define VID_TYPE_MJPEG_DECODER  4096    /* Can decode MJPEG streams */
-#define VID_TYPE_MJPEG_ENCODER  8192    /* Can encode MJPEG streams */
-#endif
-
-/*
- *      M I S C E L L A N E O U S
- */
-
-/*  Four-character-code (FOURCC) */
-#define v4l2_fourcc(a, b, c, d)\
-        ((__u32)(a) | ((__u32)(b) &lt;&lt; 8) | ((__u32)(c) &lt;&lt; 16) | ((__u32)(d) &lt;&lt; 24))
-
-/*
- *      E N U M S
- */
-enum <link linkend="v4l2-field">v4l2_field</link> {
-        V4L2_FIELD_ANY           = 0, /* driver can choose from none,
-                                         top, bottom, interlaced
-                                         depending on whatever it thinks
-                                         is approximate ... */
-        V4L2_FIELD_NONE          = 1, /* this device has no fields ... */
-        V4L2_FIELD_TOP           = 2, /* top field only */
-        V4L2_FIELD_BOTTOM        = 3, /* bottom field only */
-        V4L2_FIELD_INTERLACED    = 4, /* both fields interlaced */
-        V4L2_FIELD_SEQ_TB        = 5, /* both fields sequential into one
-                                         buffer, top-bottom order */
-        V4L2_FIELD_SEQ_BT        = 6, /* same as above + bottom-top order */
-        V4L2_FIELD_ALTERNATE     = 7, /* both fields alternating into
-                                         separate buffers */
-        V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field
-                                         first and the top field is
-                                         transmitted first */
-        V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field
-                                         first and the bottom field is
-                                         transmitted first */
-};
-#define V4L2_FIELD_HAS_TOP(field)       \
-        ((field) == V4L2_FIELD_TOP      ||\
-         (field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB   ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-#define V4L2_FIELD_HAS_BOTTOM(field)    \
-        ((field) == V4L2_FIELD_BOTTOM   ||\
-         (field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB   ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-#define V4L2_FIELD_HAS_BOTH(field)      \
-        ((field) == V4L2_FIELD_INTERLACED ||\
-         (field) == V4L2_FIELD_INTERLACED_TB ||\
-         (field) == V4L2_FIELD_INTERLACED_BT ||\
-         (field) == V4L2_FIELD_SEQ_TB ||\
-         (field) == V4L2_FIELD_SEQ_BT)
-
-enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> {
-        V4L2_BUF_TYPE_VIDEO_CAPTURE        = 1,
-        V4L2_BUF_TYPE_VIDEO_OUTPUT         = 2,
-        V4L2_BUF_TYPE_VIDEO_OVERLAY        = 3,
-        V4L2_BUF_TYPE_VBI_CAPTURE          = 4,
-        V4L2_BUF_TYPE_VBI_OUTPUT           = 5,
-        V4L2_BUF_TYPE_SLICED_VBI_CAPTURE   = 6,
-        V4L2_BUF_TYPE_SLICED_VBI_OUTPUT    = 7,
-#if 1
-        /* Experimental */
-        V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
-#endif
-        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
-        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
-        V4L2_BUF_TYPE_PRIVATE              = 0x80,
-};
-
-#define V4L2_TYPE_IS_MULTIPLANAR(type)                  \
-        ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE   \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-
-#define V4L2_TYPE_IS_OUTPUT(type)                               \
-        ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT                   \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE         \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY               \
-         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY        \
-         || (type) == V4L2_BUF_TYPE_VBI_OUTPUT                  \
-         || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
-
-enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
-        V4L2_TUNER_RADIO             = 1,
-        V4L2_TUNER_ANALOG_TV         = 2,
-        V4L2_TUNER_DIGITAL_TV        = 3,
-};
-
-enum <link linkend="v4l2-memory">v4l2_memory</link> {
-        V4L2_MEMORY_MMAP             = 1,
-        V4L2_MEMORY_USERPTR          = 2,
-        V4L2_MEMORY_OVERLAY          = 3,
-};
-
-/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
-enum <link linkend="v4l2-colorspace">v4l2_colorspace</link> {
-        /* ITU-R 601 -- broadcast NTSC/PAL */
-        V4L2_COLORSPACE_SMPTE170M     = 1,
-
-        /* 1125-Line (US) HDTV */
-        V4L2_COLORSPACE_SMPTE240M     = 2,
-
-        /* HD and modern captures. */
-        V4L2_COLORSPACE_REC709        = 3,
-
-        /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
-        V4L2_COLORSPACE_BT878         = 4,
-
-        /* These should be useful.  Assume 601 extents. */
-        V4L2_COLORSPACE_470_SYSTEM_M  = 5,
-        V4L2_COLORSPACE_470_SYSTEM_BG = 6,
-
-        /* I know there will be cameras that send this.  So, this is
-         * unspecified chromaticities and full 0-255 on each of the
-         * Y'CbCr components
-         */
-        V4L2_COLORSPACE_JPEG          = 7,
-
-        /* For RGB colourspaces, this is probably a good start. */
-        V4L2_COLORSPACE_SRGB          = 8,
-};
-
-enum <link linkend="v4l2-priority">v4l2_priority</link> {
-        V4L2_PRIORITY_UNSET       = 0,  /* not initialized */
-        V4L2_PRIORITY_BACKGROUND  = 1,
-        V4L2_PRIORITY_INTERACTIVE = 2,
-        V4L2_PRIORITY_RECORD      = 3,
-        V4L2_PRIORITY_DEFAULT     = V4L2_PRIORITY_INTERACTIVE,
-};
-
-struct <link linkend="v4l2-rect">v4l2_rect</link> {
-        __s32   left;
-        __s32   top;
-        __s32   width;
-        __s32   height;
-};
-
-struct <link linkend="v4l2-fract">v4l2_fract</link> {
-        __u32   numerator;
-        __u32   denominator;
-};
-
-/*
- *      D R I V E R   C A P A B I L I T I E S
- */
-struct <link linkend="v4l2-capability">v4l2_capability</link> {
-        __u8    driver[16];     /* i.e.ie; "bttv" */
-        __u8    card[32];       /* i.e.ie; "Hauppauge WinTV" */
-        __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
-        __u32   version;        /* should use KERNEL_VERSION() */
-        __u32   capabilities;   /* Device capabilities */
-        __u32   reserved[4];
-};
-
-/* Values for 'capabilities' field */
-#define V4L2_CAP_VIDEO_CAPTURE          0x00000001  /* Is a video capture device */
-#define V4L2_CAP_VIDEO_OUTPUT           0x00000002  /* Is a video output device */
-#define V4L2_CAP_VIDEO_OVERLAY          0x00000004  /* Can do video overlay */
-#define V4L2_CAP_VBI_CAPTURE            0x00000010  /* Is a raw VBI capture device */
-#define V4L2_CAP_VBI_OUTPUT             0x00000020  /* Is a raw VBI output device */
-#define V4L2_CAP_SLICED_VBI_CAPTURE     0x00000040  /* Is a sliced VBI capture device */
-#define V4L2_CAP_SLICED_VBI_OUTPUT      0x00000080  /* Is a sliced VBI output device */
-#define V4L2_CAP_RDS_CAPTURE            0x00000100  /* RDS data capture */
-#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY   0x00000200  /* Can do video output overlay */
-#define V4L2_CAP_HW_FREQ_SEEK           0x00000400  /* Can do hardware frequency seek  */
-#define V4L2_CAP_RDS_OUTPUT             0x00000800  /* Is an RDS encoder */
-
-/* Is a video capture device that supports multiplanar formats */
-#define V4L2_CAP_VIDEO_CAPTURE_MPLANE   0x00001000
-/* Is a video output device that supports multiplanar formats */
-#define V4L2_CAP_VIDEO_OUTPUT_MPLANE    0x00002000
-
-#define V4L2_CAP_TUNER                  0x00010000  /* has a tuner */
-#define V4L2_CAP_AUDIO                  0x00020000  /* has audio support */
-#define V4L2_CAP_RADIO                  0x00040000  /* is a radio device */
-#define V4L2_CAP_MODULATOR              0x00080000  /* has a modulator */
-
-#define V4L2_CAP_READWRITE              0x01000000  /* read/write systemcalls */
-#define V4L2_CAP_ASYNCIO                0x02000000  /* async I/O */
-#define V4L2_CAP_STREAMING              0x04000000  /* streaming I/O ioctls */
-
-/*
- *      V I D E O   I M A G E   F O R M A T
- */
-struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
-        __u32                   width;
-        __u32                   height;
-        __u32                   pixelformat;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        __u32                   bytesperline;   /* for padding, zero if unused */
-        __u32                   sizeimage;
-        enum <link linkend="v4l2-colorspace">v4l2_colorspace</link>    colorspace;
-        __u32                   priv;           /* private data, depends on pixelformat */
-};
-
-/*      Pixel format         FOURCC                          depth  Description  */
-
-/* RGB formats */
-#define <link linkend="V4L2-PIX-FMT-RGB332">V4L2_PIX_FMT_RGB332</link>  v4l2_fourcc('R', 'G', 'B', '1') /*  8  RGB-3-3-2     */
-#define <link linkend="V4L2-PIX-FMT-RGB444">V4L2_PIX_FMT_RGB444</link>  v4l2_fourcc('R', '4', '4', '4') /* 16  xxxxrrrr ggggbbbb */
-#define <link linkend="V4L2-PIX-FMT-RGB555">V4L2_PIX_FMT_RGB555</link>  v4l2_fourcc('R', 'G', 'B', 'O') /* 16  RGB-5-5-5     */
-#define <link linkend="V4L2-PIX-FMT-RGB565">V4L2_PIX_FMT_RGB565</link>  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
-#define <link linkend="V4L2-PIX-FMT-RGB555X">V4L2_PIX_FMT_RGB555X</link> v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
-#define <link linkend="V4L2-PIX-FMT-RGB565X">V4L2_PIX_FMT_RGB565X</link> v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
-#define <link linkend="V4L2-PIX-FMT-BGR666">V4L2_PIX_FMT_BGR666</link>  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6     */
-#define <link linkend="V4L2-PIX-FMT-BGR24">V4L2_PIX_FMT_BGR24</link>   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
-#define <link linkend="V4L2-PIX-FMT-RGB24">V4L2_PIX_FMT_RGB24</link>   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
-#define <link linkend="V4L2-PIX-FMT-BGR32">V4L2_PIX_FMT_BGR32</link>   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
-#define <link linkend="V4L2-PIX-FMT-RGB32">V4L2_PIX_FMT_RGB32</link>   v4l2_fourcc('R', 'G', 'B', '4') /* 32  RGB-8-8-8-8   */
-
-/* Grey formats */
-#define <link linkend="V4L2-PIX-FMT-GREY">V4L2_PIX_FMT_GREY</link>    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y4">V4L2_PIX_FMT_Y4</link>      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y6">V4L2_PIX_FMT_Y6</link>      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link>     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
-#define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
-
-/* Grey bit-packed formats */
-#define <link linkend="V4L2-PIX-FMT-Y10BPACK">V4L2_PIX_FMT_Y10BPACK</link>    v4l2_fourcc('Y', '1', '0', 'B') /* 10  Greyscale bit-packed */
-
-/* Palette formats */
-#define <link linkend="V4L2-PIX-FMT-PAL8">V4L2_PIX_FMT_PAL8</link>    v4l2_fourcc('P', 'A', 'L', '8') /*  8  8-bit palette */
-
-/* Luminance+Chrominance formats */
-#define <link linkend="V4L2-PIX-FMT-YVU410">V4L2_PIX_FMT_YVU410</link>  v4l2_fourcc('Y', 'V', 'U', '9') /*  9  YVU 4:1:0     */
-#define <link linkend="V4L2-PIX-FMT-YVU420">V4L2_PIX_FMT_YVU420</link>  v4l2_fourcc('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
-#define <link linkend="V4L2-PIX-FMT-YUYV">V4L2_PIX_FMT_YUYV</link>    v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YYUV">V4L2_PIX_FMT_YYUV</link>    v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YVYU">V4L2_PIX_FMT_YVYU</link>    v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
-#define <link linkend="V4L2-PIX-FMT-UYVY">V4L2_PIX_FMT_UYVY</link>    v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-VYUY">V4L2_PIX_FMT_VYUY</link>    v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16  YUV 4:2:2     */
-#define <link linkend="V4L2-PIX-FMT-YUV422P">V4L2_PIX_FMT_YUV422P</link> v4l2_fourcc('4', '2', '2', 'P') /* 16  YVU422 planar */
-#define <link linkend="V4L2-PIX-FMT-YUV411P">V4L2_PIX_FMT_YUV411P</link> v4l2_fourcc('4', '1', '1', 'P') /* 16  YVU411 planar */
-#define <link linkend="V4L2-PIX-FMT-Y41P">V4L2_PIX_FMT_Y41P</link>    v4l2_fourcc('Y', '4', '1', 'P') /* 12  YUV 4:1:1     */
-#define <link linkend="V4L2-PIX-FMT-YUV444">V4L2_PIX_FMT_YUV444</link>  v4l2_fourcc('Y', '4', '4', '4') /* 16  xxxxyyyy uuuuvvvv */
-#define <link linkend="V4L2-PIX-FMT-YUV555">V4L2_PIX_FMT_YUV555</link>  v4l2_fourcc('Y', 'U', 'V', 'O') /* 16  YUV-5-5-5     */
-#define <link linkend="V4L2-PIX-FMT-YUV565">V4L2_PIX_FMT_YUV565</link>  v4l2_fourcc('Y', 'U', 'V', 'P') /* 16  YUV-5-6-5     */
-#define <link linkend="V4L2-PIX-FMT-YUV32">V4L2_PIX_FMT_YUV32</link>   v4l2_fourcc('Y', 'U', 'V', '4') /* 32  YUV-8-8-8-8   */
-#define <link linkend="V4L2-PIX-FMT-YUV410">V4L2_PIX_FMT_YUV410</link>  v4l2_fourcc('Y', 'U', 'V', '9') /*  9  YUV 4:1:0     */
-#define <link linkend="V4L2-PIX-FMT-YUV420">V4L2_PIX_FMT_YUV420</link>  v4l2_fourcc('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
-#define <link linkend="V4L2-PIX-FMT-HI240">V4L2_PIX_FMT_HI240</link>   v4l2_fourcc('H', 'I', '2', '4') /*  8  8-bit color   */
-#define <link linkend="V4L2-PIX-FMT-HM12">V4L2_PIX_FMT_HM12</link>    v4l2_fourcc('H', 'M', '1', '2') /*  8  YUV 4:2:0 16x16 macroblocks */
-#define <link linkend="V4L2-PIX-FMT-M420">V4L2_PIX_FMT_M420</link>    v4l2_fourcc('M', '4', '2', '0') /* 12  YUV 4:2:0 2 lines y, 1 line uv interleaved */
-
-/* two planes -- one Y, one Cr + Cb interleaved  */
-#define <link linkend="V4L2-PIX-FMT-NV12">V4L2_PIX_FMT_NV12</link>    v4l2_fourcc('N', 'V', '1', '2') /* 12  Y/CbCr 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV21">V4L2_PIX_FMT_NV21</link>    v4l2_fourcc('N', 'V', '2', '1') /* 12  Y/CrCb 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV16">V4L2_PIX_FMT_NV16</link>    v4l2_fourcc('N', 'V', '1', '6') /* 16  Y/CbCr 4:2:2  */
-#define <link linkend="V4L2-PIX-FMT-NV61">V4L2_PIX_FMT_NV61</link>    v4l2_fourcc('N', 'V', '6', '1') /* 16  Y/CrCb 4:2:2  */
-
-/* two non contiguous planes - one Y, one Cr + Cb interleaved  */
-#define <link linkend="V4L2-PIX-FMT-NV12M">V4L2_PIX_FMT_NV12M</link>   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
-#define <link linkend="V4L2-PIX-FMT-NV12MT">V4L2_PIX_FMT_NV12MT</link>  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
-
-/* three non contiguous planes - Y, Cb, Cr */
-#define <link linkend="V4L2-PIX-FMT-YUV420M">V4L2_PIX_FMT_YUV420M</link> v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
-
-/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
-#define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link>  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
-#define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link>  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
-#define <link linkend="V4L2-PIX-FMT-SGRBG8">V4L2_PIX_FMT_SGRBG8</link>  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
-#define <link linkend="V4L2-PIX-FMT-SRGGB8">V4L2_PIX_FMT_SRGGB8</link>  v4l2_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
-#define <link linkend="V4L2-PIX-FMT-SBGGR10">V4L2_PIX_FMT_SBGGR10</link> v4l2_fourcc('B', 'G', '1', '0') /* 10  BGBG.. GRGR.. */
-#define <link linkend="V4L2-PIX-FMT-SGBRG10">V4L2_PIX_FMT_SGBRG10</link> v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
-#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
-#define <link linkend="V4L2-PIX-FMT-SRGGB10">V4L2_PIX_FMT_SRGGB10</link> v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
-        /* 10bit raw bayer DPCM compressed to 8 bits */
-#define <link linkend="V4L2-PIX-FMT-SGRBG10DPCM8">V4L2_PIX_FMT_SGRBG10DPCM8</link> v4l2_fourcc('B', 'D', '1', '0')
-        /*
-         * 10bit raw bayer, expanded to 16 bits
-         * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
-         */
-#define <link linkend="V4L2-PIX-FMT-SBGGR16">V4L2_PIX_FMT_SBGGR16</link> v4l2_fourcc('B', 'Y', 'R', '2') /* 16  BGBG.. GRGR.. */
-
-/* compressed formats */
-#define <link linkend="V4L2-PIX-FMT-MJPEG">V4L2_PIX_FMT_MJPEG</link>    v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG   */
-#define <link linkend="V4L2-PIX-FMT-JPEG">V4L2_PIX_FMT_JPEG</link>     v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG     */
-#define <link linkend="V4L2-PIX-FMT-DV">V4L2_PIX_FMT_DV</link>       v4l2_fourcc('d', 'v', 's', 'd') /* 1394          */
-#define <link linkend="V4L2-PIX-FMT-MPEG">V4L2_PIX_FMT_MPEG</link>     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
-
-/*  Vendor-specific formats   */
-#define <link linkend="V4L2-PIX-FMT-CPIA1">V4L2_PIX_FMT_CPIA1</link>    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
-#define <link linkend="V4L2-PIX-FMT-WNVA">V4L2_PIX_FMT_WNVA</link>     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
-#define <link linkend="V4L2-PIX-FMT-SN9C10X">V4L2_PIX_FMT_SN9C10X</link>  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
-#define <link linkend="V4L2-PIX-FMT-SN9C20X-I420">V4L2_PIX_FMT_SN9C20X_I420</link> v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
-#define <link linkend="V4L2-PIX-FMT-PWC1">V4L2_PIX_FMT_PWC1</link>     v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
-#define <link linkend="V4L2-PIX-FMT-PWC2">V4L2_PIX_FMT_PWC2</link>     v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
-#define <link linkend="V4L2-PIX-FMT-ET61X251">V4L2_PIX_FMT_ET61X251</link> v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
-#define <link linkend="V4L2-PIX-FMT-SPCA501">V4L2_PIX_FMT_SPCA501</link>  v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA505">V4L2_PIX_FMT_SPCA505</link>  v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA508">V4L2_PIX_FMT_SPCA508</link>  v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
-#define <link linkend="V4L2-PIX-FMT-SPCA561">V4L2_PIX_FMT_SPCA561</link>  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
-#define <link linkend="V4L2-PIX-FMT-PAC207">V4L2_PIX_FMT_PAC207</link>   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
-#define <link linkend="V4L2-PIX-FMT-MR97310A">V4L2_PIX_FMT_MR97310A</link> v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
-#define <link linkend="V4L2-PIX-FMT-SN9C2028">V4L2_PIX_FMT_SN9C2028</link> v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
-#define <link linkend="V4L2-PIX-FMT-SQ905C">V4L2_PIX_FMT_SQ905C</link>   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
-#define <link linkend="V4L2-PIX-FMT-PJPG">V4L2_PIX_FMT_PJPG</link>     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
-#define <link linkend="V4L2-PIX-FMT-OV511">V4L2_PIX_FMT_OV511</link>    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
-#define <link linkend="V4L2-PIX-FMT-OV518">V4L2_PIX_FMT_OV518</link>    v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
-#define <link linkend="V4L2-PIX-FMT-STV0680">V4L2_PIX_FMT_STV0680</link>  v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
-#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link>   v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
-#define <link linkend="V4L2-PIX-FMT-CIT-YYVYUY">V4L2_PIX_FMT_CIT_YYVYUY</link> v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
-#define <link linkend="V4L2-PIX-FMT-KONICA420">V4L2_PIX_FMT_KONICA420</link>  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
-
-/*
- *      F O R M A T   E N U M E R A T I O N
- */
-struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link> {
-        __u32               index;             /* Format number      */
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>  type;              /* buffer type        */
-        __u32               flags;
-        __u8                description[32];   /* Description string */
-        __u32               pixelformat;       /* Format fourcc      */
-        __u32               reserved[4];
-};
-
-#define V4L2_FMT_FLAG_COMPRESSED 0x0001
-#define V4L2_FMT_FLAG_EMULATED   0x0002
-
-#if 1
-        /* Experimental Frame Size and frame rate enumeration */
-/*
- *      F R A M E   S I Z E   E N U M E R A T I O N
- */
-enum <link linkend="v4l2-frmsizetypes">v4l2_frmsizetypes</link> {
-        V4L2_FRMSIZE_TYPE_DISCRETE      = 1,
-        V4L2_FRMSIZE_TYPE_CONTINUOUS    = 2,
-        V4L2_FRMSIZE_TYPE_STEPWISE      = 3,
-};
-
-struct <link linkend="v4l2-frmsize-discrete">v4l2_frmsize_discrete</link> {
-        __u32                   width;          /* Frame width [pixel] */
-        __u32                   height;         /* Frame height [pixel] */
-};
-
-struct <link linkend="v4l2-frmsize-stepwise">v4l2_frmsize_stepwise</link> {
-        __u32                   min_width;      /* Minimum frame width [pixel] */
-        __u32                   max_width;      /* Maximum frame width [pixel] */
-        __u32                   step_width;     /* Frame width step size [pixel] */
-        __u32                   min_height;     /* Minimum frame height [pixel] */
-        __u32                   max_height;     /* Maximum frame height [pixel] */
-        __u32                   step_height;    /* Frame height step size [pixel] */
-};
-
-struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link> {
-        __u32                   index;          /* Frame size number */
-        __u32                   pixel_format;   /* Pixel format */
-        __u32                   type;           /* Frame size type the device supports. */
-
-        union {                                 /* Frame size */
-                struct <link linkend="v4l2-frmsize-discrete">v4l2_frmsize_discrete</link>    discrete;
-                struct <link linkend="v4l2-frmsize-stepwise">v4l2_frmsize_stepwise</link>    stepwise;
-        };
-
-        __u32   reserved[2];                    /* Reserved space for future use */
-};
-
-/*
- *      F R A M E   R A T E   E N U M E R A T I O N
- */
-enum <link linkend="v4l2-frmivaltypes">v4l2_frmivaltypes</link> {
-        V4L2_FRMIVAL_TYPE_DISCRETE      = 1,
-        V4L2_FRMIVAL_TYPE_CONTINUOUS    = 2,
-        V4L2_FRMIVAL_TYPE_STEPWISE      = 3,
-};
-
-struct <link linkend="v4l2-frmival-stepwise">v4l2_frmival_stepwise</link> {
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       min;            /* Minimum frame interval [s] */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       max;            /* Maximum frame interval [s] */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       step;           /* Frame interval step size [s] */
-};
-
-struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link> {
-        __u32                   index;          /* Frame format index */
-        __u32                   pixel_format;   /* Pixel format */
-        __u32                   width;          /* Frame width */
-        __u32                   height;         /* Frame height */
-        __u32                   type;           /* Frame interval type the device supports. */
-
-        union {                                 /* Frame interval */
-                struct <link linkend="v4l2-fract">v4l2_fract</link>               discrete;
-                struct <link linkend="v4l2-frmival-stepwise">v4l2_frmival_stepwise</link>    stepwise;
-        };
-
-        __u32   reserved[2];                    /* Reserved space for future use */
-};
-#endif
-
-/*
- *      T I M E C O D E
- */
-struct <link linkend="v4l2-timecode">v4l2_timecode</link> {
-        __u32   type;
-        __u32   flags;
-        __u8    frames;
-        __u8    seconds;
-        __u8    minutes;
-        __u8    hours;
-        __u8    userbits[4];
-};
-
-/*  Type  */
-#define V4L2_TC_TYPE_24FPS              1
-#define V4L2_TC_TYPE_25FPS              2
-#define V4L2_TC_TYPE_30FPS              3
-#define V4L2_TC_TYPE_50FPS              4
-#define V4L2_TC_TYPE_60FPS              5
-
-/*  Flags  */
-#define V4L2_TC_FLAG_DROPFRAME          0x0001 /* "drop-frame" mode */
-#define V4L2_TC_FLAG_COLORFRAME         0x0002
-#define V4L2_TC_USERBITS_field          0x000C
-#define V4L2_TC_USERBITS_USERDEFINED    0x0000
-#define V4L2_TC_USERBITS_8BITCHARS      0x0008
-/* The above is based on SMPTE timecodes */
-
-struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link> {
-        int quality;
-
-        int  APPn;              /* Number of APP segment to be written,
-                                 * must be 0..15 */
-        int  APP_len;           /* Length of data in JPEG APPn segment */
-        char APP_data[60];      /* Data in the JPEG APPn segment. */
-
-        int  COM_len;           /* Length of data in JPEG COM segment */
-        char COM_data[60];      /* Data in JPEG COM segment */
-
-        __u32 jpeg_markers;     /* Which markers should go into the JPEG
-                                 * output. Unless you exactly know what
-                                 * you do, leave them untouched.
-                                 * Inluding less markers will make the
-                                 * resulting code smaller, but there will
-                                 * be fewer applications which can read it.
-                                 * The presence of the APP and COM marker
-                                 * is influenced by APP_len and COM_len
-                                 * ONLY, not by this property! */
-
-#define V4L2_JPEG_MARKER_DHT (1&lt;&lt;3)    /* Define Huffman Tables */
-#define V4L2_JPEG_MARKER_DQT (1&lt;&lt;4)    /* Define Quantization Tables */
-#define V4L2_JPEG_MARKER_DRI (1&lt;&lt;5)    /* Define Restart Interval */
-#define V4L2_JPEG_MARKER_COM (1&lt;&lt;6)    /* Comment segment */
-#define V4L2_JPEG_MARKER_APP (1&lt;&lt;7)    /* App segment, driver will
-                                        * allways use APP0 */
-};
-
-/*
- *      M E M O R Y - M A P P I N G   B U F F E R S
- */
-struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link> {
-        __u32                   count;
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        enum <link linkend="v4l2-memory">v4l2_memory</link>        memory;
-        __u32                   reserved[2];
-};
-
-/**
- * struct <link linkend="v4l2-plane">v4l2_plane</link> - plane info for multi-planar buffers
- * @bytesused:          number of bytes occupied by data in the plane (payload)
- * @length:             size of this plane (NOT the payload) in bytes
- * @mem_offset:         when memory in the associated struct <link linkend="v4l2-buffer">v4l2_buffer</link> is
- *                      V4L2_MEMORY_MMAP, equals the offset from the start of
- *                      the device memory for this plane (or is a "cookie" that
- *                      should be passed to mmap() called on the video node)
- * @userptr:            when memory is V4L2_MEMORY_USERPTR, a userspace pointer
- *                      pointing to this plane
- * @data_offset:        offset in the plane to the start of data; usually 0,
- *                      unless there is a header in front of the data
- *
- * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
- * with two planes can have one plane for Y, and another for interleaved CbCr
- * components. Each plane can reside in a separate memory buffer, or even in
- * a completely separate memory node (e.g. in embedded devices).
- */
-struct <link linkend="v4l2-plane">v4l2_plane</link> {
-        __u32                   bytesused;
-        __u32                   length;
-        union {
-                __u32           mem_offset;
-                unsigned long   userptr;
-        } m;
-        __u32                   data_offset;
-        __u32                   reserved[11];
-};
-
-/**
- * struct <link linkend="v4l2-buffer">v4l2_buffer</link> - video buffer info
- * @index:      id number of the buffer
- * @type:       buffer type (type == *_MPLANE for multiplanar buffers)
- * @bytesused:  number of bytes occupied by data in the buffer (payload);
- *              unused (set to 0) for multiplanar buffers
- * @flags:      buffer informational flags
- * @field:      field order of the image in the buffer
- * @timestamp:  frame timestamp
- * @timecode:   frame timecode
- * @sequence:   sequence count of this frame
- * @memory:     the method, in which the actual video data is passed
- * @offset:     for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
- *              offset from the start of the device memory for this plane,
- *              (or a "cookie" that should be passed to mmap() as offset)
- * @userptr:    for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
- *              a userspace pointer pointing to this buffer
- * @planes:     for multiplanar buffers; userspace pointer to the array of plane
- *              info structs for this buffer
- * @length:     size in bytes of the buffer (NOT its payload) for single-plane
- *              buffers (when type != *_MPLANE); number of elements in the
- *              planes array for multi-plane buffers
- * @input:      input number from which the video data has has been captured
- *
- * Contains data exchanged by application and driver using one of the Streaming
- * I/O methods.
- */
-struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
-        __u32                   index;
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        __u32                   bytesused;
-        __u32                   flags;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        struct timeval          timestamp;
-        struct <link linkend="v4l2-timecode">v4l2_timecode</link>    timecode;
-        __u32                   sequence;
-
-        /* memory location */
-        enum <link linkend="v4l2-memory">v4l2_memory</link>        memory;
-        union {
-                __u32           offset;
-                unsigned long   userptr;
-                struct <link linkend="v4l2-plane">v4l2_plane</link> *planes;
-        } m;
-        __u32                   length;
-        __u32                   input;
-        __u32                   reserved;
-};
-
-/*  Flags for 'flags' field */
-#define V4L2_BUF_FLAG_MAPPED    0x0001  /* Buffer is mapped (flag) */
-#define V4L2_BUF_FLAG_QUEUED    0x0002  /* Buffer is queued for processing */
-#define V4L2_BUF_FLAG_DONE      0x0004  /* Buffer is ready */
-#define V4L2_BUF_FLAG_KEYFRAME  0x0008  /* Image is a keyframe (I-frame) */
-#define V4L2_BUF_FLAG_PFRAME    0x0010  /* Image is a P-frame */
-#define V4L2_BUF_FLAG_BFRAME    0x0020  /* Image is a B-frame */
-/* Buffer is ready, but the data contained within is corrupted. */
-#define V4L2_BUF_FLAG_ERROR     0x0040
-#define V4L2_BUF_FLAG_TIMECODE  0x0100  /* timecode field is valid */
-#define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
-
-/*
- *      O V E R L A Y   P R E V I E W
- */
-struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link> {
-        __u32                   capability;
-        __u32                   flags;
-/* FIXME: in theory we should pass something like PCI device + memory
- * region + offset instead of some physical address */
-        void                    *base;
-        struct <link linkend="v4l2-pix-format">v4l2_pix_format</link>  fmt;
-};
-/*  Flags for the 'capability' field. Read only */
-#define V4L2_FBUF_CAP_EXTERNOVERLAY     0x0001
-#define V4L2_FBUF_CAP_CHROMAKEY         0x0002
-#define V4L2_FBUF_CAP_LIST_CLIPPING     0x0004
-#define V4L2_FBUF_CAP_BITMAP_CLIPPING   0x0008
-#define V4L2_FBUF_CAP_LOCAL_ALPHA       0x0010
-#define V4L2_FBUF_CAP_GLOBAL_ALPHA      0x0020
-#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA   0x0040
-#define V4L2_FBUF_CAP_SRC_CHROMAKEY     0x0080
-/*  Flags for the 'flags' field. */
-#define V4L2_FBUF_FLAG_PRIMARY          0x0001
-#define V4L2_FBUF_FLAG_OVERLAY          0x0002
-#define V4L2_FBUF_FLAG_CHROMAKEY        0x0004
-#define V4L2_FBUF_FLAG_LOCAL_ALPHA      0x0008
-#define V4L2_FBUF_FLAG_GLOBAL_ALPHA     0x0010
-#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA  0x0020
-#define V4L2_FBUF_FLAG_SRC_CHROMAKEY    0x0040
-
-struct <link linkend="v4l2-clip">v4l2_clip</link> {
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        c;
-        struct <link linkend="v4l2-clip">v4l2_clip</link>        __user *next;
-};
-
-struct <link linkend="v4l2-window">v4l2_window</link> {
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        w;
-        enum <link linkend="v4l2-field">v4l2_field</link>         field;
-        __u32                   chromakey;
-        struct <link linkend="v4l2-clip">v4l2_clip</link>        __user *clips;
-        __u32                   clipcount;
-        void                    __user *bitmap;
-        __u8                    global_alpha;
-};
-
-/*
- *      C A P T U R E   P A R A M E T E R S
- */
-struct <link linkend="v4l2-captureparm">v4l2_captureparm</link> {
-        __u32              capability;    /*  Supported modes */
-        __u32              capturemode;   /*  Current mode */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>  timeperframe;  /*  Time per frame in .1us units */
-        __u32              extendedmode;  /*  Driver-specific extensions */
-        __u32              readbuffers;   /*  # of buffers for read */
-        __u32              reserved[4];
-};
-
-/*  Flags for 'capability' and 'capturemode' fields */
-#define V4L2_MODE_HIGHQUALITY   0x0001  /*  High quality imaging mode */
-#define V4L2_CAP_TIMEPERFRAME   0x1000  /*  timeperframe field is supported */
-
-struct <link linkend="v4l2-outputparm">v4l2_outputparm</link> {
-        __u32              capability;   /*  Supported modes */
-        __u32              outputmode;   /*  Current mode */
-        struct <link linkend="v4l2-fract">v4l2_fract</link>  timeperframe; /*  Time per frame in seconds */
-        __u32              extendedmode; /*  Driver-specific extensions */
-        __u32              writebuffers; /*  # of buffers for write */
-        __u32              reserved[4];
-};
-
-/*
- *      I N P U T   I M A G E   C R O P P I N G
- */
-struct <link linkend="v4l2-cropcap">v4l2_cropcap</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        bounds;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        defrect;
-        struct <link linkend="v4l2-fract">v4l2_fract</link>       pixelaspect;
-};
-
-struct <link linkend="v4l2-crop">v4l2_crop</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
-        struct <link linkend="v4l2-rect">v4l2_rect</link>        c;
-};
-
-/*
- *      A N A L O G   V I D E O   S T A N D A R D
- */
-
-typedef __u64 v4l2_std_id;
-
-/* one bit for each */
-#define V4L2_STD_PAL_B          ((v4l2_std_id)0x00000001)
-#define V4L2_STD_PAL_B1         ((v4l2_std_id)0x00000002)
-#define V4L2_STD_PAL_G          ((v4l2_std_id)0x00000004)
-#define V4L2_STD_PAL_H          ((v4l2_std_id)0x00000008)
-#define V4L2_STD_PAL_I          ((v4l2_std_id)0x00000010)
-#define V4L2_STD_PAL_D          ((v4l2_std_id)0x00000020)
-#define V4L2_STD_PAL_D1         ((v4l2_std_id)0x00000040)
-#define V4L2_STD_PAL_K          ((v4l2_std_id)0x00000080)
-
-#define V4L2_STD_PAL_M          ((v4l2_std_id)0x00000100)
-#define V4L2_STD_PAL_N          ((v4l2_std_id)0x00000200)
-#define V4L2_STD_PAL_Nc         ((v4l2_std_id)0x00000400)
-#define V4L2_STD_PAL_60         ((v4l2_std_id)0x00000800)
-
-#define V4L2_STD_NTSC_M         ((v4l2_std_id)0x00001000)
-#define V4L2_STD_NTSC_M_JP      ((v4l2_std_id)0x00002000)
-#define V4L2_STD_NTSC_443       ((v4l2_std_id)0x00004000)
-#define V4L2_STD_NTSC_M_KR      ((v4l2_std_id)0x00008000)
-
-#define V4L2_STD_SECAM_B        ((v4l2_std_id)0x00010000)
-#define V4L2_STD_SECAM_D        ((v4l2_std_id)0x00020000)
-#define V4L2_STD_SECAM_G        ((v4l2_std_id)0x00040000)
-#define V4L2_STD_SECAM_H        ((v4l2_std_id)0x00080000)
-#define V4L2_STD_SECAM_K        ((v4l2_std_id)0x00100000)
-#define V4L2_STD_SECAM_K1       ((v4l2_std_id)0x00200000)
-#define V4L2_STD_SECAM_L        ((v4l2_std_id)0x00400000)
-#define V4L2_STD_SECAM_LC       ((v4l2_std_id)0x00800000)
-
-/* ATSC/HDTV */
-#define V4L2_STD_ATSC_8_VSB     ((v4l2_std_id)0x01000000)
-#define V4L2_STD_ATSC_16_VSB    ((v4l2_std_id)0x02000000)
-
-/* FIXME:
-   Although std_id is 64 bits, there is an issue on PPC32 architecture that
-   makes switch(__u64) to break. So, there's a hack on v4l2-common.c rounding
-   this value to 32 bits.
-   As, currently, the max value is for V4L2_STD_ATSC_16_VSB (30 bits wide),
-   it should work fine. However, if needed to add more than two standards,
-   v4l2-common.c should be fixed.
- */
-
-/* some merged standards */
-#define V4L2_STD_MN     (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
-#define V4L2_STD_B      (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
-#define V4L2_STD_GH     (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
-#define V4L2_STD_DK     (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
-
-/* some common needed stuff */
-#define V4L2_STD_PAL_BG         (V4L2_STD_PAL_B         |\
-                                 V4L2_STD_PAL_B1        |\
-                                 V4L2_STD_PAL_G)
-#define V4L2_STD_PAL_DK         (V4L2_STD_PAL_D         |\
-                                 V4L2_STD_PAL_D1        |\
-                                 V4L2_STD_PAL_K)
-#define V4L2_STD_PAL            (V4L2_STD_PAL_BG        |\
-                                 V4L2_STD_PAL_DK        |\
-                                 V4L2_STD_PAL_H         |\
-                                 V4L2_STD_PAL_I)
-#define V4L2_STD_NTSC           (V4L2_STD_NTSC_M        |\
-                                 V4L2_STD_NTSC_M_JP     |\
-                                 V4L2_STD_NTSC_M_KR)
-#define V4L2_STD_SECAM_DK       (V4L2_STD_SECAM_D       |\
-                                 V4L2_STD_SECAM_K       |\
-                                 V4L2_STD_SECAM_K1)
-#define V4L2_STD_SECAM          (V4L2_STD_SECAM_B       |\
-                                 V4L2_STD_SECAM_G       |\
-                                 V4L2_STD_SECAM_H       |\
-                                 V4L2_STD_SECAM_DK      |\
-                                 V4L2_STD_SECAM_L       |\
-                                 V4L2_STD_SECAM_LC)
-
-#define V4L2_STD_525_60         (V4L2_STD_PAL_M         |\
-                                 V4L2_STD_PAL_60        |\
-                                 V4L2_STD_NTSC          |\
-                                 V4L2_STD_NTSC_443)
-#define V4L2_STD_625_50         (V4L2_STD_PAL           |\
-                                 V4L2_STD_PAL_N         |\
-                                 V4L2_STD_PAL_Nc        |\
-                                 V4L2_STD_SECAM)
-#define V4L2_STD_ATSC           (V4L2_STD_ATSC_8_VSB    |\
-                                 V4L2_STD_ATSC_16_VSB)
-
-#define V4L2_STD_UNKNOWN        0
-#define V4L2_STD_ALL            (V4L2_STD_525_60        |\
-                                 V4L2_STD_625_50)
-
-struct <link linkend="v4l2-standard">v4l2_standard</link> {
-        __u32                index;
-        v4l2_std_id          id;
-        __u8                 name[24];
-        struct <link linkend="v4l2-fract">v4l2_fract</link>    frameperiod; /* Frames, not fields */
-        __u32                framelines;
-        __u32                reserved[4];
-};
-
-/*
- *      V I D E O       T I M I N G S   D V     P R E S E T
- */
-struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link> {
-        __u32   preset;
-        __u32   reserved[4];
-};
-
-/*
- *      D V     P R E S E T S   E N U M E R A T I O N
- */
-struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link> {
-        __u32   index;
-        __u32   preset;
-        __u8    name[32]; /* Name of the preset timing */
-        __u32   width;
-        __u32   height;
-        __u32   reserved[4];
-};
-
-/*
- *      D V     P R E S E T     V A L U E S
- */
-#define         V4L2_DV_INVALID         0
-#define         V4L2_DV_480P59_94       1 /* BT.1362 */
-#define         V4L2_DV_576P50          2 /* BT.1362 */
-#define         V4L2_DV_720P24          3 /* SMPTE 296M */
-#define         V4L2_DV_720P25          4 /* SMPTE 296M */
-#define         V4L2_DV_720P30          5 /* SMPTE 296M */
-#define         V4L2_DV_720P50          6 /* SMPTE 296M */
-#define         V4L2_DV_720P59_94       7 /* SMPTE 274M */
-#define         V4L2_DV_720P60          8 /* SMPTE 274M/296M */
-#define         V4L2_DV_1080I29_97      9 /* BT.1120/ SMPTE 274M */
-#define         V4L2_DV_1080I30         10 /* BT.1120/ SMPTE 274M */
-#define         V4L2_DV_1080I25         11 /* BT.1120 */
-#define         V4L2_DV_1080I50         12 /* SMPTE 296M */
-#define         V4L2_DV_1080I60         13 /* SMPTE 296M */
-#define         V4L2_DV_1080P24         14 /* SMPTE 296M */
-#define         V4L2_DV_1080P25         15 /* SMPTE 296M */
-#define         V4L2_DV_1080P30         16 /* SMPTE 296M */
-#define         V4L2_DV_1080P50         17 /* BT.1120 */
-#define         V4L2_DV_1080P60         18 /* BT.1120 */
-
-/*
- *      D V     B T     T I M I N G S
- */
-
-/* BT.656/BT.1120 timing data */
-struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link> {
-        __u32   width;          /* width in pixels */
-        __u32   height;         /* height in lines */
-        __u32   interlaced;     /* Interlaced or progressive */
-        __u32   polarities;     /* Positive or negative polarity */
-        __u64   pixelclock;     /* Pixel clock in HZ. Ex. 74.25MHz-&gt;74250000 */
-        __u32   hfrontporch;    /* Horizpontal front porch in pixels */
-        __u32   hsync;          /* Horizontal Sync length in pixels */
-        __u32   hbackporch;     /* Horizontal back porch in pixels */
-        __u32   vfrontporch;    /* Vertical front porch in pixels */
-        __u32   vsync;          /* Vertical Sync length in lines */
-        __u32   vbackporch;     /* Vertical back porch in lines */
-        __u32   il_vfrontporch; /* Vertical front porch for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   il_vsync;       /* Vertical sync length for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   il_vbackporch;  /* Vertical back porch for bottom field of
-                                 * interlaced field formats
-                                 */
-        __u32   reserved[16];
-} __attribute__ ((packed));
-
-/* Interlaced or progressive format */
-#define V4L2_DV_PROGRESSIVE     0
-#define V4L2_DV_INTERLACED      1
-
-/* Polarities. If bit is not set, it is assumed to be negative polarity */
-#define V4L2_DV_VSYNC_POS_POL   0x00000001
-#define V4L2_DV_HSYNC_POS_POL   0x00000002
-
-
-/* DV timings */
-struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link> {
-        __u32 type;
-        union {
-                struct <link linkend="v4l2-bt-timings">v4l2_bt_timings</link>  bt;
-                __u32   reserved[32];
-        };
-} __attribute__ ((packed));
-
-/* Values for the type field */
-#define V4L2_DV_BT_656_1120     0       /* BT.656/1120 timing type */
-
-/*
- *      V I D E O   I N P U T S
- */
-struct <link linkend="v4l2-input">v4l2_input</link> {
-        __u32        index;             /*  Which input */
-        __u8         name[32];          /*  Label */
-        __u32        type;              /*  Type of input */
-        __u32        audioset;          /*  Associated audios (bitfield) */
-        __u32        tuner;             /*  Associated tuner */
-        v4l2_std_id  std;
-        __u32        status;
-        __u32        capabilities;
-        __u32        reserved[3];
-};
-
-/*  Values for the 'type' field */
-#define V4L2_INPUT_TYPE_TUNER           1
-#define V4L2_INPUT_TYPE_CAMERA          2
-
-/* field 'status' - general */
-#define V4L2_IN_ST_NO_POWER    0x00000001  /* Attached device is off */
-#define V4L2_IN_ST_NO_SIGNAL   0x00000002
-#define V4L2_IN_ST_NO_COLOR    0x00000004
-
-/* field 'status' - sensor orientation */
-/* If sensor is mounted upside down set both bits */
-#define V4L2_IN_ST_HFLIP       0x00000010 /* Frames are flipped horizontally */
-#define V4L2_IN_ST_VFLIP       0x00000020 /* Frames are flipped vertically */
-
-/* field 'status' - analog */
-#define V4L2_IN_ST_NO_H_LOCK   0x00000100  /* No horizontal sync lock */
-#define V4L2_IN_ST_COLOR_KILL  0x00000200  /* Color killer is active */
-
-/* field 'status' - digital */
-#define V4L2_IN_ST_NO_SYNC     0x00010000  /* No synchronization lock */
-#define V4L2_IN_ST_NO_EQU      0x00020000  /* No equalizer lock */
-#define V4L2_IN_ST_NO_CARRIER  0x00040000  /* Carrier recovery failed */
-
-/* field 'status' - VCR and set-top box */
-#define V4L2_IN_ST_MACROVISION 0x01000000  /* Macrovision detected */
-#define V4L2_IN_ST_NO_ACCESS   0x02000000  /* Conditional access denied */
-#define V4L2_IN_ST_VTR         0x04000000  /* VTR time constant */
-
-/* capabilities flags */
-#define V4L2_IN_CAP_PRESETS             0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_IN_CAP_CUSTOM_TIMINGS      0x00000002 /* Supports S_DV_TIMINGS */
-#define V4L2_IN_CAP_STD                 0x00000004 /* Supports S_STD */
-
-/*
- *      V I D E O   O U T P U T S
- */
-struct <link linkend="v4l2-output">v4l2_output</link> {
-        __u32        index;             /*  Which output */
-        __u8         name[32];          /*  Label */
-        __u32        type;              /*  Type of output */
-        __u32        audioset;          /*  Associated audios (bitfield) */
-        __u32        modulator;         /*  Associated modulator */
-        v4l2_std_id  std;
-        __u32        capabilities;
-        __u32        reserved[3];
-};
-/*  Values for the 'type' field */
-#define V4L2_OUTPUT_TYPE_MODULATOR              1
-#define V4L2_OUTPUT_TYPE_ANALOG                 2
-#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY       3
-
-/* capabilities flags */
-#define V4L2_OUT_CAP_PRESETS            0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_OUT_CAP_CUSTOM_TIMINGS     0x00000002 /* Supports S_DV_TIMINGS */
-#define V4L2_OUT_CAP_STD                0x00000004 /* Supports S_STD */
-
-/*
- *      C O N T R O L S
- */
-struct <link linkend="v4l2-control">v4l2_control</link> {
-        __u32                id;
-        __s32                value;
-};
-
-struct <link linkend="v4l2-ext-control">v4l2_ext_control</link> {
-        __u32 id;
-        __u32 size;
-        __u32 reserved2[1];
-        union {
-                __s32 value;
-                __s64 value64;
-                char *string;
-        };
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link> {
-        __u32 ctrl_class;
-        __u32 count;
-        __u32 error_idx;
-        __u32 reserved[2];
-        struct <link linkend="v4l2-ext-control">v4l2_ext_control</link> *controls;
-};
-
-/*  Values for ctrl_class field */
-#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */
-#define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */
-#define V4L2_CTRL_CLASS_CAMERA 0x009a0000       /* Camera class controls */
-#define V4L2_CTRL_CLASS_FM_TX 0x009b0000        /* FM Modulator control class */
-
-#define V4L2_CTRL_ID_MASK         (0x0fffffff)
-#define V4L2_CTRL_ID2CLASS(id)    ((id) &amp; 0x0fff0000UL)
-#define V4L2_CTRL_DRIVER_PRIV(id) (((id) &amp; 0xffff) &gt;= 0x1000)
-
-enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
-        V4L2_CTRL_TYPE_INTEGER       = 1,
-        V4L2_CTRL_TYPE_BOOLEAN       = 2,
-        V4L2_CTRL_TYPE_MENU          = 3,
-        V4L2_CTRL_TYPE_BUTTON        = 4,
-        V4L2_CTRL_TYPE_INTEGER64     = 5,
-        V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
-        V4L2_CTRL_TYPE_STRING        = 7,
-};
-
-/*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
-struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link> {
-        __u32                id;
-        enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link>  type;
-        __u8                 name[32];  /* Whatever */
-        __s32                minimum;   /* Note signedness */
-        __s32                maximum;
-        __s32                step;
-        __s32                default_value;
-        __u32                flags;
-        __u32                reserved[2];
-};
-
-/*  Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
-struct <link linkend="v4l2-querymenu">v4l2_querymenu</link> {
-        __u32           id;
-        __u32           index;
-        __u8            name[32];       /* Whatever */
-        __u32           reserved;
-};
-
-/*  Control flags  */
-#define V4L2_CTRL_FLAG_DISABLED         0x0001
-#define V4L2_CTRL_FLAG_GRABBED          0x0002
-#define V4L2_CTRL_FLAG_READ_ONLY        0x0004
-#define V4L2_CTRL_FLAG_UPDATE           0x0008
-#define V4L2_CTRL_FLAG_INACTIVE         0x0010
-#define V4L2_CTRL_FLAG_SLIDER           0x0020
-#define V4L2_CTRL_FLAG_WRITE_ONLY       0x0040
-
-/*  Query flag, to be ORed with the control ID */
-#define V4L2_CTRL_FLAG_NEXT_CTRL        0x80000000
-
-/*  User-class control IDs defined by V4L2 */
-#define V4L2_CID_BASE                   (V4L2_CTRL_CLASS_USER | 0x900)
-#define V4L2_CID_USER_BASE              V4L2_CID_BASE
-/*  IDs reserved for driver specific controls */
-#define V4L2_CID_PRIVATE_BASE           0x08000000
-
-#define V4L2_CID_USER_CLASS             (V4L2_CTRL_CLASS_USER | 1)
-#define V4L2_CID_BRIGHTNESS             (V4L2_CID_BASE+0)
-#define V4L2_CID_CONTRAST               (V4L2_CID_BASE+1)
-#define V4L2_CID_SATURATION             (V4L2_CID_BASE+2)
-#define V4L2_CID_HUE                    (V4L2_CID_BASE+3)
-#define V4L2_CID_AUDIO_VOLUME           (V4L2_CID_BASE+5)
-#define V4L2_CID_AUDIO_BALANCE          (V4L2_CID_BASE+6)
-#define V4L2_CID_AUDIO_BASS             (V4L2_CID_BASE+7)
-#define V4L2_CID_AUDIO_TREBLE           (V4L2_CID_BASE+8)
-#define V4L2_CID_AUDIO_MUTE             (V4L2_CID_BASE+9)
-#define V4L2_CID_AUDIO_LOUDNESS         (V4L2_CID_BASE+10)
-#define V4L2_CID_BLACK_LEVEL            (V4L2_CID_BASE+11) /* Deprecated */
-#define V4L2_CID_AUTO_WHITE_BALANCE     (V4L2_CID_BASE+12)
-#define V4L2_CID_DO_WHITE_BALANCE       (V4L2_CID_BASE+13)
-#define V4L2_CID_RED_BALANCE            (V4L2_CID_BASE+14)
-#define V4L2_CID_BLUE_BALANCE           (V4L2_CID_BASE+15)
-#define V4L2_CID_GAMMA                  (V4L2_CID_BASE+16)
-#define V4L2_CID_WHITENESS              (V4L2_CID_GAMMA) /* Deprecated */
-#define V4L2_CID_EXPOSURE               (V4L2_CID_BASE+17)
-#define V4L2_CID_AUTOGAIN               (V4L2_CID_BASE+18)
-#define V4L2_CID_GAIN                   (V4L2_CID_BASE+19)
-#define V4L2_CID_HFLIP                  (V4L2_CID_BASE+20)
-#define V4L2_CID_VFLIP                  (V4L2_CID_BASE+21)
-
-/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
-#define V4L2_CID_HCENTER                (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER                (V4L2_CID_BASE+23)
-
-#define V4L2_CID_POWER_LINE_FREQUENCY   (V4L2_CID_BASE+24)
-enum <link linkend="v4l2-power-line-frequency">v4l2_power_line_frequency</link> {
-        V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
-        V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
-        V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
-};
-#define V4L2_CID_HUE_AUTO                       (V4L2_CID_BASE+25)
-#define V4L2_CID_WHITE_BALANCE_TEMPERATURE      (V4L2_CID_BASE+26)
-#define V4L2_CID_SHARPNESS                      (V4L2_CID_BASE+27)
-#define V4L2_CID_BACKLIGHT_COMPENSATION         (V4L2_CID_BASE+28)
-#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
-#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
-#define V4L2_CID_COLORFX                        (V4L2_CID_BASE+31)
-enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> {
-        V4L2_COLORFX_NONE       = 0,
-        V4L2_COLORFX_BW         = 1,
-        V4L2_COLORFX_SEPIA      = 2,
-        V4L2_COLORFX_NEGATIVE = 3,
-        V4L2_COLORFX_EMBOSS = 4,
-        V4L2_COLORFX_SKETCH = 5,
-        V4L2_COLORFX_SKY_BLUE = 6,
-        V4L2_COLORFX_GRASS_GREEN = 7,
-        V4L2_COLORFX_SKIN_WHITEN = 8,
-        V4L2_COLORFX_VIVID = 9,
-};
-#define V4L2_CID_AUTOBRIGHTNESS                 (V4L2_CID_BASE+32)
-#define V4L2_CID_BAND_STOP_FILTER               (V4L2_CID_BASE+33)
-
-#define V4L2_CID_ROTATE                         (V4L2_CID_BASE+34)
-#define V4L2_CID_BG_COLOR                       (V4L2_CID_BASE+35)
-
-#define V4L2_CID_CHROMA_GAIN                    (V4L2_CID_BASE+36)
-
-#define V4L2_CID_ILLUMINATORS_1                 (V4L2_CID_BASE+37)
-#define V4L2_CID_ILLUMINATORS_2                 (V4L2_CID_BASE+38)
-
-/* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+39)
-
-/*  MPEG-class control IDs defined by V4L2 */
-#define V4L2_CID_MPEG_BASE                      (V4L2_CTRL_CLASS_MPEG | 0x900)
-#define V4L2_CID_MPEG_CLASS                     (V4L2_CTRL_CLASS_MPEG | 1)
-
-/*  MPEG streams */
-#define V4L2_CID_MPEG_STREAM_TYPE               (V4L2_CID_MPEG_BASE+0)
-enum <link linkend="v4l2-mpeg-stream-type">v4l2_mpeg_stream_type</link> {
-        V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
-        V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
-};
-#define V4L2_CID_MPEG_STREAM_PID_PMT            (V4L2_CID_MPEG_BASE+1)
-#define V4L2_CID_MPEG_STREAM_PID_AUDIO          (V4L2_CID_MPEG_BASE+2)
-#define V4L2_CID_MPEG_STREAM_PID_VIDEO          (V4L2_CID_MPEG_BASE+3)
-#define V4L2_CID_MPEG_STREAM_PID_PCR            (V4L2_CID_MPEG_BASE+4)
-#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO       (V4L2_CID_MPEG_BASE+5)
-#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO       (V4L2_CID_MPEG_BASE+6)
-#define V4L2_CID_MPEG_STREAM_VBI_FMT            (V4L2_CID_MPEG_BASE+7)
-enum <link linkend="v4l2-mpeg-stream-vbi-fmt">v4l2_mpeg_stream_vbi_fmt</link> {
-        V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
-        V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
-};
-
-/*  MPEG audio */
-#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ       (V4L2_CID_MPEG_BASE+100)
-enum <link linkend="v4l2-mpeg-audio-sampling-freq">v4l2_mpeg_audio_sampling_freq</link> {
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
-        V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_ENCODING            (V4L2_CID_MPEG_BASE+101)
-enum <link linkend="v4l2-mpeg-audio-encoding">v4l2_mpeg_audio_encoding</link> {
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
-        V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
-        V4L2_MPEG_AUDIO_ENCODING_AAC     = 3,
-        V4L2_MPEG_AUDIO_ENCODING_AC3     = 4,
-};
-#define V4L2_CID_MPEG_AUDIO_L1_BITRATE          (V4L2_CID_MPEG_BASE+102)
-enum <link linkend="v4l2-mpeg-audio-l1-bitrate">v4l2_mpeg_audio_l1_bitrate</link> {
-        V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
-        V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
-        V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
-        V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
-        V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
-        V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
-        V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
-        V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
-        V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
-        V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
-        V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
-        V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
-        V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L2_BITRATE          (V4L2_CID_MPEG_BASE+103)
-enum <link linkend="v4l2-mpeg-audio-l2-bitrate">v4l2_mpeg_audio_l2_bitrate</link> {
-        V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
-        V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
-        V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
-        V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
-        V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
-        V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
-        V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
-        V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
-        V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
-        V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
-        V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
-        V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
-        V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L3_BITRATE          (V4L2_CID_MPEG_BASE+104)
-enum <link linkend="v4l2-mpeg-audio-l3-bitrate">v4l2_mpeg_audio_l3_bitrate</link> {
-        V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
-        V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
-        V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
-        V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
-        V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
-        V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
-        V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
-        V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
-        V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
-        V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
-        V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
-        V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
-        V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE                (V4L2_CID_MPEG_BASE+105)
-enum <link linkend="v4l2-mpeg-audio-mode">v4l2_mpeg_audio_mode</link> {
-        V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
-        V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
-        V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
-        V4L2_MPEG_AUDIO_MODE_MONO         = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION      (V4L2_CID_MPEG_BASE+106)
-enum <link linkend="v4l2-mpeg-audio-mode-extension">v4l2_mpeg_audio_mode_extension</link> {
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
-        V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_EMPHASIS            (V4L2_CID_MPEG_BASE+107)
-enum <link linkend="v4l2-mpeg-audio-emphasis">v4l2_mpeg_audio_emphasis</link> {
-        V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
-        V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
-        V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_CRC                 (V4L2_CID_MPEG_BASE+108)
-enum <link linkend="v4l2-mpeg-audio-crc">v4l2_mpeg_audio_crc</link> {
-        V4L2_MPEG_AUDIO_CRC_NONE  = 0,
-        V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
-};
-#define V4L2_CID_MPEG_AUDIO_MUTE                (V4L2_CID_MPEG_BASE+109)
-#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE         (V4L2_CID_MPEG_BASE+110)
-#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE         (V4L2_CID_MPEG_BASE+111)
-enum <link linkend="v4l2-mpeg-audio-ac3-bitrate">v4l2_mpeg_audio_ac3_bitrate</link> {
-        V4L2_MPEG_AUDIO_AC3_BITRATE_32K  = 0,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_40K  = 1,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_48K  = 2,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_56K  = 3,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_64K  = 4,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_80K  = 5,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_96K  = 6,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17,
-        V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
-};
-
-/*  MPEG video */
-#define V4L2_CID_MPEG_VIDEO_ENCODING            (V4L2_CID_MPEG_BASE+200)
-enum <link linkend="v4l2-mpeg-video-encoding">v4l2_mpeg_video_encoding</link> {
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_2     = 1,
-        V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2,
-};
-#define V4L2_CID_MPEG_VIDEO_ASPECT              (V4L2_CID_MPEG_BASE+201)
-enum <link linkend="v4l2-mpeg-video-aspect">v4l2_mpeg_video_aspect</link> {
-        V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
-        V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
-        V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
-        V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
-};
-#define V4L2_CID_MPEG_VIDEO_B_FRAMES            (V4L2_CID_MPEG_BASE+202)
-#define V4L2_CID_MPEG_VIDEO_GOP_SIZE            (V4L2_CID_MPEG_BASE+203)
-#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE         (V4L2_CID_MPEG_BASE+204)
-#define V4L2_CID_MPEG_VIDEO_PULLDOWN            (V4L2_CID_MPEG_BASE+205)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE        (V4L2_CID_MPEG_BASE+206)
-enum <link linkend="v4l2-mpeg-video-bitrate-mode">v4l2_mpeg_video_bitrate_mode</link> {
-        V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
-        V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
-};
-#define V4L2_CID_MPEG_VIDEO_BITRATE             (V4L2_CID_MPEG_BASE+207)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK        (V4L2_CID_MPEG_BASE+208)
-#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
-#define V4L2_CID_MPEG_VIDEO_MUTE                (V4L2_CID_MPEG_BASE+210)
-#define V4L2_CID_MPEG_VIDEO_MUTE_YUV            (V4L2_CID_MPEG_BASE+211)
-
-/*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
-#define V4L2_CID_MPEG_CX2341X_BASE                              (V4L2_CTRL_CLASS_MPEG | 0x1000)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE         (V4L2_CID_MPEG_CX2341X_BASE+0)
-enum <link linkend="v4l2-mpeg-cx2341x-video-spatial-filter-mode">v4l2_mpeg_cx2341x_video_spatial_filter_mode</link> {
-        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
-        V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER              (V4L2_CID_MPEG_CX2341X_BASE+1)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE    (V4L2_CID_MPEG_CX2341X_BASE+2)
-enum <link linkend="luma-spatial-filter-type">v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
-        V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE  (V4L2_CID_MPEG_CX2341X_BASE+3)
-enum <link linkend="chroma-spatial-filter-type">v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
-        V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE        (V4L2_CID_MPEG_CX2341X_BASE+4)
-enum <link linkend="v4l2-mpeg-cx2341x-video-temporal-filter-mode">v4l2_mpeg_cx2341x_video_temporal_filter_mode</link> {
-        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
-        V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER             (V4L2_CID_MPEG_CX2341X_BASE+5)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE          (V4L2_CID_MPEG_CX2341X_BASE+6)
-enum <link linkend="v4l2-mpeg-cx2341x-video-median-filter-type">v4l2_mpeg_cx2341x_video_median_filter_type</link> {
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
-        V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM   (V4L2_CID_MPEG_CX2341X_BASE+7)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP      (V4L2_CID_MPEG_CX2341X_BASE+8)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP    (V4L2_CID_MPEG_CX2341X_BASE+10)
-#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS         (V4L2_CID_MPEG_CX2341X_BASE+11)
-
-/*  Camera class control IDs */
-#define V4L2_CID_CAMERA_CLASS_BASE      (V4L2_CTRL_CLASS_CAMERA | 0x900)
-#define V4L2_CID_CAMERA_CLASS           (V4L2_CTRL_CLASS_CAMERA | 1)
-
-#define V4L2_CID_EXPOSURE_AUTO                  (V4L2_CID_CAMERA_CLASS_BASE+1)
-enum  <link linkend="v4l2-exposure-auto-type">v4l2_exposure_auto_type</link> {
-        V4L2_EXPOSURE_AUTO = 0,
-        V4L2_EXPOSURE_MANUAL = 1,
-        V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
-        V4L2_EXPOSURE_APERTURE_PRIORITY = 3
-};
-#define V4L2_CID_EXPOSURE_ABSOLUTE              (V4L2_CID_CAMERA_CLASS_BASE+2)
-#define V4L2_CID_EXPOSURE_AUTO_PRIORITY         (V4L2_CID_CAMERA_CLASS_BASE+3)
-
-#define V4L2_CID_PAN_RELATIVE                   (V4L2_CID_CAMERA_CLASS_BASE+4)
-#define V4L2_CID_TILT_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+5)
-#define V4L2_CID_PAN_RESET                      (V4L2_CID_CAMERA_CLASS_BASE+6)
-#define V4L2_CID_TILT_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+7)
-
-#define V4L2_CID_PAN_ABSOLUTE                   (V4L2_CID_CAMERA_CLASS_BASE+8)
-#define V4L2_CID_TILT_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+9)
-
-#define V4L2_CID_FOCUS_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+10)
-#define V4L2_CID_FOCUS_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+11)
-#define V4L2_CID_FOCUS_AUTO                     (V4L2_CID_CAMERA_CLASS_BASE+12)
-
-#define V4L2_CID_ZOOM_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+13)
-#define V4L2_CID_ZOOM_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+14)
-#define V4L2_CID_ZOOM_CONTINUOUS                (V4L2_CID_CAMERA_CLASS_BASE+15)
-
-#define V4L2_CID_PRIVACY                        (V4L2_CID_CAMERA_CLASS_BASE+16)
-
-#define V4L2_CID_IRIS_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+17)
-#define V4L2_CID_IRIS_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+18)
-
-/* FM Modulator class control IDs */
-#define V4L2_CID_FM_TX_CLASS_BASE               (V4L2_CTRL_CLASS_FM_TX | 0x900)
-#define V4L2_CID_FM_TX_CLASS                    (V4L2_CTRL_CLASS_FM_TX | 1)
-
-#define V4L2_CID_RDS_TX_DEVIATION               (V4L2_CID_FM_TX_CLASS_BASE + 1)
-#define V4L2_CID_RDS_TX_PI                      (V4L2_CID_FM_TX_CLASS_BASE + 2)
-#define V4L2_CID_RDS_TX_PTY                     (V4L2_CID_FM_TX_CLASS_BASE + 3)
-#define V4L2_CID_RDS_TX_PS_NAME                 (V4L2_CID_FM_TX_CLASS_BASE + 5)
-#define V4L2_CID_RDS_TX_RADIO_TEXT              (V4L2_CID_FM_TX_CLASS_BASE + 6)
-
-#define V4L2_CID_AUDIO_LIMITER_ENABLED          (V4L2_CID_FM_TX_CLASS_BASE + 64)
-#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME     (V4L2_CID_FM_TX_CLASS_BASE + 65)
-#define V4L2_CID_AUDIO_LIMITER_DEVIATION        (V4L2_CID_FM_TX_CLASS_BASE + 66)
-
-#define V4L2_CID_AUDIO_COMPRESSION_ENABLED      (V4L2_CID_FM_TX_CLASS_BASE + 80)
-#define V4L2_CID_AUDIO_COMPRESSION_GAIN         (V4L2_CID_FM_TX_CLASS_BASE + 81)
-#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD    (V4L2_CID_FM_TX_CLASS_BASE + 82)
-#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME  (V4L2_CID_FM_TX_CLASS_BASE + 83)
-#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME (V4L2_CID_FM_TX_CLASS_BASE + 84)
-
-#define V4L2_CID_PILOT_TONE_ENABLED             (V4L2_CID_FM_TX_CLASS_BASE + 96)
-#define V4L2_CID_PILOT_TONE_DEVIATION           (V4L2_CID_FM_TX_CLASS_BASE + 97)
-#define V4L2_CID_PILOT_TONE_FREQUENCY           (V4L2_CID_FM_TX_CLASS_BASE + 98)
-
-#define V4L2_CID_TUNE_PREEMPHASIS               (V4L2_CID_FM_TX_CLASS_BASE + 112)
-enum <link linkend="v4l2-preemphasis">v4l2_preemphasis</link> {
-        V4L2_PREEMPHASIS_DISABLED       = 0,
-        V4L2_PREEMPHASIS_50_uS          = 1,
-        V4L2_PREEMPHASIS_75_uS          = 2,
-};
-#define V4L2_CID_TUNE_POWER_LEVEL               (V4L2_CID_FM_TX_CLASS_BASE + 113)
-#define V4L2_CID_TUNE_ANTENNA_CAPACITOR         (V4L2_CID_FM_TX_CLASS_BASE + 114)
-
-/*
- *      T U N I N G
- */
-struct <link linkend="v4l2-tuner">v4l2_tuner</link> {
-        __u32                   index;
-        __u8                    name[32];
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>    type;
-        __u32                   capability;
-        __u32                   rangelow;
-        __u32                   rangehigh;
-        __u32                   rxsubchans;
-        __u32                   audmode;
-        __s32                   signal;
-        __s32                   afc;
-        __u32                   reserved[4];
-};
-
-struct <link linkend="v4l2-modulator">v4l2_modulator</link> {
-        __u32                   index;
-        __u8                    name[32];
-        __u32                   capability;
-        __u32                   rangelow;
-        __u32                   rangehigh;
-        __u32                   txsubchans;
-        __u32                   reserved[4];
-};
-
-/*  Flags for the 'capability' field */
-#define V4L2_TUNER_CAP_LOW              0x0001
-#define V4L2_TUNER_CAP_NORM             0x0002
-#define V4L2_TUNER_CAP_STEREO           0x0010
-#define V4L2_TUNER_CAP_LANG2            0x0020
-#define V4L2_TUNER_CAP_SAP              0x0020
-#define V4L2_TUNER_CAP_LANG1            0x0040
-#define V4L2_TUNER_CAP_RDS              0x0080
-#define V4L2_TUNER_CAP_RDS_BLOCK_IO     0x0100
-#define V4L2_TUNER_CAP_RDS_CONTROLS     0x0200
-
-/*  Flags for the 'rxsubchans' field */
-#define V4L2_TUNER_SUB_MONO             0x0001
-#define V4L2_TUNER_SUB_STEREO           0x0002
-#define V4L2_TUNER_SUB_LANG2            0x0004
-#define V4L2_TUNER_SUB_SAP              0x0004
-#define V4L2_TUNER_SUB_LANG1            0x0008
-#define V4L2_TUNER_SUB_RDS              0x0010
-
-/*  Values for the 'audmode' field */
-#define V4L2_TUNER_MODE_MONO            0x0000
-#define V4L2_TUNER_MODE_STEREO          0x0001
-#define V4L2_TUNER_MODE_LANG2           0x0002
-#define V4L2_TUNER_MODE_SAP             0x0002
-#define V4L2_TUNER_MODE_LANG1           0x0003
-#define V4L2_TUNER_MODE_LANG1_LANG2     0x0004
-
-struct <link linkend="v4l2-frequency">v4l2_frequency</link> {
-        __u32                 tuner;
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
-        __u32                 frequency;
-        __u32                 reserved[8];
-};
-
-struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link> {
-        __u32                 tuner;
-        enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
-        __u32                 seek_upward;
-        __u32                 wrap_around;
-        __u32                 spacing;
-        __u32                 reserved[7];
-};
-
-/*
- *      R D S
- */
-
-struct <link linkend="v4l2-rds-data">v4l2_rds_data</link> {
-        __u8    lsb;
-        __u8    msb;
-        __u8    block;
-} __attribute__ ((packed));
-
-#define V4L2_RDS_BLOCK_MSK       0x7
-#define V4L2_RDS_BLOCK_A         0
-#define V4L2_RDS_BLOCK_B         1
-#define V4L2_RDS_BLOCK_C         2
-#define V4L2_RDS_BLOCK_D         3
-#define V4L2_RDS_BLOCK_C_ALT     4
-#define V4L2_RDS_BLOCK_INVALID   7
-
-#define V4L2_RDS_BLOCK_CORRECTED 0x40
-#define V4L2_RDS_BLOCK_ERROR     0x80
-
-/*
- *      A U D I O
- */
-struct <link linkend="v4l2-audio">v4l2_audio</link> {
-        __u32   index;
-        __u8    name[32];
-        __u32   capability;
-        __u32   mode;
-        __u32   reserved[2];
-};
-
-/*  Flags for the 'capability' field */
-#define V4L2_AUDCAP_STEREO              0x00001
-#define V4L2_AUDCAP_AVL                 0x00002
-
-/*  Flags for the 'mode' field */
-#define V4L2_AUDMODE_AVL                0x00001
-
-struct <link linkend="v4l2-audioout">v4l2_audioout</link> {
-        __u32   index;
-        __u8    name[32];
-        __u32   capability;
-        __u32   mode;
-        __u32   reserved[2];
-};
-
-/*
- *      M P E G   S E R V I C E S
- *
- *      NOTE: EXPERIMENTAL API
- */
-#if 1
-#define V4L2_ENC_IDX_FRAME_I    (0)
-#define V4L2_ENC_IDX_FRAME_P    (1)
-#define V4L2_ENC_IDX_FRAME_B    (2)
-#define V4L2_ENC_IDX_FRAME_MASK (0xf)
-
-struct <link linkend="v4l2-enc-idx-entry">v4l2_enc_idx_entry</link> {
-        __u64 offset;
-        __u64 pts;
-        __u32 length;
-        __u32 flags;
-        __u32 reserved[2];
-};
-
-#define V4L2_ENC_IDX_ENTRIES (64)
-struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link> {
-        __u32 entries;
-        __u32 entries_cap;
-        __u32 reserved[4];
-        struct <link linkend="v4l2-enc-idx-entry">v4l2_enc_idx_entry</link> entry[V4L2_ENC_IDX_ENTRIES];
-};
-
-
-#define V4L2_ENC_CMD_START      (0)
-#define V4L2_ENC_CMD_STOP       (1)
-#define V4L2_ENC_CMD_PAUSE      (2)
-#define V4L2_ENC_CMD_RESUME     (3)
-
-/* Flags for V4L2_ENC_CMD_STOP */
-#define V4L2_ENC_CMD_STOP_AT_GOP_END    (1 &lt;&lt; 0)
-
-struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link> {
-        __u32 cmd;
-        __u32 flags;
-        union {
-                struct {
-                        __u32 data[8];
-                } raw;
-        };
-};
-
-#endif
-
-
-/*
- *      D A T A   S E R V I C E S   ( V B I )
- *
- *      Data services API by Michael Schimek
- */
-
-/* Raw VBI */
-struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link> {
-        __u32   sampling_rate;          /* in 1 Hz */
-        __u32   offset;
-        __u32   samples_per_line;
-        __u32   sample_format;          /* V4L2_PIX_FMT_* */
-        __s32   start[2];
-        __u32   count[2];
-        __u32   flags;                  /* V4L2_VBI_* */
-        __u32   reserved[2];            /* must be zero */
-};
-
-/*  VBI flags  */
-#define V4L2_VBI_UNSYNC         (1 &lt;&lt; 0)
-#define V4L2_VBI_INTERLACED     (1 &lt;&lt; 1)
-
-/* Sliced VBI
- *
- *    This implements is a proposal V4L2 API to allow SLICED VBI
- * required for some hardware encoders. It should change without
- * notice in the definitive implementation.
- */
-
-struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link> {
-        __u16   service_set;
-        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
-           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
-                                 (equals frame lines 313-336 for 625 line video
-                                  standards, 263-286 for 525 line standards) */
-        __u16   service_lines[2][24];
-        __u32   io_size;
-        __u32   reserved[2];            /* must be zero */
-};
-
-/* Teletext World System Teletext
-   (WST), defined on ITU-R BT.653-2 */
-#define V4L2_SLICED_TELETEXT_B          (0x0001)
-/* Video Program System, defined on ETS 300 231*/
-#define V4L2_SLICED_VPS                 (0x0400)
-/* Closed Caption, defined on EIA-608 */
-#define V4L2_SLICED_CAPTION_525         (0x1000)
-/* Wide Screen System, defined on ITU-R BT1119.1 */
-#define V4L2_SLICED_WSS_625             (0x4000)
-
-#define V4L2_SLICED_VBI_525             (V4L2_SLICED_CAPTION_525)
-#define V4L2_SLICED_VBI_625             (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625)
-
-struct <link linkend="v4l2-sliced-vbi-cap">v4l2_sliced_vbi_cap</link> {
-        __u16   service_set;
-        /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field
-           service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field
-                                 (equals frame lines 313-336 for 625 line video
-                                  standards, 263-286 for 525 line standards) */
-        __u16   service_lines[2][24];
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        __u32   reserved[3];    /* must be 0 */
-};
-
-struct <link linkend="v4l2-sliced-vbi-data">v4l2_sliced_vbi_data</link> {
-        __u32   id;
-        __u32   field;          /* 0: first field, 1: second field */
-        __u32   line;           /* 1-23 */
-        __u32   reserved;       /* must be 0 */
-        __u8    data[48];
-};
-
-/*
- * Sliced VBI data inserted into MPEG Streams
- */
-
-/*
- * V4L2_MPEG_STREAM_VBI_FMT_IVTV:
- *
- * Structure of payload contained in an MPEG 2 Private Stream 1 PES Packet in an
- * MPEG-2 Program Pack that contains V4L2_MPEG_STREAM_VBI_FMT_IVTV Sliced VBI
- * data
- *
- * Note, the MPEG-2 Program Pack and Private Stream 1 PES packet header
- * definitions are not included here.  See the MPEG-2 specifications for details
- * on these headers.
- */
-
-/* Line type IDs */
-#define V4L2_MPEG_VBI_IVTV_TELETEXT_B     (1)
-#define V4L2_MPEG_VBI_IVTV_CAPTION_525    (4)
-#define V4L2_MPEG_VBI_IVTV_WSS_625        (5)
-#define V4L2_MPEG_VBI_IVTV_VPS            (7)
-
-struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> {
-        __u8 id;        /* One of V4L2_MPEG_VBI_IVTV_* above */
-        __u8 data[42];  /* Sliced VBI data for the line */
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-mpeg-vbi-itv0">v4l2_mpeg_vbi_itv0</link> {
-        __le32 linemask[2]; /* Bitmasks of VBI service lines present */
-        struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> line[35];
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-mpeg-vbi-itv0-1">v4l2_mpeg_vbi_ITV0</link> {
-        struct <link linkend="v4l2-mpeg-vbi-itv0-line">v4l2_mpeg_vbi_itv0_line</link> line[36];
-} __attribute__ ((packed));
-
-#define V4L2_MPEG_VBI_IVTV_MAGIC0       "itv0"
-#define V4L2_MPEG_VBI_IVTV_MAGIC1       "ITV0"
-
-struct <link linkend="v4l2-mpeg-vbi-fmt-ivtv">v4l2_mpeg_vbi_fmt_ivtv</link> {
-        __u8 magic[4];
-        union {
-                struct <link linkend="v4l2-mpeg-vbi-itv0">v4l2_mpeg_vbi_itv0</link> itv0;
-                struct <link linkend="v4l2-mpeg-vbi-itv0-1">v4l2_mpeg_vbi_ITV0</link> ITV0;
-        };
-} __attribute__ ((packed));
-
-/*
- *      A G G R E G A T E   S T R U C T U R E S
- */
-
-/**
- * struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> - additional, per-plane format definition
- * @sizeimage:          maximum size in bytes required for data, for which
- *                      this plane will be used
- * @bytesperline:       distance in bytes between the leftmost pixels in two
- *                      adjacent lines
- */
-struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> {
-        __u32           sizeimage;
-        __u16           bytesperline;
-        __u16           reserved[7];
-} __attribute__ ((packed));
-
-/**
- * struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> - multiplanar format definition
- * @width:              image width in pixels
- * @height:             image height in pixels
- * @pixelformat:        little endian four character code (fourcc)
- * @field:              field order (for interlaced video)
- * @colorspace:         supplemental to pixelformat
- * @plane_fmt:          per-plane information
- * @num_planes:         number of planes for this format
- */
-struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> {
-        __u32                           width;
-        __u32                           height;
-        __u32                           pixelformat;
-        enum <link linkend="v4l2-field">v4l2_field</link>                 field;
-        enum <link linkend="v4l2-colorspace">v4l2_colorspace</link>            colorspace;
-
-        struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link>    plane_fmt[VIDEO_MAX_PLANES];
-        __u8                            num_planes;
-        __u8                            reserved[11];
-} __attribute__ ((packed));
-
-/**
- * struct <link linkend="v4l2-format">v4l2_format</link> - stream data format
- * @type:       type of the data stream
- * @pix:        definition of an image format
- * @pix_mp:     definition of a multiplanar image format
- * @win:        definition of an overlaid image
- * @vbi:        raw VBI capture or output parameters
- * @sliced:     sliced VBI capture or output parameters
- * @raw_data:   placeholder for future extensions and custom formats
- */
-struct <link linkend="v4l2-format">v4l2_format</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        union {
-                struct <link linkend="v4l2-pix-format">v4l2_pix_format</link>          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
-                struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link>   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
-                struct <link linkend="v4l2-window">v4l2_window</link>              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
-                struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link>          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
-                struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link>   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
-                __u8    raw_data[200];                   /* user-defined */
-        } fmt;
-};
-
-/*      Stream type-dependent parameters
- */
-struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
-        enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
-        union {
-                struct <link linkend="v4l2-captureparm">v4l2_captureparm</link> capture;
-                struct <link linkend="v4l2-outputparm">v4l2_outputparm</link>  output;
-                __u8    raw_data[200];  /* user-defined */
-        } parm;
-};
-
-/*
- *      E V E N T S
- */
-
-#define V4L2_EVENT_ALL                          0
-#define V4L2_EVENT_VSYNC                        1
-#define V4L2_EVENT_EOS                          2
-#define V4L2_EVENT_PRIVATE_START                0x08000000
-
-/* Payload for V4L2_EVENT_VSYNC */
-struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> {
-        /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */
-        __u8 field;
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-event">v4l2_event</link> {
-        __u32                           type;
-        union {
-                struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> vsync;
-                __u8                    data[64];
-        } u;
-        __u32                           pending;
-        __u32                           sequence;
-        struct timespec                 timestamp;
-        __u32                           reserved[9];
-};
-
-struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link> {
-        __u32                           type;
-        __u32                           reserved[7];
-};
-
-/*
- *      A D V A N C E D   D E B U G G I N G
- *
- *      NOTE: EXPERIMENTAL API, NEVER RELY ON THIS IN APPLICATIONS!
- *      FOR DEBUGGING, TESTING AND INTERNAL USE ONLY!
- */
-
-/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */
-
-#define V4L2_CHIP_MATCH_HOST       0  /* Match against chip ID on host (0 for the host) */
-#define V4L2_CHIP_MATCH_I2C_DRIVER 1  /* Match against I2C driver name */
-#define V4L2_CHIP_MATCH_I2C_ADDR   2  /* Match against I2C 7-bit address */
-#define V4L2_CHIP_MATCH_AC97       3  /* Match against anciliary AC97 chip */
-
-struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> {
-        __u32 type; /* Match type */
-        union {     /* Match this chip, meaning determined by type */
-                __u32 addr;
-                char name[32];
-        };
-} __attribute__ ((packed));
-
-struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link> {
-        struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> match;
-        __u32 size;     /* register size in bytes */
-        __u64 reg;
-        __u64 val;
-} __attribute__ ((packed));
-
-/* VIDIOC_DBG_G_CHIP_IDENT */
-struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
-        struct <link linkend="v4l2-dbg-match">v4l2_dbg_match</link> match;
-        __u32 ident;       /* chip identifier as specified in &lt;media/v4l2-chip-ident.h&gt; */
-        __u32 revision;    /* chip revision, chip specific */
-} __attribute__ ((packed));
-
-/*
- *      I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
- *
- */
-#define VIDIOC_QUERYCAP          _IOR('V',  0, struct <link linkend="v4l2-capability">v4l2_capability</link>)
-#define VIDIOC_RESERVED           _IO('V',  1)
-#define VIDIOC_ENUM_FMT         _IOWR('V',  2, struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link>)
-#define VIDIOC_G_FMT            _IOWR('V',  4, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_S_FMT            _IOWR('V',  5, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_REQBUFS          _IOWR('V',  8, struct <link linkend="v4l2-requestbuffers">v4l2_requestbuffers</link>)
-#define VIDIOC_QUERYBUF         _IOWR('V',  9, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_G_FBUF            _IOR('V', 10, struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link>)
-#define VIDIOC_S_FBUF            _IOW('V', 11, struct <link linkend="v4l2-framebuffer">v4l2_framebuffer</link>)
-#define VIDIOC_OVERLAY           _IOW('V', 14, int)
-#define VIDIOC_QBUF             _IOWR('V', 15, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_DQBUF            _IOWR('V', 17, struct <link linkend="v4l2-buffer">v4l2_buffer</link>)
-#define VIDIOC_STREAMON          _IOW('V', 18, int)
-#define VIDIOC_STREAMOFF         _IOW('V', 19, int)
-#define VIDIOC_G_PARM           _IOWR('V', 21, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
-#define VIDIOC_S_PARM           _IOWR('V', 22, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
-#define VIDIOC_G_STD             _IOR('V', 23, v4l2_std_id)
-#define VIDIOC_S_STD             _IOW('V', 24, v4l2_std_id)
-#define VIDIOC_ENUMSTD          _IOWR('V', 25, struct <link linkend="v4l2-standard">v4l2_standard</link>)
-#define VIDIOC_ENUMINPUT        _IOWR('V', 26, struct <link linkend="v4l2-input">v4l2_input</link>)
-#define VIDIOC_G_CTRL           _IOWR('V', 27, struct <link linkend="v4l2-control">v4l2_control</link>)
-#define VIDIOC_S_CTRL           _IOWR('V', 28, struct <link linkend="v4l2-control">v4l2_control</link>)
-#define VIDIOC_G_TUNER          _IOWR('V', 29, struct <link linkend="v4l2-tuner">v4l2_tuner</link>)
-#define VIDIOC_S_TUNER           _IOW('V', 30, struct <link linkend="v4l2-tuner">v4l2_tuner</link>)
-#define VIDIOC_G_AUDIO           _IOR('V', 33, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_S_AUDIO           _IOW('V', 34, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_QUERYCTRL        _IOWR('V', 36, struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link>)
-#define VIDIOC_QUERYMENU        _IOWR('V', 37, struct <link linkend="v4l2-querymenu">v4l2_querymenu</link>)
-#define VIDIOC_G_INPUT           _IOR('V', 38, int)
-#define VIDIOC_S_INPUT          _IOWR('V', 39, int)
-#define VIDIOC_G_OUTPUT          _IOR('V', 46, int)
-#define VIDIOC_S_OUTPUT         _IOWR('V', 47, int)
-#define VIDIOC_ENUMOUTPUT       _IOWR('V', 48, struct <link linkend="v4l2-output">v4l2_output</link>)
-#define VIDIOC_G_AUDOUT          _IOR('V', 49, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_S_AUDOUT          _IOW('V', 50, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_G_MODULATOR      _IOWR('V', 54, struct <link linkend="v4l2-modulator">v4l2_modulator</link>)
-#define VIDIOC_S_MODULATOR       _IOW('V', 55, struct <link linkend="v4l2-modulator">v4l2_modulator</link>)
-#define VIDIOC_G_FREQUENCY      _IOWR('V', 56, struct <link linkend="v4l2-frequency">v4l2_frequency</link>)
-#define VIDIOC_S_FREQUENCY       _IOW('V', 57, struct <link linkend="v4l2-frequency">v4l2_frequency</link>)
-#define VIDIOC_CROPCAP          _IOWR('V', 58, struct <link linkend="v4l2-cropcap">v4l2_cropcap</link>)
-#define VIDIOC_G_CROP           _IOWR('V', 59, struct <link linkend="v4l2-crop">v4l2_crop</link>)
-#define VIDIOC_S_CROP            _IOW('V', 60, struct <link linkend="v4l2-crop">v4l2_crop</link>)
-#define VIDIOC_G_JPEGCOMP        _IOR('V', 61, struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link>)
-#define VIDIOC_S_JPEGCOMP        _IOW('V', 62, struct <link linkend="v4l2-jpegcompression">v4l2_jpegcompression</link>)
-#define VIDIOC_QUERYSTD          _IOR('V', 63, v4l2_std_id)
-#define VIDIOC_TRY_FMT          _IOWR('V', 64, struct <link linkend="v4l2-format">v4l2_format</link>)
-#define VIDIOC_ENUMAUDIO        _IOWR('V', 65, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_ENUMAUDOUT       _IOWR('V', 66, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_G_PRIORITY        _IOR('V', 67, enum <link linkend="v4l2-priority">v4l2_priority</link>)
-#define VIDIOC_S_PRIORITY        _IOW('V', 68, enum <link linkend="v4l2-priority">v4l2_priority</link>)
-#define VIDIOC_G_SLICED_VBI_CAP _IOWR('V', 69, struct <link linkend="v4l2-sliced-vbi-cap">v4l2_sliced_vbi_cap</link>)
-#define VIDIOC_LOG_STATUS         _IO('V', 70)
-#define VIDIOC_G_EXT_CTRLS      _IOWR('V', 71, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#define VIDIOC_S_EXT_CTRLS      _IOWR('V', 72, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#define VIDIOC_TRY_EXT_CTRLS    _IOWR('V', 73, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#if 1
-#define VIDIOC_ENUM_FRAMESIZES  _IOWR('V', 74, struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link>)
-#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link>)
-#define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link>)
-#define VIDIOC_ENCODER_CMD      _IOWR('V', 77, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
-#define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
-#endif
-
-#if 1
-/* Experimental, meant for debugging, testing and internal use.
-   Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
-   You must be root to use these ioctls. Never use these in applications! */
-#define VIDIOC_DBG_S_REGISTER    _IOW('V', 79, struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link>)
-#define VIDIOC_DBG_G_REGISTER   _IOWR('V', 80, struct <link linkend="v4l2-dbg-register">v4l2_dbg_register</link>)
-
-/* Experimental, meant for debugging, testing and internal use.
-   Never use this ioctl in applications! */
-#define VIDIOC_DBG_G_CHIP_IDENT _IOWR('V', 81, struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link>)
-#endif
-
-#define VIDIOC_S_HW_FREQ_SEEK    _IOW('V', 82, struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link>)
-#define VIDIOC_ENUM_DV_PRESETS  _IOWR('V', 83, struct <link linkend="v4l2-dv-enum-preset">v4l2_dv_enum_preset</link>)
-#define VIDIOC_S_DV_PRESET      _IOWR('V', 84, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_G_DV_PRESET      _IOWR('V', 85, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_QUERY_DV_PRESET  _IOR('V',  86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
-#define VIDIOC_S_DV_TIMINGS     _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
-#define VIDIOC_G_DV_TIMINGS     _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
-#define VIDIOC_DQEVENT           _IOR('V', 89, struct <link linkend="v4l2-event">v4l2_event</link>)
-#define VIDIOC_SUBSCRIBE_EVENT   _IOW('V', 90, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
-#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
-
-/* Reminder: when adding new ioctls please add support for them to
-   drivers/media/video/v4l2-compat-ioctl32.c as well! */
-
-#define BASE_VIDIOC_PRIVATE     192             /* 192-255 are private */
-
-#endif /* __LINUX_VIDEODEV2_H */
-</programlisting>
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index a6b3430..c419902 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -583,6 +583,39 @@
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
+The PM core always increments the run-time usage counter before calling the
+->suspend() callback and decrements it after calling the ->resume() callback.
+Hence disabling run-time PM temporarily like this will not cause any runtime
+suspend attempts to be permanently lost.  If the usage count goes to zero
+following the return of the ->resume() callback, the ->runtime_idle() callback
+will be invoked as usual.
+
+On some systems, however, system sleep is not entered through a global firmware
+or hardware operation.  Instead, all hardware components are put into low-power
+states directly by the kernel in a coordinated way.  Then, the system sleep
+state effectively follows from the states the hardware components end up in
+and the system is woken up from that state by a hardware interrupt or a similar
+mechanism entirely under the kernel's control.  As a result, the kernel never
+gives control away and the states of all devices during resume are precisely
+known to it.  If that is the case and none of the situations listed above takes
+place (in particular, if the system is not waking up from hibernation), it may
+be more efficient to leave the devices that had been suspended before the system
+suspend began in the suspended state.
+
+The PM core does its best to reduce the probability of race conditions between
+the runtime PM and system suspend/resume (and hibernation) callbacks by carrying
+out the following operations:
+
+  * During system suspend it calls pm_runtime_get_noresume() and
+    pm_runtime_barrier() for every device right before executing the
+    subsystem-level .suspend() callback for it.  In addition to that it calls
+    pm_runtime_disable() for every device right after executing the
+    subsystem-level .suspend() callback for it.
+
+  * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync()
+    for every device right before and right after executing the subsystem-level
+    .resume() callback for it, respectively.
+
 7. Generic subsystem callbacks
 
 Subsystems may wish to conserve code space by using the set of generic power
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 7fa8099..dc2db27 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -426,6 +426,7 @@
 CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 621e066..ba616b0 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -91,6 +91,7 @@
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L1_ERR_PANIC=y
+CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
 CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_DCVS=y
@@ -433,6 +434,7 @@
 CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_MSM_SSBI=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 9429250..601f235 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -206,10 +206,6 @@
 CONFIG_REGULATOR_GPIO=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
-CONFIG_FB=y
-CONFIG_FB_MSM=y
-CONFIG_FB_MSM_MDP_NONE=y
-CONFIG_FB_MSM_EBI2_PANEL_DETECT=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e94ad3a..33c84a6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1260,6 +1260,13 @@
 
 	  If in doubt, say yes.
 
+config MSM_IPC_LOGGING
+	bool "MSM Debug Logging for IPC Drivers"
+	help
+	  This option allows the debug logging for IPC Drivers.
+
+	  If in doubt, say no.
+
 config MSM_SMD_NMEA
 	bool "NMEA GPS Driver"
 	depends on MSM_SMD
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index c71d270..fec1b4f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -83,6 +83,10 @@
 obj-$(CONFIG_MSM_SDIO_DMUX) += sdio_dmux.o
 obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o
 obj-$(CONFIG_MSM_SMD_LOGGING) += smem_log.o
+obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging.o
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging_debug.o
+endif
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o
 obj-y += socinfo.o
 ifndef CONFIG_ARCH_MSM9615
@@ -145,7 +149,7 @@
 obj-$(CONFIG_MSM_AUDIO_QDSP6) += qdsp6v2/
 obj-$(CONFIG_MSM_HW3D) += hw3d.o
 obj-$(CONFIG_PM) += pm-boot.o
-obj-$(CONFIG_MSM_PM8X60) += pm-8x60.o
+obj-$(CONFIG_MSM_PM8X60) += pm-8x60.o pm-data.o
 obj-$(CONFIG_MSM_PM2) += pm2.o
 obj-$(CONFIG_MSM_PM) += pm.o
 obj-$(CONFIG_MSM_NOPM) += no-pm.o
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 2960a8b..77e7dab 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -123,4 +123,5 @@
 	.pc_sf_lut		= &palladium_1500_pc_sf,
 	.rbatt_sf_lut		= &palladium_1500_rbatt_sf,
 	.default_rbatt_mohm	= 254,
+	.delta_rbatt_mohm	= 60,
 };
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 5d1f3e8..3723da8 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -418,15 +418,16 @@
 	.i2c_mux_mode = MODE_L,
 };
 
-static struct i2c_board_info imx074_actuator_i2c_info = {
-	I2C_BOARD_INFO("imx074_act", 0x11),
+static struct i2c_board_info msm_act_main_cam_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
-static struct msm_actuator_info imx074_actuator_info = {
-	.board_info     = &imx074_actuator_i2c_info,
+static struct msm_actuator_info msm_act_main_cam_0_info = {
+	.board_info     = &msm_act_main_cam_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_0,
 	.bus_id         = APQ_8064_GSBI4_QUP_I2C_BUS_ID,
 	.vcm_pwd        = 0,
-	.vcm_enable     = 1,
+	.vcm_enable     = 0,
 };
 
 static struct msm_camera_i2c_conf apq8064_front_cam_i2c_conf = {
@@ -462,7 +463,7 @@
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
-	.actuator_info = &imx074_actuator_info
+	.actuator_info = &msm_act_main_cam_0_info,
 };
 static struct msm_camera_csi_lane_params imx091_csi_lane_params = {
 	.csi_lane_assign = 0xE4,
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 4b9931a..8464752 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -518,6 +518,12 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting ap2mdm_wakeup = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct msm_gpiomux_config mdm_configs[] __initdata = {
 	/* AP2MDM_STATUS */
 	{
@@ -554,6 +560,13 @@
 			[GPIOMUX_SUSPENDED] = &ap2mdm_pon_reset_n_cfg,
 		}
 	},
+	/* AP2MDM_WAKEUP */
+	{
+		.gpio = 35,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ap2mdm_wakeup,
+		}
+	},
 };
 
 static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d02b4be..18d4c4b 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -71,7 +71,7 @@
 #include "board-8064.h"
 #include "acpuclock.h"
 #include "spm.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "rpm_resources.h"
 #include "pm.h"
 #include "pm-boot.h"
@@ -892,9 +892,31 @@
 	},
 };
 
+/* enable the level shifter for cs8427 to make sure the I2C
+ * clock is running at 100KHz and voltage levels are at 3.3
+ * and 5 volts
+ */
+static int enable_100KHz_ls(int enable)
+{
+	int ret = 0;
+	if (enable) {
+		ret = gpio_request(SX150X_GPIO(1, 10),
+					"cs8427_100KHZ_ENABLE");
+		if (ret) {
+			pr_err("%s: Failed to request gpio %d\n", __func__,
+				SX150X_GPIO(1, 10));
+			return ret;
+		}
+		gpio_direction_output(SX150X_GPIO(1, 10), 1);
+	} else
+		gpio_free(SX150X_GPIO(1, 10));
+	return ret;
+}
+
 static struct cs8427_platform_data cs8427_i2c_platform_data = {
 	.irq = SX150X_GPIO(1, 4),
 	.reset_gpio = SX150X_GPIO(1, 6),
+	.enable = enable_100KHz_ls,
 };
 
 static struct i2c_board_info cs8427_device_info[] __initdata = {
@@ -911,22 +933,27 @@
 
 static int isa1200_power(int on)
 {
+	int rc = 0;
+
 	gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
 
-	return 0;
+	if (on)
+		rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, true);
+	else
+		rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_NONE, true);
+
+	if (rc) {
+		pr_err("%s: unable to write aux clock register(%d)\n",
+			__func__, rc);
+	}
+
+	return rc;
 }
 
 static int isa1200_dev_setup(bool enable)
 {
 	int rc = 0;
 
-	rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, enable);
-	if (rc) {
-		pr_err("%s: unable to write aux clock register(%d)\n",
-			__func__, rc);
-		return rc;
-	}
-
 	if (!enable)
 		goto free_gpio;
 
@@ -1079,7 +1106,7 @@
 	.disp_maxx		= 1365,
 	.disp_miny		= 0,
 	.disp_maxy		= 767,
-	.irqflags		= IRQF_TRIGGER_FALLING,
+	.irqflags		= IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 	.i2c_pull_up		= true,
 	.reset_gpio		= MXT_TS_RESET_GPIO,
 	.irq_gpio		= MXT_TS_GPIO_IRQ,
@@ -1540,121 +1567,6 @@
 	},
 };
 
-static struct msm_cpuidle_state msm_cstates[] __initdata = {
-	{0, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{0, 2, "C2", "POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-
-	{1, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{2, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{2, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{3, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{3, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-};
-
-static struct msm_pm_platform_data msm_pm_data[] = {
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 0,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 0,
-		.idle_enabled = 1,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 0,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 0,
-		.idle_enabled = 1,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 0,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 0,
-		.idle_enabled = 1,
-		.suspend_enabled = 0,
-	},
-};
-
 static uint8_t spm_wfi_cmd_sequence[] __initdata = {
 	0x03, 0x0f,
 };
@@ -2538,10 +2450,6 @@
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
 	acpuclk_init(&acpuclk_8064_soc_data);
 	msm_spm_l2_init(msm_spm_l2_data);
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	apq8064_epm_adc_init();
 }
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 92e88aa72..12312ee 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -407,15 +407,16 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8930_back_cam_gpio_set_tbl),
 };
 
-static struct i2c_board_info imx074_actuator_i2c_info = {
-	I2C_BOARD_INFO("imx074_act", 0x11),
+static struct i2c_board_info msm_act_main_cam_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
-static struct msm_actuator_info imx074_actuator_info = {
-	.board_info     = &imx074_actuator_i2c_info,
+static struct msm_actuator_info msm_act_main_cam_0_info = {
+	.board_info     = &msm_act_main_cam_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_0,
 	.bus_id         = MSM_8930_GSBI4_QUP_I2C_BUS_ID,
 	.vcm_pwd        = 0,
-	.vcm_enable     = 1,
+	.vcm_enable     = 0,
 };
 
 static struct msm_camera_sensor_flash_data flash_imx074 = {
@@ -447,7 +448,7 @@
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
-	.actuator_info = &imx074_actuator_info
+	.actuator_info = &msm_act_main_cam_0_info,
 };
 
 static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 98f1228..173ec95 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -84,7 +84,7 @@
 #include "pm.h"
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "acpuclock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
@@ -1762,67 +1762,6 @@
 					&msm8960_i2c_qup_gsbi12_pdata;
 }
 
-static struct msm_cpuidle_state msm_cstates[] __initdata = {
-	{0, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{0, 2, "C2", "POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-
-	{1, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-};
-
-static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 0,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 0,
-		.idle_enabled = 1,
-		.suspend_enabled = 0,
-	},
-};
-
 static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
 	{
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
@@ -2075,10 +2014,6 @@
 	msm8930_init_fb();
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	change_memory_power = &msm8930_change_memory_power;
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index c2a378f..a3d9cba 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -478,15 +478,16 @@
 	.cam_gpio_set_tbl_size = ARRAY_SIZE(msm8960_back_cam_gpio_set_tbl),
 };
 
-static struct i2c_board_info imx074_actuator_i2c_info = {
-	I2C_BOARD_INFO("imx074_act", 0x11),
+static struct i2c_board_info msm_act_main_cam_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
-static struct msm_actuator_info imx074_actuator_info = {
-	.board_info     = &imx074_actuator_i2c_info,
+static struct msm_actuator_info msm_act_main_cam_0_info = {
+	.board_info     = &msm_act_main_cam_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_0,
 	.bus_id         = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
 	.vcm_pwd        = 0,
-	.vcm_enable     = 1,
+	.vcm_enable     = 0,
 };
 
 static struct msm_camera_sensor_flash_data flash_imx074 = {
@@ -518,7 +519,7 @@
 	.csi_if	= 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
-	.actuator_info = &imx074_actuator_info
+	.actuator_info = &msm_act_main_cam_0_info,
 };
 
 static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index bfb8be3..2cb923c 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -539,6 +539,9 @@
 			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
 		},
 	},
+};
+
+static struct msm_gpiomux_config msm8960_hsic_hub_configs[] = {
 	{
 		.gpio = 91,               /* HSIC_HUB_RESET */
 		.settings = {
@@ -706,6 +709,11 @@
 		(PLATFORM_IS_CHARM25() || machine_is_msm8960_liquid()))
 		msm_gpiomux_install(msm8960_hsic_configs,
 			ARRAY_SIZE(msm8960_hsic_configs));
+
+	if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) &&
+			machine_is_msm8960_liquid())
+		msm_gpiomux_install(msm8960_hsic_hub_configs,
+			ARRAY_SIZE(msm8960_hsic_hub_configs));
 #endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 3bf1297..c9a5f77 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -444,6 +444,7 @@
 	.v_failure		= 3000,
 	.calib_delay_ms		= 600000,
 	.max_voltage_uv		= MAX_VOLTAGE_MV * 1000,
+	.rconn_mohm		= 30,
 };
 
 #define	PM8921_LC_LED_MAX_CURRENT	4	/* I = 4mA */
@@ -617,4 +618,7 @@
 	} else if (machine_is_msm8960_mtp()) {
 		pm8921_platform_data.bms_pdata->battery_type = BATT_PALLADIUM;
 	}
+
+	if (machine_is_msm8960_fluid())
+		pm8921_bms_pdata.rconn_mohm = 20;
 }
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 64fa69f..ed47ae2 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -174,7 +174,7 @@
 	REGULATOR_SUPPLY("CDC_VDDA_TX",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("CDC_VDDA_RX",		"tabla2x-slim"),
 	REGULATOR_SUPPLY("vcc_i2c",		"3-005b"),
-	REGULATOR_SUPPLY("EXT_HUB_VDDIO",	"msm_hsic_host"),
+	REGULATOR_SUPPLY("EXT_HUB_VDDIO",	"msm_smsc_hub"),
 	REGULATOR_SUPPLY("vcc_i2c",		"10-0048"),
 };
 VREG_CONSUMERS(S5) = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 106d2ef..c677d97 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -74,6 +74,7 @@
 #include <linux/mfd/wcd9xxx/pdata.h>
 #endif
 
+#include <linux/smsc3503.h>
 #include <linux/ion.h>
 #include <mach/ion.h>
 #include <mach/mdm2.h>
@@ -92,7 +93,7 @@
 #include "pm.h"
 #include <mach/cpuidle.h>
 #include "rpm_resources.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "acpuclock.h"
 #include "smd_private.h"
 #include "pm-boot.h"
@@ -1302,10 +1303,23 @@
 	.strobe		= 150,
 	.data		= 151,
 };
+
+static struct smsc_hub_platform_data hsic_hub_pdata = {
+	.hub_reset		= HSIC_HUB_RESET_GPIO,
+};
 #else
 static struct msm_hsic_host_platform_data msm_hsic_pdata;
+static struct smsc_hub_platform_data hsic_hub_pdata;
 #endif
 
+static struct platform_device smsc_hub_device = {
+	.name	= "msm_smsc_hub",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &hsic_hub_pdata,
+	},
+};
+
 #define PID_MAGIC_ID		0x71432909
 #define SERIAL_NUM_MAGIC_ID	0x61945374
 #define SERIAL_NUMBER_LENGTH	127
@@ -2421,68 +2435,6 @@
 	}
 }
 
-static struct msm_cpuidle_state msm_cstates[] __initdata = {
-
-	{0, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{0, 2, "C2", "POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-
-	{1, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-};
-
-static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 0,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 0,
-		.idle_enabled = 1,
-		.suspend_enabled = 0,
-	},
-};
-
 static struct msm_rpmrs_level msm_rpmrs_levels[] = {
 	{
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
@@ -2651,6 +2603,17 @@
 }
 EXPORT_SYMBOL(peripheral_disconnect);
 
+static void __init msm8960_init_smsc_hub(void)
+{
+	uint32_t version = socinfo_get_version();
+
+	if (SOCINFO_VERSION_MAJOR(version) == 1)
+		return;
+
+	if (machine_is_msm8960_liquid())
+		platform_device_register(&smsc_hub_device);
+}
+
 static void __init msm8960_init_hsic(void)
 {
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
@@ -2821,10 +2784,6 @@
 	msm8960_init_fb();
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 }
@@ -2853,10 +2812,6 @@
 	msm8960_init_fb();
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 }
@@ -2887,13 +2842,10 @@
 	}
 	msm_otg_pdata.swfi_latency =
 		msm_rpmrs_levels[0].latency_us;
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-	if (machine_is_msm8960_liquid()) {
-		if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
-			msm_hsic_pdata.hub_reset = HSIC_HUB_RESET_GPIO;
-	}
-#endif
 	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2 &&
+					machine_is_msm8960_liquid())
+		msm_device_hsic_host.dev.parent = &smsc_hub_device.dev;
 	msm8960_init_gpiomux();
 	msm8960_device_qup_spi_gsbi1.dev.platform_data =
 				&msm8960_qup_spi_gsbi1_pdata;
@@ -2923,6 +2875,7 @@
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
+	msm8960_init_smsc_hub();
 	msm8960_init_hsic();
 	msm8960_init_cam();
 	msm8960_init_mmc();
@@ -2934,10 +2887,6 @@
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
 	msm8960_init_dsps();
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	change_memory_power = &msm8960_change_memory_power;
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 8a8e575..6c6a5c2 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -268,37 +268,6 @@
 	},
 };
 
-static  struct msm_cpuidle_state msm_cstates[] __initdata = {
-	{0, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{0, 2, "C2", "POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-};
-static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR] = {
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-};
-
 static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
 	.mode = MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR,
 	.v_addr = MSM_APCS_GLB_BASE +  0x24,
@@ -795,10 +764,6 @@
 	msm9615_init_mmc();
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_APCC_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-						msm_pm_data);
 	msm_pm_boot_pdata.p_addr = allocate_contiguous_ebi_nomap(SZ_8, SZ_64K);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 	msm_tsens_early_init(&msm_tsens_pdata);
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 94b8710..f7333b9 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -114,18 +114,17 @@
 	.is_csic = 1,
 };
 
-#ifdef CONFIG_DW9712_ACT
-static struct i2c_board_info s5k4e1_actuator_i2c_info = {
-	I2C_BOARD_INFO("dw9712_act", 0x8C >> 1),
+static struct i2c_board_info msm_act_main_cam_i2c_info = {
+	I2C_BOARD_INFO("msm_actuator", 0x11),
 };
 
-static struct msm_actuator_info s5k4e1_actuator_info = {
-	.board_info     = &s5k4e1_actuator_i2c_info,
+static struct msm_actuator_info msm_act_main_cam_4_info = {
+	.board_info     = &msm_act_main_cam_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_4,
 	.bus_id         = MSM_GSBI0_QUP_I2C_BUS_ID,
 	.vcm_pwd        = GPIO_CAM_GP_CAM_PWDN,
 	.vcm_enable     = 1,
 };
-#endif
 
 #ifdef CONFIG_S5K4E1
 static struct msm_camera_sensor_flash_data flash_s5k4e1 = {
@@ -150,9 +149,7 @@
 	.csi_if                 = 1,
 	.camera_type = BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
-#ifdef CONFIG_DW9712_ACT
-	.actuator_info = &s5k4e1_actuator_info
-#endif
+	.actuator_info = &msm_act_main_cam_4_info,
 };
 #endif
 
@@ -185,18 +182,13 @@
 
 #ifdef CONFIG_OV5647
 
-#ifdef CONFIG_AD5046_ACT
-static struct i2c_board_info ad5046_actuator_i2c_info = {
-	I2C_BOARD_INFO("ad5046_act", 0x18 >> 1),
-};
-
-static struct msm_actuator_info ad5046_actuator_info = {
-	.board_info     = &ad5046_actuator_i2c_info,
+static struct msm_actuator_info msm_act_main_cam_5_info = {
+	.board_info     = &msm_act_main_cam_i2c_info,
+	.cam_name   = MSM_ACTUATOR_MAIN_CAM_5,
 	.bus_id         = MSM_GSBI0_QUP_I2C_BUS_ID,
 	.vcm_pwd        = GPIO_SKU3_CAM_5MP_CAM_DRIVER_PWDN,
 	.vcm_enable     = 1,
 };
-#endif
 
 static struct msm_camera_sensor_platform_info sensor_board_info_ov5647 = {
 	.mount_angle = 90,
@@ -228,10 +220,7 @@
 	.csi_if                 = 1,
 	.camera_type	= BACK_CAMERA_2D,
 	.sensor_type = BAYER_SENSOR,
-
-#ifdef CONFIG_AD5046_ACT
-	.actuator_info = &ad5046_actuator_info
-#endif
+	.actuator_info = &msm_act_main_cam_5_info,
 };
 
 #endif
@@ -309,6 +298,8 @@
 		platform_device_register(&msm7x27a_device_csic0);
 		platform_device_register(&msm7x27a_device_csic1);
 	}
+	if (machine_is_msm8625_evb())
+		*(int *) msm7x27a_device_clkctl.dev.platform_data = 1;
 	platform_device_register(&msm7x27a_device_clkctl);
 	platform_device_register(&msm7x27a_device_vfe);
 }
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index e2076f8..af3d187 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -28,11 +28,13 @@
 #include "board-msm7627a.h"
 
 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
-#define MSM_FB_SIZE		0x2FD000
-#define MSM7x25A_MSM_FB_SIZE    0xE1000
+#define MSM_FB_SIZE		0x4BF000
+#define MSM7x25A_MSM_FB_SIZE    0x1C2000
+#define MSM8x25_MSM_FB_SIZE	0x5FA000
 #else
-#define MSM_FB_SIZE	     0x196000
-#define MSM7x25A_MSM_FB_SIZE    0x96000
+#define MSM_FB_SIZE		0x32A000
+#define MSM7x25A_MSM_FB_SIZE	0x12C000
+#define MSM8x25_MSM_FB_SIZE	0x3FC000
 #endif
 
 /*
@@ -685,7 +687,7 @@
 };
 
 static struct msm_panel_common_pdata mipi_NT35516_pdata = {
-	.pmic_backlight = NULL,
+	.pmic_backlight = evb_backlight_control,
 };
 
 static struct platform_device mipi_dsi_NT35516_panel_device = {
@@ -730,8 +732,11 @@
 
 	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa())
 		fb_size = MSM7x25A_MSM_FB_SIZE;
+	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
+		fb_size = MSM8x25_MSM_FB_SIZE;
 	else
 		fb_size = MSM_FB_SIZE;
+
 	addr = alloc_bootmem_align(fb_size, 0x1000);
 	msm_fb_resources[0].start = __pa(addr);
 	msm_fb_resources[0].end = msm_fb_resources[0].start + fb_size - 1;
@@ -1279,6 +1284,7 @@
 				ARRAY_SIZE(qrd_fb_devices));
 	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
 		mipi_NT35510_pdata.bl_lock = 1;
+		mipi_NT35516_pdata.bl_lock = 1;
 		platform_add_devices(evb_fb_devices,
 				ARRAY_SIZE(evb_fb_devices));
 	} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 6a0e5df..8e02093 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -90,7 +90,7 @@
 #include "devices-msm8x60.h"
 #include <mach/cpuidle.h>
 #include "pm.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "spm.h"
 #include "rpm_log.h"
 #include "timer.h"
@@ -799,67 +799,6 @@
 };
 #endif
 
-static struct msm_pm_platform_data msm_pm_data[MSM_PM_SLEEP_MODE_NR * 2] = {
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 0,
-		.suspend_enabled = 0,
-	},
-
-	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
-		.idle_supported = 1,
-		.suspend_supported = 1,
-		.idle_enabled = 1,
-		.suspend_enabled = 1,
-	},
-};
-
-static struct msm_cpuidle_state msm_cstates[] __initdata = {
-	{0, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-
-	{0, 2, "C2", "POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
-
-	{1, 0, "C0", "WFI",
-		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
-
-	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
-		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
-};
-
 static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
 	{
 		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
@@ -10507,10 +10446,6 @@
 	}
 #endif
 
-	msm_pm_set_platform_data(msm_pm_data, ARRAY_SIZE(msm_pm_data));
-	msm_pm_set_rpm_wakeup_irq(RPM_SCSS_CPU0_WAKE_UP_IRQ);
-	msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
-				msm_pm_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
 
 	pm8058_gpios_init();
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index ac38774..4a6b150 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -126,7 +126,7 @@
 };
 
 #ifdef CONFIG_ARCH_MSM7X27A
-#define MSM_PMEM_MDP_SIZE       0x1DD1000
+#define MSM_PMEM_MDP_SIZE       0x2300000
 #define MSM_PMEM_ADSP_SIZE      0x1100000
 #endif
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 9ce10df9..bbe7bae 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1257,7 +1257,6 @@
 	F_GP( 96000000, pll8, 4, 0, 0),
 	F_GP(128000000, pll8, 3, 0, 0),
 	F_GP(192000000, pll8, 2, 0, 0),
-	F_GP(384000000, pll8, 1, 0, 0),
 	F_END
 };
 
@@ -3345,7 +3344,6 @@
 	F_GFX3D(200000000, pll2,  1,  4),
 	F_GFX3D(228571000, pll2,  2,  7),
 	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(300000000, pll3,  1,  4),
 	F_GFX3D(320000000, pll2,  2,  5),
 	F_GFX3D(400000000, pll2,  1,  2),
 	F_GFX3D(450000000, pll15, 1,  2),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 8e244eb..6c85450 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3121,11 +3121,11 @@
 static DEFINE_CLK_VOTER(dfab_sdc4_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_sdc5_clk, &dfab_clk.c, 0);
 static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c, 0);
+static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c, 0);
 
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ebi1_adm0_clk,   &ebi1_clk.c, 0);
 static DEFINE_CLK_VOTER(ebi1_adm1_clk,   &ebi1_clk.c, 0);
-
 static DEFINE_CLK_MEASURE(sc0_m_clk);
 static DEFINE_CLK_MEASURE(sc1_m_clk);
 static DEFINE_CLK_MEASURE(l2_m_clk);
@@ -3716,6 +3716,7 @@
 	CLK_LOOKUP("bus_clk",		dfab_sdc4_clk.c, "msm_sdcc.4"),
 	CLK_LOOKUP("bus_clk",		dfab_sdc5_clk.c, "msm_sdcc.5"),
 	CLK_LOOKUP("bus_clk",		dfab_scm_clk.c,	"scm"),
+	CLK_LOOKUP("bus_clk",		dfab_qseecom_clk.c,	"qseecom"),
 
 	CLK_LOOKUP("mem_clk",		ebi1_adm0_clk.c, "msm_dmov.0"),
 	CLK_LOOKUP("mem_clk",		ebi1_adm1_clk.c, "msm_dmov.1"),
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 54b13e6..e8c3e05 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -148,8 +148,6 @@
 
 int __init clock_debug_init(struct clock_init_data *data)
 {
-	int ret = 0;
-
 	debugfs_base = debugfs_create_dir("clk", NULL);
 	if (!debugfs_base)
 		return -ENOMEM;
@@ -162,12 +160,10 @@
 	num_msm_clocks = data->size;
 
 	measure = clk_get_sys("debug", "measure");
-	if (IS_ERR(measure)) {
-		ret = PTR_ERR(measure);
+	if (IS_ERR(measure))
 		measure = NULL;
-	}
 
-	return ret;
+	return 0;
 }
 
 
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 6512872..63534a4 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -88,13 +88,13 @@
 	struct cpufreq_work_struct *cpu_work = NULL;
 	cpumask_var_t mask;
 
-	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
-		return -ENOMEM;
-
 	if (!cpu_active(policy->cpu)) {
 		pr_info("cpufreq: cpu %d is not active.\n", policy->cpu);
 		return -ENODEV;
 	}
+
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
+		return -ENOMEM;
 #endif
 
 	mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
@@ -138,13 +138,15 @@
 		wait_for_completion(&cpu_work->complete);
 	}
 
-	free_cpumask_var(mask);
 	ret = cpu_work->status;
 #else
 	ret = set_cpu_freq(policy, table[index].frequency);
 #endif
 
 done:
+#ifdef CONFIG_SMP
+	free_cpumask_var(mask);
+#endif
 	mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex);
 	return ret;
 }
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index cccba2d..4ba3f95 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -26,6 +26,36 @@
 	.owner = THIS_MODULE,
 };
 
+static struct msm_cpuidle_state msm_cstates[] = {
+	{0, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{0, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{0, 2, "C2", "POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE},
+
+	{1, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{1, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{2, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{2, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+
+	{3, 0, "C0", "WFI",
+		MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT},
+
+	{3, 1, "C1", "STANDALONE_POWER_COLLAPSE",
+		MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE},
+};
+
+
 #ifdef CONFIG_MSM_SLEEP_STATS
 static DEFINE_PER_CPU(struct atomic_notifier_head, msm_cpuidle_notifiers);
 
@@ -81,8 +111,7 @@
 	return ret;
 }
 
-void __init msm_cpuidle_set_states(struct msm_cpuidle_state *states,
-	int nr_states, struct msm_pm_platform_data *pm_data)
+static void __init msm_cpuidle_set_states(void)
 {
 	unsigned int cpu;
 
@@ -93,8 +122,8 @@
 		dev->cpu = cpu;
 		dev->prepare = msm_pm_idle_prepare;
 
-		for (i = 0; i < nr_states; i++) {
-			struct msm_cpuidle_state *cstate = &states[i];
+		for (i = 0; i < ARRAY_SIZE(msm_cstates); i++) {
+			struct msm_cpuidle_state *cstate = &msm_cstates[i];
 			struct cpuidle_state *state;
 			struct msm_pm_platform_data *pm_mode;
 
@@ -102,7 +131,8 @@
 				continue;
 
 			state = &dev->states[cstate->state_nr];
-			pm_mode = &pm_data[MSM_PM_MODE(cpu, cstate->mode_nr)];
+			pm_mode = &msm_pm_sleep_modes[
+				MSM_PM_MODE(cpu, cstate->mode_nr)];
 
 			snprintf(state->name, CPUIDLE_NAME_LEN, cstate->name);
 			snprintf(state->desc, CPUIDLE_DESC_LEN, cstate->desc);
@@ -127,6 +157,7 @@
 	unsigned int cpu;
 	int ret;
 
+	msm_cpuidle_set_states();
 	ret = cpuidle_register_driver(&msm_cpuidle_driver);
 	if (ret)
 		pr_err("%s: failed to register cpuidle driver: %d\n",
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index aef5cfd..5d6a3ae 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -39,7 +39,7 @@
 #include "msm_watchdog.h"
 #include "rpm_stats.h"
 #include "rpm_log.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 
 /* Address of GSBI blocks */
 #define MSM_GSBI1_PHYS		0x12440000
@@ -1730,6 +1730,7 @@
 	},
 	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
 	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+	.irq_wakeup = RPM_APCC_CPU0_WAKE_UP_IRQ,
 	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
 	.ipc_rpm_val = 4,
 	.target_id =  {
@@ -2157,6 +2158,7 @@
 #define MDM2AP_STATUS			49
 #define AP2MDM_STATUS			48
 #define AP2MDM_PMIC_RESET_N		27
+#define AP2MDM_WAKEUP			35
 
 static struct resource mdm_resources[] = {
 	{
@@ -2189,6 +2191,12 @@
 		.name	= "AP2MDM_PMIC_RESET_N",
 		.flags	= IORESOURCE_IO,
 	},
+	{
+		.start	= AP2MDM_WAKEUP,
+		.end	= AP2MDM_WAKEUP,
+		.name	= "AP2MDM_WAKEUP",
+		.flags	= IORESOURCE_IO,
+	},
 };
 
 struct platform_device mdm_8064_device = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index da3574b..85e927e 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -28,7 +28,7 @@
 #include "rpm_stats.h"
 
 #ifdef CONFIG_MSM_MPM
-#include "mpm.h"
+#include <mach/mpm.h>
 #endif
 
 struct msm_rpm_platform_data msm8930_rpm_data __initdata = {
@@ -40,6 +40,7 @@
 	},
 	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
 	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+	.irq_wakeup = RPM_APCC_CPU0_WAKE_UP_IRQ,
 	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
 	.ipc_rpm_val = 4,
 	.target_id = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index e8e6e37..375aa8d 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -49,7 +49,7 @@
 #include <mach/msm_dcvs.h>
 
 #ifdef CONFIG_MSM_MPM
-#include "mpm.h"
+#include <mach/mpm.h>
 #endif
 #ifdef CONFIG_MSM_DSPS
 #include <mach/msm_dsps.h>
@@ -2984,6 +2984,7 @@
 	},
 	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
 	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+	.irq_wakeup = RPM_APCC_CPU0_WAKE_UP_IRQ,
 	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
 	.ipc_rpm_val = 4,
 	.target_id = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index f7306d2..60bcdce 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -33,7 +33,7 @@
 #include <mach/dma.h>
 #include "pm.h"
 #include "devices.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "spm.h"
 #include "rpm_resources.h"
 #include "msm_watchdog.h"
@@ -905,6 +905,7 @@
 	},
 	.irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
 	.irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+	.irq_wakeup = RPM_APCC_CPU0_WAKE_UP_IRQ,
 	.ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
 	.ipc_rpm_val = 4,
 	.target_id = {
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 917500c..1391981 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -608,6 +608,7 @@
 };
 
 #ifdef CONFIG_MSM_CAMERA_V4L2
+static int apps_reset;
 static struct resource msm_csic0_resources[] = {
 	{
 		.name   = "csic",
@@ -665,6 +666,9 @@
 	.id             = 0,
 	.resource       = msm_clkctl_resources,
 	.num_resources  = ARRAY_SIZE(msm_clkctl_resources),
+	.dev = {
+		.platform_data = &apps_reset,
+	},
 };
 
 struct platform_device msm7x27a_device_vfe = {
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index ba333ed..608ca27 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -54,7 +54,7 @@
 #include <sound/apr_audio.h>
 #include "rpm_log.h"
 #include "rpm_stats.h"
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "msm_watchdog.h"
 
 /* Address of GSBI blocks */
@@ -2582,6 +2582,7 @@
 	},
 	.irq_ack = RPM_SCSS_CPU0_GP_HIGH_IRQ,
 	.irq_err = RPM_SCSS_CPU0_GP_LOW_IRQ,
+	.irq_wakeup = RPM_SCSS_CPU0_WAKE_UP_IRQ,
 	.ipc_rpm_reg = MSM_GCC_BASE + 0x008,
 	.ipc_rpm_val = 4,
 	.target_id = {
diff --git a/arch/arm/mach-msm/gpio-v2.c b/arch/arm/mach-msm/gpio-v2.c
index b716a6c..d1766a3 100644
--- a/arch/arm/mach-msm/gpio-v2.c
+++ b/arch/arm/mach-msm/gpio-v2.c
@@ -27,7 +27,7 @@
 
 #include <mach/msm_iomap.h>
 #include <mach/gpiomux.h>
-#include "mpm.h"
+#include <mach/mpm.h>
 
 /* Bits of interest in the GPIO_IN_OUT register.
  */
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index f01b0f7..d0235f3 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -241,8 +241,21 @@
 	struct msm_camera_csi_lane_params *csi_lane_params;
 };
 
+enum msm_camera_actuator_name {
+	MSM_ACTUATOR_MAIN_CAM_0,
+	MSM_ACTUATOR_MAIN_CAM_1,
+	MSM_ACTUATOR_MAIN_CAM_2,
+	MSM_ACTUATOR_MAIN_CAM_3,
+	MSM_ACTUATOR_MAIN_CAM_4,
+	MSM_ACTUATOR_MAIN_CAM_5,
+	MSM_ACTUATOR_WEB_CAM_0,
+	MSM_ACTUATOR_WEB_CAM_1,
+	MSM_ACTUATOR_WEB_CAM_2,
+};
+
 struct msm_actuator_info {
 	struct i2c_board_info const *board_info;
+	enum msm_camera_actuator_name cam_name;
 	int bus_id;
 	int vcm_pwd;
 	int vcm_enable;
@@ -359,6 +372,7 @@
 	uintptr_t hw_revision_addr;
 	int gpio;
 	bool bl_lock;
+	spinlock_t bl_spinlock;
 	int (*backlight_level)(int level, int max, int min);
 	int (*pmic_backlight)(int level);
 	int (*panel_num)(void);
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 5ee9e1a..ef9fbc1 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -343,7 +343,6 @@
 };
 
 struct msm_actuator_ctrl {
-	int (*a_init_table)(void);
 	int (*a_power_up)(void *);
 	int (*a_power_down)(void *);
 	int (*a_create_subdevice)(void *, void *);
@@ -657,6 +656,7 @@
 void msm_camio_camif_pad_reg_reset_2(void);
 
 void msm_camio_vfe_blk_reset(void);
+void msm_camio_vfe_blk_reset_2(int flag);
 
 int32_t msm_camio_3d_enable(const struct msm_camera_sensor_info *sinfo);
 void msm_camio_3d_disable(void);
diff --git a/arch/arm/mach-msm/include/mach/cpuidle.h b/arch/arm/mach-msm/include/mach/cpuidle.h
index d1561f4..654121f 100644
--- a/arch/arm/mach-msm/include/mach/cpuidle.h
+++ b/arch/arm/mach-msm/include/mach/cpuidle.h
@@ -26,14 +26,8 @@
 };
 
 #ifdef CONFIG_CPU_IDLE
-void msm_cpuidle_set_states(struct msm_cpuidle_state *states,
-	int nr_states, struct msm_pm_platform_data *pm_data);
-
 int msm_cpuidle_init(void);
 #else
-static inline void msm_cpuidle_set_states(struct msm_cpuidle_state *states,
-	int nr_states, struct msm_pm_platform_data *pm_data) {}
-
 static inline int msm_cpuidle_init(void)
 { return -ENOSYS; }
 #endif
diff --git a/arch/arm/mach-msm/mpm.h b/arch/arm/mach-msm/include/mach/mpm.h
similarity index 73%
rename from arch/arm/mach-msm/mpm.h
rename to arch/arm/mach-msm/include/mach/mpm.h
index 85761bc..5cf52b9 100644
--- a/arch/arm/mach-msm/mpm.h
+++ b/arch/arm/mach-msm/include/mach/mpm.h
@@ -54,24 +54,25 @@
 void msm_mpm_enter_sleep(bool from_idle);
 void msm_mpm_exit_sleep(bool from_idle);
 #else
-int msm_mpm_enable_irq(unsigned int irq, unsigned int enable)
+static inline int msm_mpm_enable_irq(unsigned int irq, unsigned int enable)
 { return -ENODEV; }
-int msm_mpm_set_irq_wake(unsigned int irq, unsigned int on)
+static inline int msm_mpm_set_irq_wake(unsigned int irq, unsigned int on)
 { return -ENODEV; }
-int msm_mpm_set_irq_type(unsigned int irq, unsigned int flow_type)
+static inline int msm_mpm_set_irq_type(unsigned int irq, unsigned int flow_type)
 { return -ENODEV; }
-int msm_mpm_enable_pin(enum msm_mpm_pin pin, unsigned int enable)
+static inline int msm_mpm_enable_pin(enum msm_mpm_pin pin, unsigned int enable)
 { return -ENODEV; }
-int msm_mpm_set_pin_wake(enum msm_mpm_pin pin, unsigned int on)
+static inline int msm_mpm_set_pin_wake(enum msm_mpm_pin pin, unsigned int on)
 { return -ENODEV; }
-int msm_mpm_set_pin_type(enum msm_mpm_pin pin, unsigned int flow_type)
+static inline int msm_mpm_set_pin_type(enum msm_mpm_pin pin,
+				       unsigned int flow_type)
 { return -ENODEV; }
-bool msm_mpm_irqs_detectable(bool from_idle)
+static inline bool msm_mpm_irqs_detectable(bool from_idle)
 { return false; }
-bool msm_mpm_gpio_irqs_detectable(bool from_idle)
+static inline bool msm_mpm_gpio_irqs_detectable(bool from_idle)
 { return false; }
-void msm_mpm_enter_sleep(bool from_idle) {}
-void msm_mpm_exit_sleep(bool from_idle) {}
+static inline void msm_mpm_enter_sleep(bool from_idle) {}
+static inline void msm_mpm_exit_sleep(bool from_idle) {}
 #endif
 
 
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
index c07de44..3cc2595 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h
@@ -115,7 +115,7 @@
  *		@param0: Did the core iowait
  *		@param1: unused
  *		@ret0: New clock frequency for the core in KHz
- *		@ret1: unused
+ *		@ret1: New QoS timer value for the core in usec
  *	MSM_DCVS_SCM_QOS_TIMER_EXPIRED
  *		@param0: unused
  *		@param1: unused
diff --git a/arch/arm/mach-msm/include/mach/msm_hsusb.h b/arch/arm/mach-msm/include/mach/msm_hsusb.h
index 8dd761c..3069916 100644
--- a/arch/arm/mach-msm/include/mach/msm_hsusb.h
+++ b/arch/arm/mach-msm/include/mach/msm_hsusb.h
@@ -20,6 +20,8 @@
 
 #include <linux/types.h>
 #include <linux/pm_qos_params.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
 
 #define PHY_TYPE_MASK		0x0F
 #define PHY_TYPE_MODE		0xF0
@@ -60,6 +62,21 @@
 #define phy_id_state_c(ints)	(phy_id_state((ints)) == PHY_ID_C)
 #endif
 
+/*
+ * The following are bit fields describing the usb_request.udc_priv word.
+ * These bit fields are set by function drivers that wish to queue
+ * usb_requests with sps/bam parameters.
+ */
+#define MSM_PIPE_ID_MASK		(0x1F)
+#define MSM_TX_PIPE_ID_OFS		(16)
+#define MSM_SPS_MODE			BIT(5)
+#define MSM_IS_FINITE_TRANSFER		BIT(6)
+#define MSM_PRODUCER			BIT(7)
+#define MSM_DISABLE_WB			BIT(8)
+#define MSM_ETD_IOC			BIT(9)
+#define MSM_INTERNAL_MEM		BIT(10)
+#define MSM_VENDOR_ID			BIT(16)
+
 /* used to detect the OTG Mode */
 enum otg_mode {
 	OTG_ID = 0,   		/* ID pin detection */
@@ -185,4 +202,8 @@
 	struct clk *ebi1_clk;
 };
 
+int msm_ep_config(struct usb_ep *ep);
+int msm_ep_unconfig(struct usb_ep *ep);
+int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size);
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_logging.h b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
new file mode 100644
index 0000000..0a203a5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_logging.h
@@ -0,0 +1,235 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MSM_IPC_LOGGING_H
+#define _MSM_IPC_LOGGING_H
+
+#include <linux/types.h>
+
+#define MAX_MSG_SIZE 255
+
+enum {
+	TSV_TYPE_MSG_START = 1,
+	TSV_TYPE_SKB = TSV_TYPE_MSG_START,
+	TSV_TYPE_STRING,
+	TSV_TYPE_MSG_END = TSV_TYPE_STRING,
+};
+
+struct tsv_header {
+	unsigned char type;
+	unsigned char size; /* size of data field */
+};
+
+struct encode_context {
+	struct tsv_header hdr;
+	char buff[MAX_MSG_SIZE];
+	int offset;
+};
+
+struct decode_context {
+	int output_format;      /* 0 = debugfs */
+	char *buff;             /* output buffer */
+	int size;               /* size of output buffer */
+};
+
+#if defined(CONFIG_MSM_IPC_LOGGING)
+/*
+ * ipc_log_context_create: Create a debug log context
+ *                         Should not be called from atomic context
+ *
+ * @max_num_pages: Number of pages of logging space required (max. 10)
+ * @mod_name     : Name of the directory entry under DEBUGFS
+ *
+ * returns context id on success, NULL on failure
+ */
+void *ipc_log_context_create(int max_num_pages, const char *modname);
+
+/*
+ * msg_encode_start: Start encoding a log message
+ *
+ * @ectxt: Temporary storage to hold the encoded message
+ * @type:  Root event type defined by the module which is logging
+ */
+void msg_encode_start(struct encode_context *ectxt, uint32_t type);
+
+/*
+ * tsv_timestamp_write: Writes the current timestamp count
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ */
+int tsv_timestamp_write(struct encode_context *ectxt);
+
+/*
+ * tsv_pointer_write: Writes a data pointer
+ *
+ * @ectxt:   Context initialized by calling msg_encode_start()
+ * @pointer: Pointer value to write
+ */
+int tsv_pointer_write(struct encode_context *ectxt, void *pointer);
+
+/*
+ * tsv_int32_write: Writes a 32-bit integer value
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ * @n:     Integer to write
+ */
+int tsv_int32_write(struct encode_context *ectxt, int32_t n);
+
+/*
+ * tsv_int32_write: Writes a 32-bit integer value
+ *
+ * @ectxt: Context initialized by calling msg_encode_start()
+ * @n:     Integer to write
+ */
+int tsv_byte_array_write(struct encode_context *ectxt,
+			 void *data, int data_size);
+
+/*
+ * msg_encode_end: Complete the message encode process
+ *
+ * @ectxt: Temporary storage which holds the encoded message
+ */
+void msg_encode_end(struct encode_context *ectxt);
+
+/*
+ * msg_encode_end: Complete the message encode process
+ *
+ * @ectxt: Temporary storage which holds the encoded message
+ */
+void ipc_log_write(void *ctxt, struct encode_context *ectxt);
+
+/*
+ * ipc_log_string: Helper function to log a string
+ *
+ * @ilctxt: Debug Log Context created using ipc_log_context_create()
+ * @fmt:    Data specified using format specifiers
+ */
+int ipc_log_string(void *ilctxt, const char *fmt, ...);
+
+/*
+ * Print a string to decode context.
+ * @dctxt   Decode context
+ * @args   printf args
+ */
+#define IPC_SPRINTF_DECODE(dctxt, args...) \
+do { \
+	int i; \
+	i = scnprintf(dctxt->buff, dctxt->size, args); \
+	dctxt->buff += i; \
+	dctxt->size -= i; \
+} while (0)
+
+/*
+ * tsv_timestamp_read: Reads a timestamp
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_timestamp_read(struct encode_context *ectxt,
+			struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_pointer_read: Reads a data pointer
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_pointer_read(struct encode_context *ectxt,
+		      struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_int32_read: Reads a 32-bit integer value
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+int32_t tsv_int32_read(struct encode_context *ectxt,
+		       struct decode_context *dctxt, const char *format);
+
+/*
+ * tsv_int32_read: Reads a 32-bit integer value
+ *
+ * @ectxt:  Context retrieved by reading from log space
+ * @dctxt:  Temporary storage to hold the decoded message
+ * @format: Output format while dumping through DEBUGFS
+ */
+void tsv_byte_array_read(struct encode_context *ectxt,
+			 struct decode_context *dctxt, const char *format);
+
+/*
+ * add_deserialization_func: Register a deserialization function to
+ *                           to unpack the subevents of a main event
+ *
+ * @ctxt: Debug log context to which the deserialization function has
+ *        to be registered
+ * @type: Main/Root event, defined by the module which is logging, to
+ *        which this deserialization function has to be registered.
+ * @dfune: Deserialization function to be registered
+ *
+ * return 0 on success, -ve value on FAILURE
+ */
+int add_deserialization_func(void *ctxt, int type,
+			void (*dfunc)(struct encode_context *,
+				      struct decode_context *));
+#else
+
+void *ipc_log_context_create(int max_num_pages, const char *modname)
+{ return NULL; }
+
+void msg_encode_start(struct encode_context *ectxt, uint32_t type) { }
+
+int tsv_timestamp_write(struct encode_context *ectxt)
+{ return -EINVAL; }
+
+int tsv_pointer_write(struct encode_context *ectxt, void *pointer)
+{ return -EINVAL; }
+
+int tsv_int32_write(struct encode_context *ectxt, int32_t n)
+{ return -EINVAL; }
+
+int tsv_byte_array_write(struct encode_context *ectxt,
+			 void *data, int data_size)
+{ return -EINVAL; }
+
+void msg_encode_end(struct encode_context *ectxt) { }
+
+void ipc_log_write(void *ctxt, struct encode_context *ectxt) { }
+
+int ipc_log_string(void *ilctxt, const char *fmt, ...)
+{ return -EINVAL; }
+
+#define IPC_SPRINTF_DECODE(dctxt, args...) do { } while (0)
+
+void tsv_timestamp_read(struct encode_context *ectxt,
+			struct decode_context *dctxt, const char *format) { }
+
+void tsv_pointer_read(struct encode_context *ectxt,
+		      struct decode_context *dctxt, const char *format) { }
+
+int32_t tsv_int32_read(struct encode_context *ectxt,
+		       struct decode_context *dctxt, const char *format)
+{ return 0; }
+
+void tsv_byte_array_read(struct encode_context *ectxt,
+			 struct decode_context *dctxt, const char *format) { }
+
+int add_deserialization_func(void *ctxt, int type,
+			void (*dfunc)(struct encode_context *,
+				      struct decode_context *))
+{ return 0; }
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 140b7c9..98621be 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -883,6 +883,7 @@
 	void __iomem *reg_base_addrs[MSM_RPM_PAGE_COUNT];
 	unsigned int irq_ack;
 	unsigned int irq_err;
+	unsigned int irq_wakeup;
 	void *ipc_rpm_reg;
 	unsigned int ipc_rpm_val;
 	struct msm_rpm_map_data target_id[MSM_RPM_ID_LAST];
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
new file mode 100644
index 0000000..2cd30de
--- /dev/null
+++ b/arch/arm/mach-msm/ipc_logging.c
@@ -0,0 +1,556 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/idr.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+
+#include <mach/msm_ipc_logging.h>
+
+#include "ipc_logging.h"
+
+static LIST_HEAD(ipc_log_context_list);
+DEFINE_SPINLOCK(ipc_log_context_list_lock);
+static atomic_t next_log_id = ATOMIC_INIT(0);
+
+static struct ipc_log_page *get_first_page(struct ipc_log_context *ilctxt)
+{
+	struct ipc_log_page_header *p_pghdr;
+	struct ipc_log_page *pg = NULL;
+
+	if (!ilctxt)
+		return NULL;
+	p_pghdr = list_first_entry(&ilctxt->page_list,
+				   struct ipc_log_page_header, list);
+	pg = container_of(p_pghdr, struct ipc_log_page, hdr);
+	return pg;
+}
+
+static struct ipc_log_page *get_next_page(struct ipc_log_context *ilctxt,
+					  struct ipc_log_page *cur_pg)
+{
+	struct ipc_log_page_header *p_pghdr;
+	struct ipc_log_page *pg = NULL;
+
+	if (!ilctxt || !cur_pg)
+		return NULL;
+
+	if (ilctxt->last_page == cur_pg)
+		return ilctxt->first_page;
+
+	p_pghdr = list_first_entry(&cur_pg->hdr.list,
+			struct ipc_log_page_header, list);
+	pg = container_of(p_pghdr, struct ipc_log_page, hdr);
+
+	return pg;
+}
+
+/* If data == NULL, drop the log of size data_size*/
+static void ipc_log_read(struct ipc_log_context *ilctxt,
+			 void *data, int data_size)
+{
+	int bytes_to_read;
+
+	bytes_to_read = MIN(((PAGE_SIZE - sizeof(struct ipc_log_page_header))
+				- ilctxt->read_page->hdr.read_offset),
+			      data_size);
+	if (data)
+		memcpy(data, (ilctxt->read_page->data +
+			ilctxt->read_page->hdr.read_offset), bytes_to_read);
+	if (bytes_to_read != data_size) {
+		ilctxt->read_page->hdr.read_offset = 0xFFFF;
+		ilctxt->read_page = get_next_page(ilctxt, ilctxt->read_page);
+		ilctxt->read_page->hdr.read_offset = 0;
+		if (data)
+			memcpy((data + bytes_to_read),
+			       (ilctxt->read_page->data +
+				ilctxt->read_page->hdr.read_offset),
+			       (data_size - bytes_to_read));
+		bytes_to_read = (data_size - bytes_to_read);
+	}
+	ilctxt->read_page->hdr.read_offset += bytes_to_read;
+	ilctxt->write_avail += data_size;
+}
+
+/*
+ * Reads a message.
+ *
+ * If a message is read successfully, then the the message context
+ * will be set to:
+ *     .hdr    message header .size and .type values
+ *     .offset beginning of message data
+ *
+ * @ectxt   Message context and if NULL, drops the message.
+ *
+ * @returns 0  - no message available
+ *          1  - message read
+ */
+int msg_read(struct ipc_log_context *ilctxt,
+	     struct encode_context *ectxt)
+{
+	struct tsv_header hdr;
+
+	ipc_log_read(ilctxt, &hdr, sizeof(hdr));
+	if (ectxt) {
+		ectxt->hdr.type = hdr.type;
+		ectxt->hdr.size = hdr.size;
+		ectxt->offset = sizeof(hdr);
+		ipc_log_read(ilctxt, (ectxt->buff + ectxt->offset),
+			     (int)hdr.size);
+	} else {
+		ipc_log_read(ilctxt, NULL, (int)hdr.size);
+	}
+	return sizeof(hdr) + (int)hdr.size;
+}
+
+/*
+ * Commits messages to the FIFO.  If the FIFO is full, then enough
+ * messages are dropped to create space for the new message.
+ */
+void ipc_log_write(void *ctxt, struct encode_context *ectxt)
+{
+	struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt;
+	int bytes_to_write;
+	unsigned long flags;
+
+	if (!ilctxt || !ectxt) {
+		pr_err("%s: Invalid ipc_log or encode context\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	spin_lock(&ilctxt->ipc_log_context_lock);
+	while (ilctxt->write_avail < ectxt->offset)
+		msg_read(ilctxt, NULL);
+
+	bytes_to_write = MIN(((PAGE_SIZE - sizeof(struct ipc_log_page_header))
+				- ilctxt->write_page->hdr.write_offset),
+				ectxt->offset);
+	memcpy((ilctxt->write_page->data +
+		ilctxt->write_page->hdr.write_offset),
+		ectxt->buff, bytes_to_write);
+	if (bytes_to_write != ectxt->offset) {
+		ilctxt->write_page->hdr.write_offset = 0xFFFF;
+		ilctxt->write_page = get_next_page(ilctxt, ilctxt->write_page);
+		ilctxt->write_page->hdr.write_offset = 0;
+		memcpy((ilctxt->write_page->data +
+			ilctxt->write_page->hdr.write_offset),
+		       (ectxt->buff + bytes_to_write),
+		       (ectxt->offset - bytes_to_write));
+		bytes_to_write = (ectxt->offset - bytes_to_write);
+	}
+	ilctxt->write_page->hdr.write_offset += bytes_to_write;
+	ilctxt->write_avail -= ectxt->offset;
+	complete(&ilctxt->read_avail);
+	spin_unlock(&ilctxt->ipc_log_context_lock);
+	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+}
+EXPORT_SYMBOL(ipc_log_write);
+
+/*
+ * Starts a new message after which you can add serialized data and
+ * then complete the message by calling msg_encode_end().
+ */
+void msg_encode_start(struct encode_context *ectxt, uint32_t type)
+{
+	if (!ectxt) {
+		pr_err("%s: Invalid encode context\n", __func__);
+		return;
+	}
+
+	ectxt->hdr.type = type;
+	ectxt->hdr.size = 0;
+	ectxt->offset = sizeof(ectxt->hdr);
+}
+EXPORT_SYMBOL(msg_encode_start);
+
+/*
+ * Completes the message
+ */
+void msg_encode_end(struct encode_context *ectxt)
+{
+	if (!ectxt) {
+		pr_err("%s: Invalid encode context\n", __func__);
+		return;
+	}
+
+	/* finalize data size */
+	ectxt->hdr.size = ectxt->offset - sizeof(ectxt->hdr);
+	BUG_ON(ectxt->hdr.size > MAX_MSG_SIZE);
+	memcpy(ectxt->buff, &ectxt->hdr, sizeof(ectxt->hdr));
+}
+EXPORT_SYMBOL(msg_encode_end);
+
+/*
+ * Helper funtion used to write data to a message context.
+ *
+ * @ectxt context initialized by calling msg_encode_start()
+ * @data  data to write
+ * @size  number of bytes of data to write
+ */
+static inline int tsv_write_data(struct encode_context *ectxt,
+				 void *data, uint32_t size)
+{
+	if (!ectxt) {
+		pr_err("%s: Invalid encode context\n", __func__);
+		return -EINVAL;
+	}
+	if ((ectxt->offset + size) > MAX_MSG_SIZE) {
+		pr_err("%s: No space to encode further\n", __func__);
+		return -EINVAL;
+	}
+
+	memcpy((void *)(ectxt->buff + ectxt->offset), data, size);
+	ectxt->offset += size;
+	return 0;
+}
+
+/*
+ * Helper function that writes a type to the context.
+ *
+ * @ectxt context initialized by calling msg_encode_start()
+ * @type  primitive type
+ * @size  size of primitive in bytes
+ */
+static inline int tsv_write_header(struct encode_context *ectxt,
+				   uint32_t type, uint32_t size)
+{
+	struct tsv_header hdr;
+
+	hdr.type = (unsigned char)type;
+	hdr.size = (unsigned char)size;
+	return tsv_write_data(ectxt, &hdr, sizeof(hdr));
+}
+
+/*
+ * Writes the current timestamp count.
+ *
+ * @ectxt   context initialized by calling msg_encode_start()
+ */
+int tsv_timestamp_write(struct encode_context *ectxt)
+{
+	int ret;
+	unsigned long long t_now = sched_clock();
+
+	ret = tsv_write_header(ectxt, TSV_TYPE_TIMESTAMP, sizeof(t_now));
+	if (ret)
+		return ret;
+	return tsv_write_data(ectxt, &t_now, sizeof(t_now));
+}
+EXPORT_SYMBOL(tsv_timestamp_write);
+
+/*
+ * Writes a data pointer.
+ *
+ * @ectxt   context initialized by calling msg_encode_start()
+ * @pointer pointer value to write
+ */
+int tsv_pointer_write(struct encode_context *ectxt, void *pointer)
+{
+	int ret;
+	ret = tsv_write_header(ectxt, TSV_TYPE_POINTER, sizeof(pointer));
+	if (ret)
+		return ret;
+	return tsv_write_data(ectxt, &pointer, sizeof(pointer));
+}
+EXPORT_SYMBOL(tsv_pointer_write);
+
+/*
+ * Writes a 32-bit integer value.
+ *
+ * @ectxt context initialized by calling msg_encode_start()
+ * @n     integer to write
+ */
+int tsv_int32_write(struct encode_context *ectxt, int32_t n)
+{
+	int ret;
+	ret = tsv_write_header(ectxt, TSV_TYPE_INT32, sizeof(n));
+	if (ret)
+		return ret;
+	return tsv_write_data(ectxt, &n, sizeof(n));
+}
+EXPORT_SYMBOL(tsv_int32_write);
+
+/*
+ * Writes a byte array.
+ *
+ * @ectxt context initialized by calling msg_write_start()
+ * @data  Beginning address of data
+ * @data_size Size of data to be written
+ */
+int tsv_byte_array_write(struct encode_context *ectxt,
+			 void *data, int data_size)
+{
+	int ret;
+	ret = tsv_write_header(ectxt, TSV_TYPE_BYTE_ARRAY, data_size);
+	if (ret)
+		return ret;
+	return tsv_write_data(ectxt, data, data_size);
+}
+EXPORT_SYMBOL(tsv_byte_array_write);
+
+/*
+ * Helper function to log a string
+ *
+ * @ilctxt ipc_log_context created using ipc_log_context_create()
+ * @fmt Data specified using format specifiers
+ */
+int ipc_log_string(void *ilctxt, const char *fmt, ...)
+{
+	struct encode_context ectxt;
+	int avail_size, data_size, hdr_size = sizeof(struct tsv_header);
+	va_list arg_list;
+
+	if (!ilctxt)
+		return -EINVAL;
+
+	msg_encode_start(&ectxt, TSV_TYPE_STRING);
+	tsv_timestamp_write(&ectxt);
+	avail_size = (MAX_MSG_SIZE - (ectxt.offset + hdr_size));
+	va_start(arg_list, fmt);
+	data_size = vsnprintf((ectxt.buff + ectxt.offset + hdr_size),
+			      avail_size, fmt, arg_list);
+	va_end(arg_list);
+	tsv_write_header(&ectxt, TSV_TYPE_BYTE_ARRAY, data_size);
+	ectxt.offset += data_size;
+	msg_encode_end(&ectxt);
+	ipc_log_write(ilctxt, &ectxt);
+	return 0;
+}
+
+/*
+ * Helper funtion used to read data from a message context.
+ *
+ * @ectxt  context initialized by calling msg_read()
+ * @data  data to read
+ * @size  number of bytes of data to read
+ */
+static void tsv_read_data(struct encode_context *ectxt,
+			  void *data, uint32_t size)
+{
+	BUG_ON((ectxt->offset + size) > MAX_MSG_SIZE);
+	memcpy(data, (ectxt->buff + ectxt->offset), size);
+	ectxt->offset += size;
+}
+
+/*
+ * Helper function that reads a type from the context and updates the
+ * context pointers.
+ *
+ * @ectxt  context initialized by calling msg_read()
+ * @hdr   type header
+ */
+static void tsv_read_header(struct encode_context *ectxt,
+			    struct tsv_header *hdr)
+{
+	BUG_ON((ectxt->offset + sizeof(*hdr)) > MAX_MSG_SIZE);
+	memcpy(hdr, (ectxt->buff + ectxt->offset), sizeof(*hdr));
+	ectxt->offset += sizeof(*hdr);
+}
+
+/*
+ * Reads a timestamp.
+ *
+ * @ectxt   context initialized by calling msg_read()
+ * @dctxt   deserialization context
+ * @format output format (appended to %6u.%09u timestamp format)
+ */
+void tsv_timestamp_read(struct encode_context *ectxt,
+			struct decode_context *dctxt, const char *format)
+{
+	struct tsv_header hdr;
+	unsigned long long val;
+	unsigned long nanosec_rem;
+
+	tsv_read_header(ectxt, &hdr);
+	BUG_ON(hdr.type != TSV_TYPE_TIMESTAMP);
+	tsv_read_data(ectxt, &val, sizeof(val));
+	nanosec_rem = do_div(val, 1000000000U);
+	IPC_SPRINTF_DECODE(dctxt, "[%6u.%09lu]%s",
+			(unsigned)val, nanosec_rem, format);
+}
+EXPORT_SYMBOL(tsv_timestamp_read);
+
+/*
+ * Reads a data pointer.
+ *
+ * @ectxt   context initialized by calling msg_read()
+ * @dctxt   deserialization context
+ * @format output format
+ */
+void tsv_pointer_read(struct encode_context *ectxt,
+		      struct decode_context *dctxt, const char *format)
+{
+	struct tsv_header hdr;
+	void *val;
+
+	tsv_read_header(ectxt, &hdr);
+	BUG_ON(hdr.type != TSV_TYPE_POINTER);
+	tsv_read_data(ectxt, &val, sizeof(val));
+
+	IPC_SPRINTF_DECODE(dctxt, format, val);
+}
+EXPORT_SYMBOL(tsv_pointer_read);
+
+/*
+ * Reads a 32-bit integer value.
+ *
+ * @ectxt   context initialized by calling msg_read()
+ * @dctxt   deserialization context
+ * @format output format
+ */
+int32_t tsv_int32_read(struct encode_context *ectxt,
+		       struct decode_context *dctxt, const char *format)
+{
+	struct tsv_header hdr;
+	int32_t val;
+
+	tsv_read_header(ectxt, &hdr);
+	BUG_ON(hdr.type != TSV_TYPE_INT32);
+	tsv_read_data(ectxt, &val, sizeof(val));
+
+	IPC_SPRINTF_DECODE(dctxt, format, val);
+	return val;
+}
+EXPORT_SYMBOL(tsv_int32_read);
+
+/*
+ * Reads a byte array/string.
+ *
+ * @ectxt   context initialized by calling msg_read()
+ * @dctxt   deserialization context
+ * @format output format
+ */
+void tsv_byte_array_read(struct encode_context *ectxt,
+			 struct decode_context *dctxt, const char *format)
+{
+	struct tsv_header hdr;
+
+	tsv_read_header(ectxt, &hdr);
+	BUG_ON(hdr.type != TSV_TYPE_BYTE_ARRAY);
+	tsv_read_data(ectxt, dctxt->buff, hdr.size);
+	dctxt->buff += hdr.size;
+	dctxt->size -= hdr.size;
+}
+EXPORT_SYMBOL(tsv_byte_array_read);
+
+int add_deserialization_func(void *ctxt, int type,
+			void (*dfunc)(struct encode_context *,
+				      struct decode_context *))
+{
+	struct ipc_log_context *ilctxt = (struct ipc_log_context *)ctxt;
+	struct dfunc_info *df_info;
+	unsigned long flags;
+
+	if (!ilctxt || !dfunc)
+		return -EINVAL;
+
+	df_info = kmalloc(sizeof(struct dfunc_info), GFP_KERNEL);
+	if (!df_info)
+		return -ENOSPC;
+
+	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	spin_lock(&ilctxt->ipc_log_context_lock);
+	df_info->type = type;
+	df_info->dfunc = dfunc;
+	list_add_tail(&df_info->list, &ilctxt->dfunc_info_list);
+	spin_unlock(&ilctxt->ipc_log_context_lock);
+	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(add_deserialization_func);
+
+void *ipc_log_context_create(int max_num_pages,
+			     const char *mod_name)
+{
+	struct ipc_log_context *ctxt;
+	struct ipc_log_page *pg = NULL;
+	int page_cnt, local_log_id;
+	unsigned long flags;
+
+	ctxt = kzalloc(sizeof(struct ipc_log_context), GFP_KERNEL);
+	if (!ctxt) {
+		pr_err("%s: cannot create ipc_log_context\n", __func__);
+		return 0;
+	}
+
+	local_log_id = atomic_add_return(1, &next_log_id);
+	init_completion(&ctxt->read_avail);
+	INIT_LIST_HEAD(&ctxt->page_list);
+	INIT_LIST_HEAD(&ctxt->dfunc_info_list);
+	spin_lock_init(&ctxt->ipc_log_context_lock);
+	for (page_cnt = 0; page_cnt < max_num_pages; page_cnt++) {
+		pg = kzalloc(sizeof(struct ipc_log_page), GFP_KERNEL);
+		if (!pg) {
+			pr_err("%s: cannot create ipc_log_page\n", __func__);
+			goto release_ipc_log_context;
+		}
+		pg->hdr.magic = IPC_LOGGING_MAGIC_NUM;
+		pg->hdr.nmagic = ~(IPC_LOGGING_MAGIC_NUM);
+		pg->hdr.log_id = (uint32_t)local_log_id;
+		pg->hdr.page_num = page_cnt;
+		pg->hdr.read_offset = 0xFFFF;
+		pg->hdr.write_offset = 0xFFFF;
+		spin_lock_irqsave(&ctxt->ipc_log_context_lock, flags);
+		list_add_tail(&pg->hdr.list, &ctxt->page_list);
+		spin_unlock_irqrestore(&ctxt->ipc_log_context_lock, flags);
+	}
+	ctxt->first_page = get_first_page(ctxt);
+	ctxt->last_page = pg;
+	ctxt->write_page = ctxt->first_page;
+	ctxt->read_page = ctxt->first_page;
+	ctxt->write_page->hdr.write_offset = 0;
+	ctxt->read_page->hdr.read_offset = 0;
+	ctxt->write_avail = max_num_pages * (PAGE_SIZE -
+					sizeof(struct ipc_log_page_header));
+
+	create_ctx_debugfs(ctxt, mod_name);
+
+	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	list_add_tail(&ctxt->list, &ipc_log_context_list);
+	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	return (void *)ctxt;
+
+release_ipc_log_context:
+	while (page_cnt-- > 0) {
+		pg = get_first_page(ctxt);
+		list_del(&pg->hdr.list);
+		kfree(pg);
+	}
+	kfree(ctxt);
+	return 0;
+}
+EXPORT_SYMBOL(ipc_log_context_create);
+
+static int __init ipc_logging_init(void)
+{
+	check_and_create_debugfs();
+	return 0;
+}
+
+module_init(ipc_logging_init);
+
+MODULE_DESCRIPTION("ipc logging");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
new file mode 100644
index 0000000..5e614ab
--- /dev/null
+++ b/arch/arm/mach-msm/ipc_logging.h
@@ -0,0 +1,98 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef _IPC_LOGGING_H
+#define _IPC_LOGGING_H
+
+struct ipc_log_page_header {
+	uint32_t magic;
+	uint32_t nmagic; /* inverse of magic number */
+	uint32_t log_id; /* owner of log */
+	uint32_t page_num;
+	uint16_t read_offset;
+	uint16_t write_offset;
+	struct list_head list;
+};
+
+struct ipc_log_page {
+	struct ipc_log_page_header hdr;
+	char data[PAGE_SIZE - sizeof(struct ipc_log_page_header)];
+};
+
+struct ipc_log_context {
+	struct list_head list;
+	struct list_head page_list;
+	struct ipc_log_page *first_page;
+	struct ipc_log_page *last_page;
+	struct ipc_log_page *write_page;
+	struct ipc_log_page *read_page;
+	uint32_t write_avail;
+	struct dentry *dent;
+	struct list_head dfunc_info_list;
+	spinlock_t ipc_log_context_lock;
+	struct completion read_avail;
+};
+
+struct dfunc_info {
+	struct list_head list;
+	int type;
+	void (*dfunc) (struct encode_context *, struct decode_context *);
+};
+
+enum {
+	TSV_TYPE_INVALID,
+	TSV_TYPE_TIMESTAMP,
+	TSV_TYPE_POINTER,
+	TSV_TYPE_INT32,
+	TSV_TYPE_BYTE_ARRAY,
+};
+
+enum {
+	OUTPUT_DEBUGFS,
+};
+
+#define IPC_LOGGING_MAGIC_NUM 0x52784425
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
+			((x) < TSV_TYPE_MSG_END))
+
+extern spinlock_t ipc_log_context_list_lock;
+
+extern int msg_read(struct ipc_log_context *ilctxt,
+		    struct encode_context *ectxt);
+
+static inline int is_ilctxt_empty(struct ipc_log_context *ilctxt)
+{
+	if (!ilctxt)
+		return -EINVAL;
+
+	return ((ilctxt->read_page == ilctxt->write_page) &&
+		(ilctxt->read_page->hdr.read_offset ==
+		 ilctxt->write_page->hdr.write_offset));
+}
+
+#if (defined(CONFIG_DEBUG_FS))
+void check_and_create_debugfs(void);
+
+void create_ctx_debugfs(struct ipc_log_context *ctxt,
+			const char *mod_name);
+#else
+void check_and_create_debugfs(void)
+{
+}
+
+void create_ctx_debugfs(struct ipc_log_context *ctxt, const char *mod_name)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
new file mode 100644
index 0000000..5f7a95e
--- /dev/null
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -0,0 +1,225 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/jiffies.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/idr.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+
+#include <mach/msm_ipc_logging.h>
+
+#include "ipc_logging.h"
+
+static DEFINE_MUTEX(ipc_log_debugfs_init_lock);
+static struct dentry *root_dent;
+#define MAX_MSG_DECODED_SIZE (MAX_MSG_SIZE*4)
+
+static void *get_deserialization_func(struct ipc_log_context *ilctxt,
+				      int type)
+{
+	struct dfunc_info *df_info = NULL;
+
+	if (!ilctxt)
+		return NULL;
+
+	list_for_each_entry(df_info, &ilctxt->dfunc_info_list, list) {
+		if (df_info->type == type)
+			return df_info->dfunc;
+	}
+	return NULL;
+}
+
+static int deserialize_log(struct ipc_log_context *ilctxt,
+			   char *buff, int size)
+{
+	struct encode_context ectxt;
+	struct decode_context dctxt;
+	void (*deserialize_func)(struct encode_context *ectxt,
+				 struct decode_context *dctxt);
+	unsigned long flags;
+
+	dctxt.output_format = OUTPUT_DEBUGFS;
+	dctxt.buff = buff;
+	dctxt.size = size;
+	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	spin_lock(&ilctxt->ipc_log_context_lock);
+	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
+	       !is_ilctxt_empty(ilctxt)) {
+		msg_read(ilctxt, &ectxt);
+		deserialize_func = get_deserialization_func(ilctxt,
+							ectxt.hdr.type);
+		spin_unlock(&ilctxt->ipc_log_context_lock);
+		spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+		if (deserialize_func)
+			deserialize_func(&ectxt, &dctxt);
+		else
+			pr_err("%s: unknown message 0x%x\n",
+				__func__, ectxt.hdr.type);
+		spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+		spin_lock(&ilctxt->ipc_log_context_lock);
+	}
+	if ((size - dctxt.size) == 0)
+		init_completion(&ilctxt->read_avail);
+	spin_unlock(&ilctxt->ipc_log_context_lock);
+	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	return size - dctxt.size;
+}
+
+static int debug_log(struct ipc_log_context *ilctxt,
+		     char *buff, int size, int cont)
+{
+	int i = 0;
+
+	if (size < MAX_MSG_DECODED_SIZE) {
+		pr_err("%s: buffer size %d < %d\n", __func__, size,
+			MAX_MSG_DECODED_SIZE);
+		return -ENOMEM;
+	}
+	do {
+		i = deserialize_log(ilctxt, buff, size - 1);
+		if (cont && i == 0) {
+			wait_for_completion_interruptible(&ilctxt->read_avail);
+			if (signal_pending(current))
+				break;
+		}
+	} while (cont && i == 0);
+
+	return i;
+}
+
+/*
+ * VFS Read operation helper which dispatches the call to the debugfs
+ * read command stored in file->private_data.
+ *
+ * @file  File structure
+ * @buff   user buffer
+ * @count size of user buffer
+ * @ppos  file position to read from (only a value of 0 is accepted)
+ * @cont  1 = continuous mode (don't return 0 to signal end-of-file)
+ *
+ * @returns ==0 end of file
+ *           >0 number of bytes read
+ *           <0 error
+ */
+static ssize_t debug_read_helper(struct file *file, char __user *buff,
+				 size_t count, loff_t *ppos, int cont)
+{
+	struct ipc_log_context *ilctxt = file->private_data;
+	char *buffer;
+	int bsize;
+
+	buffer = kmalloc(count, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	bsize = debug_log(ilctxt, buffer, count, cont);
+	if (bsize > 0) {
+		if (copy_to_user(buff, buffer, bsize)) {
+			kfree(buffer);
+			return -EFAULT;
+		}
+		*ppos += bsize;
+	}
+	kfree(buffer);
+	return bsize;
+}
+
+static ssize_t debug_read(struct file *file, char __user *buff,
+			  size_t count, loff_t *ppos)
+{
+	return debug_read_helper(file, buff, count, ppos, 0);
+}
+
+static ssize_t debug_read_cont(struct file *file, char __user *buff,
+			       size_t count, loff_t *ppos)
+{
+	return debug_read_helper(file, buff, count, ppos, 1);
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static const struct file_operations debug_ops = {
+	.read = debug_read,
+	.open = debug_open,
+};
+
+static const struct file_operations debug_ops_cont = {
+	.read = debug_read_cont,
+	.open = debug_open,
+};
+
+static void debug_create(const char *name, mode_t mode,
+			 struct dentry *dent,
+			 struct ipc_log_context *ilctxt,
+			 const struct file_operations *fops)
+{
+	debugfs_create_file(name, mode, dent, ilctxt, fops);
+}
+
+static void dfunc_string(struct encode_context *ectxt,
+			 struct decode_context *dctxt)
+{
+	tsv_timestamp_read(ectxt, dctxt, " ");
+	tsv_byte_array_read(ectxt, dctxt, "");
+}
+
+void check_and_create_debugfs(void)
+{
+	mutex_lock(&ipc_log_debugfs_init_lock);
+	if (!root_dent) {
+		root_dent = debugfs_create_dir("ipc_logging", 0);
+
+		if (IS_ERR(root_dent)) {
+			pr_err("%s: unable to create debugfs %ld\n",
+				__func__, IS_ERR(root_dent));
+			root_dent = NULL;
+		}
+	}
+	mutex_unlock(&ipc_log_debugfs_init_lock);
+}
+EXPORT_SYMBOL(check_and_create_debugfs);
+
+void create_ctx_debugfs(struct ipc_log_context *ctxt,
+			const char *mod_name)
+{
+	if (!root_dent)
+		check_and_create_debugfs();
+
+	if (root_dent) {
+		ctxt->dent = debugfs_create_dir(mod_name, root_dent);
+		if (!IS_ERR(ctxt->dent)) {
+			debug_create("log", 0444, ctxt->dent,
+				     ctxt, &debug_ops);
+			debug_create("log_cont", 0444, ctxt->dent,
+				     ctxt, &debug_ops_cont);
+		}
+	}
+	add_deserialization_func((void *)ctxt,
+				 TSV_TYPE_STRING, dfunc_string);
+}
+EXPORT_SYMBOL(create_ctx_debugfs);
diff --git a/arch/arm/mach-msm/ipc_router_smd_xprt.c b/arch/arm/mach-msm/ipc_router_smd_xprt.c
index 6960d2e..0cde393 100644
--- a/arch/arm/mach-msm/ipc_router_smd_xprt.c
+++ b/arch/arm/mach-msm/ipc_router_smd_xprt.c
@@ -38,7 +38,7 @@
 
 #define MIN_FRAG_SZ (IPC_ROUTER_HDR_SIZE + sizeof(union rr_control_msg))
 
-#define NUM_SMD_XPRTS 2
+#define NUM_SMD_XPRTS 3
 #define XPRT_NAME_LEN (SMD_MAX_CH_NAME_LEN + 12)
 
 struct msm_ipc_router_smd_xprt {
@@ -72,16 +72,18 @@
 struct msm_ipc_router_smd_xprt_config smd_xprt_cfg[] = {
 	{"RPCRPY_CNTL", "ipc_rtr_smd_rpcrpy_cntl", SMD_APPS_MODEM, 1},
 	{"IPCRTR", "ipc_rtr_smd_ipcrtr", SMD_APPS_MODEM, 1},
+	{"IPCRTR", "ipc_rtr_q6_ipcrtr", SMD_APPS_QDSP, 1},
 };
 
 static struct msm_ipc_router_smd_xprt smd_remote_xprt[NUM_SMD_XPRTS];
 
-static int find_smd_xprt_cfg(const char *name)
+static int find_smd_xprt_cfg(struct platform_device *pdev)
 {
 	int i;
 
 	for (i = 0; i < NUM_SMD_XPRTS; i++) {
-		if (!strncmp(name, smd_xprt_cfg[i].ch_name, 20))
+		if (!strncmp(pdev->name, smd_xprt_cfg[i].ch_name, 20) &&
+		    (pdev->id == smd_xprt_cfg[i].edge))
 			return i;
 	}
 
@@ -389,7 +391,7 @@
 	int rc;
 	int id;		/*Index into the smd_xprt_cfg table*/
 
-	id = find_smd_xprt_cfg(pdev->name);
+	id = find_smd_xprt_cfg(pdev);
 	if (id < 0) {
 		pr_err("%s: called for unknown ch %s\n",
 			__func__, pdev->name);
@@ -460,9 +462,8 @@
 static int __init msm_ipc_router_smd_init(void)
 {
 	int i, ret, rc = 0;
-	BUG_ON(ARRAY_SIZE(msm_ipc_router_smd_remote_driver) != NUM_SMD_XPRTS);
 	BUG_ON(ARRAY_SIZE(smd_xprt_cfg) != NUM_SMD_XPRTS);
-	for (i = 0; i < NUM_SMD_XPRTS; i++) {
+	for (i = 0; i < ARRAY_SIZE(msm_ipc_router_smd_remote_driver); i++) {
 		ret = platform_driver_register(
 				&msm_ipc_router_smd_remote_driver[i]);
 		if (ret) {
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index e0d2696..b4b7ea3 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -79,6 +79,11 @@
 {
 	power_on_count++;
 
+	/* this gpio will be used to indicate apq readiness,
+	 * de-assert it now so that it can asserted later
+	 */
+	gpio_direction_output(mdm_drv->ap2mdm_wakeup_gpio, 0);
+
 	/* The second attempt to power-on the mdm is the first attempt
 	 * from user space, but we're already powered on. Ignore this.
 	 * Subsequent attempts are from SSR or if something failed, in
@@ -97,7 +102,7 @@
 	/* Deassert RESET first and wait for it to settle. */
 	pr_debug("%s: Pulling RESET gpio high\n", __func__);
 	gpio_direction_output(mdm_drv->ap2mdm_pmic_reset_n_gpio, 1);
-	usleep(1000);
+	usleep(20000);
 
 	/* Pull PWR gpio high and wait for it to settle, but only
 	 * the first time the mdm is powered up.
@@ -152,6 +157,7 @@
 	if (value) {
 		mdm_peripheral_disconnect(mdm_drv);
 		mdm_peripheral_connect(mdm_drv);
+		gpio_direction_output(mdm_drv->ap2mdm_wakeup_gpio, 1);
 	}
 }
 
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index a7ba4a0..8d99c1c 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -204,9 +204,6 @@
 	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);
@@ -239,7 +236,7 @@
 		/* Wait for the external modem to complete
 		 * its preparation for ramdumps.
 		 */
-		mdelay(mdm_drv->pdata->ramdump_delay_ms);
+		msleep(mdm_drv->pdata->ramdump_delay_ms);
 	}
 	mdm_drv->ops->power_down_mdm_cb(mdm_drv);
 	return 0;
@@ -523,12 +520,6 @@
 {
 	mdm_disable_irqs();
 
-	if (mdm_drv->ap2mdm_wakeup_gpio > 0)
-		gpio_set_value(mdm_drv->ap2mdm_wakeup_gpio, 1);
-
 	mdm_drv->ops->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/mpm.c b/arch/arm/mach-msm/mpm.c
index 746c0f8..dccdc8b 100644
--- a/arch/arm/mach-msm/mpm.c
+++ b/arch/arm/mach-msm/mpm.c
@@ -26,7 +26,7 @@
 #include <mach/msm_iomap.h>
 #include <mach/gpio.h>
 
-#include "mpm.h"
+#include <mach/mpm.h>
 
 /******************************************************************************
  * Debug Definitions
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index c547d8c..0c158de 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -81,8 +81,9 @@
 	uint32_t group_id;
 	uint32_t freq_pending;
 	struct hrtimer timer;
-	int32_t core_slack_time_us;
 	int32_t timer_disabled;
+	/* track if kthread for change_freq is active */
+	int32_t change_freq_activated;
 };
 
 static int msm_dcvs_debug;
@@ -153,19 +154,12 @@
 	if (ret <= 0) {
 		__err("Core %s failed to set freq %u\n",
 				core->core_name, requested_freq);
-		/* Restart the timers at the current slack time */
-		core->timer_disabled = 0;
-		ret = hrtimer_start(&core->timer,
-			ktime_set(0, core->core_slack_time_us * 1000),
-				HRTIMER_MODE_REL_PINNED);
-			if (ret)
-				__err("Failed to register timer for core %s\n",
-						core->core_name);
-		return -EFAULT;
+		/* continue to call TZ to get updated slack timer */
+	} else {
+		prev_freq = core->actual_freq;
+		core->actual_freq = ret;
 	}
 
-	prev_freq = core->actual_freq;
-	core->actual_freq = ret;
 	time_end = ktime_to_ns(ktime_get());
 	if (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE)
 		__info("Core %s Time end %llu Time start: %llu\n",
@@ -201,7 +195,6 @@
 		core->actual_freq, (uint32_t)time_end, &slack_us, &ret1);
 	if (!ret) {
 		/* Reset the slack timer */
-		core->core_slack_time_us = slack_us;
 		if (slack_us) {
 			core->timer_disabled = 0;
 			ret = hrtimer_start(&core->timer,
@@ -221,7 +214,7 @@
 			"change time %u us slack time %u us\n",
 			requested_freq, core->core_name,
 			core->actual_freq, prev_freq,
-			core->freq_change_us, core->core_slack_time_us);
+			core->freq_change_us, slack_us);
 
 	/**
 	 * By the time we are done with freq changes, we could be asked to
@@ -230,6 +223,7 @@
 	if (core->freq_pending)
 		goto repeat;
 
+	core->change_freq_activated = 0;
 	return ret;
 }
 
@@ -260,17 +254,16 @@
 }
 
 static int msm_dcvs_update_freq(struct dcvs_core *core,
-		enum msm_dcvs_scm_event event, uint32_t param0)
+		enum msm_dcvs_scm_event event, uint32_t param0,
+		uint32_t *ret1, int *freq_changed)
 {
 	int ret = 0;
 	unsigned long flags = 0;
 	uint32_t new_freq = 0;
-	uint32_t ret1 = 0;
 
 	spin_lock_irqsave(&core->cpu_lock, flags);
 	ret = msm_dcvs_scm_event(core->handle, event, param0,
-				core->actual_freq, &new_freq, &ret1);
-
+				core->actual_freq, &new_freq, ret1);
 	if (ret) {
 		__err("Error (%d) sending SCM event %d for core %s\n",
 				ret, event, core->core_name);
@@ -288,8 +281,15 @@
 		if (!core->task)
 			__err("Uninitialized task for core %s\n",
 					core->core_name);
-		else
+		else {
+			if (freq_changed)
+				*freq_changed = 1;
+			core->change_freq_activated = 1;
 			wake_up_process(core->task);
+		}
+	} else {
+		if (freq_changed)
+			*freq_changed = 0;
 	}
 freq_done:
 	spin_unlock_irqrestore(&core->cpu_lock, flags);
@@ -301,6 +301,8 @@
 {
 	int ret = 0;
 	struct dcvs_core *core = container_of(timer, struct dcvs_core, timer);
+	uint32_t ret1;
+	uint32_t ret2;
 
 	if (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE)
 		__info("Slack timer fired for core %s\n", core->core_name);
@@ -309,7 +311,8 @@
 	 * Timer expired, notify TZ
 	 * Dont care about the third arg.
 	 */
-	ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_QOS_TIMER_EXPIRED, 0);
+	ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_QOS_TIMER_EXPIRED, 0,
+				   &ret1, &ret2);
 	if (ret)
 		__err("Timer expired for core %s but failed to notify.\n",
 				core->core_name);
@@ -551,6 +554,8 @@
 {
 	int ret = -EINVAL;
 	struct dcvs_core *core = NULL;
+	uint32_t ret1;
+	uint32_t ret2;
 
 	if (!drv || !drv->core_name)
 		return ret;
@@ -577,7 +582,8 @@
 	if (core->idle_driver) {
 		core->actual_freq = core->freq_driver->get_frequency(drv);
 		/* Notify TZ to start receiving idle info for the core */
-		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1);
+		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1,
+					   &ret1, &ret2);
 		core->idle_driver->enable(core->idle_driver,
 				MSM_DCVS_ENABLE_IDLE_PULSE);
 	}
@@ -592,6 +598,8 @@
 {
 	int ret = -EINVAL;
 	struct dcvs_core *core = NULL;
+	uint32_t ret1;
+	uint32_t ret2;
 
 	if (!drv || !drv->core_name)
 		return ret;
@@ -607,7 +615,8 @@
 		core->idle_driver->enable(core->idle_driver,
 				MSM_DCVS_DISABLE_IDLE_PULSE);
 		/* Notify TZ to stop receiving idle info for the core */
-		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0);
+		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0,
+					   &ret1, &ret2);
 		hrtimer_cancel(&core->timer);
 		core->idle_driver->enable(core->idle_driver,
 				MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
@@ -670,8 +679,9 @@
 {
 	int ret = 0;
 	struct dcvs_core *core = NULL;
-	int64_t timer_interval_us = 0;
+	uint32_t timer_interval_us = 0;
 	uint32_t r0, r1;
+	uint32_t freq_changed = 0;
 
 	if (handle >= CORE_HANDLE_OFFSET &&
 			(handle - CORE_HANDLE_OFFSET) < CORES_MAX)
@@ -695,18 +705,21 @@
 	case MSM_DCVS_IDLE_EXIT:
 		hrtimer_cancel(&core->timer);
 		ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_IDLE_EXIT,
-				iowaited);
+				iowaited, &timer_interval_us, &freq_changed);
 		if (ret)
 			__err("Error (%d) sending idle exit for %s\n",
 					ret, core->core_name);
-		timer_interval_us = core->core_slack_time_us;
+		/* only start slack timer if change_freq won't */
+		if (freq_changed || core->change_freq_activated)
+			break;
 		if (timer_interval_us && !core->timer_disabled) {
 			ret = hrtimer_start(&core->timer,
 				ktime_set(0, timer_interval_us * 1000),
 				HRTIMER_MODE_REL_PINNED);
+
 			if (ret)
 				__err("Failed to register timer for core %s\n",
-						core->core_name);
+				      core->core_name);
 		}
 		break;
 	}
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 6de0660..2b0cc18 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -55,7 +55,6 @@
  * Debug Definitions
  *****************************************************************************/
 
-
 enum {
 	MSM_PM_DEBUG_SUSPEND = BIT(0),
 	MSM_PM_DEBUG_POWER_COLLAPSE = BIT(1),
@@ -77,22 +76,6 @@
 /******************************************************************************
  * Sleep Modes and Parameters
  *****************************************************************************/
-
-static struct msm_pm_platform_data *msm_pm_modes;
-static int rpm_cpu0_wakeup_irq;
-
-void __init msm_pm_set_platform_data(
-	struct msm_pm_platform_data *data, int count)
-{
-	BUG_ON(MSM_PM_SLEEP_MODE_NR * num_possible_cpus() > count);
-	msm_pm_modes = data;
-}
-
-void __init msm_pm_set_rpm_wakeup_irq(unsigned int irq)
-{
-	rpm_cpu0_wakeup_irq = irq;
-}
-
 enum {
 	MSM_PM_MODE_ATTR_SUSPEND,
 	MSM_PM_MODE_ATTR_IDLE,
@@ -147,7 +130,7 @@
 			continue;
 
 		cpu = GET_CPU_OF_ATTR(attr);
-		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+		mode = &msm_pm_sleep_modes[MSM_PM_MODE(cpu, i)];
 
 		if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
@@ -193,7 +176,7 @@
 			continue;
 
 		cpu = GET_CPU_OF_ATTR(attr);
-		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+		mode = &msm_pm_sleep_modes[MSM_PM_MODE(cpu, i)];
 
 		if (!strcmp(attr->attr.name,
 			msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_SUSPEND])) {
@@ -234,8 +217,12 @@
 	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
 		int idx = MSM_PM_MODE(cpu, i);
 
-		if ((!msm_pm_modes[idx].suspend_supported)
-			&& (!msm_pm_modes[idx].idle_supported))
+		if ((!msm_pm_sleep_modes[idx].suspend_supported)
+			&& (!msm_pm_sleep_modes[idx].idle_supported))
+			continue;
+
+		if (!msm_pm_sleep_mode_labels[i] ||
+				!msm_pm_sleep_mode_labels[i][0])
 			continue;
 
 		mode = kzalloc(sizeof(*mode), GFP_KERNEL);
@@ -256,10 +243,10 @@
 
 		for (k = 0, j = 0; k < MSM_PM_MODE_ATTR_NR; k++) {
 			if ((k == MSM_PM_MODE_ATTR_IDLE) &&
-				!msm_pm_modes[idx].idle_supported)
+				!msm_pm_sleep_modes[idx].idle_supported)
 				continue;
 			if ((k == MSM_PM_MODE_ATTR_SUSPEND) &&
-			     !msm_pm_modes[idx].suspend_supported)
+			     !msm_pm_sleep_modes[idx].suspend_supported)
 				continue;
 			mode->kas[j].cpu = cpu;
 			mode->kas[j].ka.attr.mode = 0644;
@@ -763,15 +750,6 @@
 	return collapsed;
 }
 
-static irqreturn_t msm_pm_rpm_wakeup_interrupt(int irq, void *dev_id)
-{
-	if (dev_id != &msm_pm_rpm_wakeup_interrupt)
-		return IRQ_NONE;
-
-	return IRQ_HANDLED;
-}
-
-
 /******************************************************************************
  * External Idle/Suspend Functions
  *****************************************************************************/
@@ -801,8 +779,8 @@
 		mode = (enum msm_pm_sleep_mode) state->driver_data;
 		idx = MSM_PM_MODE(dev->cpu, mode);
 
-		allow = msm_pm_modes[idx].idle_enabled &&
-				msm_pm_modes[idx].idle_supported;
+		allow = msm_pm_sleep_modes[idx].idle_enabled &&
+				msm_pm_sleep_modes[idx].idle_supported;
 
 		switch (mode) {
 		case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
@@ -989,7 +967,7 @@
 	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
 		struct msm_pm_platform_data *mode;
 
-		mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)];
+		mode = &msm_pm_sleep_modes[MSM_PM_MODE(cpu, i)];
 		allow[i] = mode->suspend_supported && mode->suspend_enabled;
 	}
 
@@ -1064,7 +1042,7 @@
 	for (i = 0; i < MSM_PM_SLEEP_MODE_NR; i++) {
 		struct msm_pm_platform_data *mode;
 
-		mode = &msm_pm_modes[MSM_PM_MODE(0, i)];
+		mode = &msm_pm_sleep_modes[MSM_PM_MODE(0, i)];
 		allow[i] = mode->suspend_supported && mode->suspend_enabled;
 	}
 
@@ -1167,7 +1145,6 @@
 #ifdef CONFIG_MSM_IDLE_STATS
 	struct proc_dir_entry *d_entry;
 #endif
-	int ret;
 
 	/* Page table for cores to come back up safely. */
 	pc_pgd = pgd_alloc(&init_mm);
@@ -1205,22 +1182,6 @@
 	clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
 		     virt_to_phys(&msm_pm_pc_pgd));
 
-	ret = request_irq(rpm_cpu0_wakeup_irq,
-			msm_pm_rpm_wakeup_interrupt, IRQF_TRIGGER_RISING,
-			"pm_drv", msm_pm_rpm_wakeup_interrupt);
-	if (ret) {
-		pr_err("%s: failed to request irq %u: %d\n",
-			__func__, rpm_cpu0_wakeup_irq, ret);
-		return ret;
-	}
-
-	ret = irq_set_irq_wake(rpm_cpu0_wakeup_irq, 1);
-	if (ret) {
-		pr_err("%s: failed to set wakeup irq %u: %d\n",
-			__func__, rpm_cpu0_wakeup_irq, ret);
-		return ret;
-	}
-
 #ifdef CONFIG_MSM_IDLE_STATS
 	for_each_possible_cpu(cpu) {
 		struct msm_pm_time_stats *stats =
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
new file mode 100644
index 0000000..d7001d7
--- /dev/null
+++ b/arch/arm/mach-msm/pm-data.c
@@ -0,0 +1,100 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#include "pm.h"
+
+struct msm_pm_platform_data msm_pm_sleep_modes[] = {
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 1,
+		.suspend_enabled = 1,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = {
+		.idle_supported = 0,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
+		.idle_supported = 1,
+		.suspend_supported = 1,
+		.idle_enabled = 0,
+		.suspend_enabled = 0,
+	},
+
+	[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)] = {
+		.idle_supported = 1,
+		.suspend_supported = 0,
+		.idle_enabled = 1,
+		.suspend_enabled = 0,
+	},
+};
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index caafbdd..7ef3c34 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -67,6 +67,8 @@
 				staying in the low power mode saves power */
 };
 
+extern struct msm_pm_platform_data msm_pm_sleep_modes[];
+
 struct msm_pm_sleep_status_data {
 	void *base_addr;
 	uint32_t cpu_offset;
diff --git a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
index 5df976d..1dd90a7 100644
--- a/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/amrwb_in.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -201,8 +201,8 @@
 	audio->enc_cfg = kzalloc(sizeof(struct msm_audio_amrwb_enc_config),
 				GFP_KERNEL);
 	if (audio->enc_cfg == NULL) {
-		pr_err("%s:session id %d: Could not allocate memory for amrwb"
-			"config param\n", __func__, audio->ac->session);
+		pr_err("%s: Could not allocate memory for amrwb"
+			"config param\n", __func__);
 		kfree(audio);
 		return -ENOMEM;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
index 88189f6..438909a 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -274,6 +274,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
index 6768f7a..9618adb 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrnb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -138,6 +138,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrnb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
index f95e191..a15ab28 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_amrwb.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -140,6 +140,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_amrwb_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
index 12c815d..5a511c9 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_evrc.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -144,6 +144,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_evrc_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
index bb5dc96..c1a90bd 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_mp3.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -135,6 +135,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_mp3_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index ee32b80..0f6b5a6 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -275,6 +275,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_multi_aac_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
index 7b72c97..8343beb 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_qcelp.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -150,6 +150,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_qcelp_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index d2557ca..48e0135 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1181,21 +1181,19 @@
 	file->private_data = audio;
 	audio->codec_ioctl = audio_aio_ioctl;
 
-	for (i = 0; i < AUDIO_EVENT_NUM; i++) {
-		e_node = kmalloc(sizeof(struct audio_aio_event), GFP_KERNEL);
-		if (e_node)
-			list_add_tail(&e_node->list, &audio->free_event_queue);
-		else {
-			pr_err("%s[%p]:event pkt alloc failed\n",
-				__func__, audio);
-			break;
-		}
+	e_node = kmalloc(sizeof(struct audio_aio_event) * AUDIO_EVENT_NUM,
+			GFP_KERNEL);
+	if (e_node) {
+		for (i = 0; i < AUDIO_EVENT_NUM; i++)
+			list_add_tail(&e_node[i].list,
+				&audio->free_event_queue);
+	} else {
+		pr_err("%s[%p]:event pkt alloc failed\n",
+			__func__, audio);
+		rc = -ENOMEM;
+		goto fail;
 	}
-	return 0;
 fail:
-	q6asm_audio_client_free(audio->ac);
-	kfree(audio->codec_cfg);
-	kfree(audio);
 	return rc;
 }
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wma.c b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
index bea0485..62d4393 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wma.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -185,6 +185,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wma_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
index 98d1b30..a83fce9 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_wmapro.c
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -245,6 +245,10 @@
 		goto fail;
 	}
 	rc = audio_aio_open(audio, file);
+	if (IS_ERR_VALUE(rc)) {
+		pr_err("%s: audio_aio_open failed\n", __func__);
+		goto fail;
+	}
 
 #ifdef CONFIG_DEBUG_FS
 	snprintf(name, sizeof name, "msm_wmapro_%04x", audio->ac->session);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index edb1e7d..bfd4c48 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -249,8 +249,6 @@
 	int len;
 	static int t_len;
 
-	if (count < 0)
-		return 0;
 	len = count > 63 ? 63 : count;
 	if (copy_from_user(l_buf + 20 , buf, len)) {
 		pr_info("Unable to copy data from user space\n");
diff --git a/arch/arm/mach-msm/qdsp6v2/rtac.c b/arch/arm/mach-msm/qdsp6v2/rtac.c
index a3a14c4..4fd20d0 100644
--- a/arch/arm/mach-msm/qdsp6v2/rtac.c
+++ b/arch/arm/mach-msm/qdsp6v2/rtac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -443,7 +443,6 @@
 
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
-
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -614,7 +613,6 @@
 	}
 
 	if (payload_size > MAX_PAYLOAD_SIZE) {
-
 			pr_err("%s: Invalid payload size = %d\n",
 				__func__, payload_size);
 		goto done;
@@ -625,17 +623,15 @@
 			__func__);
 		goto done;
 	}
-	if (session_id > (SESSION_MAX + 1)) {
+	if (session_id > SESSION_MAX) {
 		pr_err("%s: Invalid Session = %d\n", __func__, session_id);
 		goto done;
 	}
 
 	mutex_lock(&rtac_asm_apr_mutex);
-	if (session_id < SESSION_MAX+1) {
-		if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
-			pr_err("%s: APR not initialized\n", __func__);
-			goto err;
-		}
+	if (rtac_asm_apr_data[session_id].apr_handle == NULL) {
+		pr_err("%s: APR not initialized\n", __func__);
+		goto err;
 	}
 
 	/* Set globals for copy of returned payload */
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index b0fa3d2..44e50dd 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -54,7 +54,6 @@
 static uint32_t msm_rpm_sel_mask_size;
 static struct msm_rpm_platform_data msm_rpm_data;
 
-
 static DEFINE_MUTEX(msm_rpm_mutex);
 static DEFINE_SPINLOCK(msm_rpm_lock);
 static DEFINE_SPINLOCK(msm_rpm_irq_lock);
@@ -936,9 +935,16 @@
 	}
 }
 
+static irqreturn_t msm_pm_rpm_wakeup_interrupt(int irq, void *dev_id)
+{
+	if (dev_id != &msm_pm_rpm_wakeup_interrupt)
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
 int __init msm_rpm_init(struct msm_rpm_platform_data *data)
 {
-	unsigned int irq;
 	int rc;
 
 	memcpy(&msm_rpm_data, data, sizeof(struct msm_rpm_platform_data));
@@ -971,21 +977,19 @@
 	msm_rpm_write(MSM_RPM_PAGE_CTRL,
 		target_ctrl(MSM_RPM_CTRL_VERSION_BUILD), msm_rpm_data.ver[2]);
 
-	irq = data->irq_ack;
-
-	rc = request_irq(irq, msm_rpm_ack_interrupt,
+	rc = request_irq(data->irq_ack, msm_rpm_ack_interrupt,
 			IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
 			"rpm_drv", msm_rpm_ack_interrupt);
 	if (rc) {
 		pr_err("%s: failed to request irq %d: %d\n",
-			__func__, irq, rc);
+			__func__, data->irq_ack, rc);
 		return rc;
 	}
 
-	rc = irq_set_irq_wake(irq, 1);
+	rc = irq_set_irq_wake(data->irq_ack, 1);
 	if (rc) {
 		pr_err("%s: failed to set wakeup irq %u: %d\n",
-			__func__, irq, rc);
+			__func__, data->irq_ack, rc);
 		return rc;
 	}
 
@@ -997,6 +1001,22 @@
 		return rc;
 	}
 
+	rc = request_irq(data->irq_wakeup,
+			msm_pm_rpm_wakeup_interrupt, IRQF_TRIGGER_RISING,
+			"pm_drv", msm_pm_rpm_wakeup_interrupt);
+	if (rc) {
+		pr_err("%s: failed to request irq %u: %d\n",
+			__func__, data->irq_wakeup, rc);
+		return rc;
+	}
+
+	rc = irq_set_irq_wake(data->irq_wakeup, 1);
+	if (rc) {
+		pr_err("%s: failed to set wakeup irq %u: %d\n",
+			__func__, data->irq_wakeup, rc);
+		return rc;
+	}
+
 	msm_rpm_populate_map(data);
 
 	return platform_driver_register(&msm_rpm_platform_driver);
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 6282eca..7daea5c 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -25,7 +25,7 @@
 #include <asm/mach-types.h>
 #include <linux/io.h>
 #include <mach/socinfo.h>
-#include "mpm.h"
+#include <mach/mpm.h>
 #include "rpm_resources.h"
 #include "spm.h"
 #include "idle.h"
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 5f835a2..430a4c0 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -40,7 +40,7 @@
 #ifdef CONFIG_ARCH_FSM9XXX
 #define NUM_SMD_PKT_PORTS 4
 #else
-#define NUM_SMD_PKT_PORTS 13
+#define NUM_SMD_PKT_PORTS 14
 #endif
 
 #define LOOPBACK_INX (NUM_SMD_PKT_PORTS - 1)
@@ -657,6 +657,7 @@
 	"smd_sns_dsps",
 	"apr_apps2",
 	"smdcntl8",
+	"smd_sns_adsp",
 	"smd_pkt_loopback",
 };
 
@@ -673,6 +674,7 @@
 	"SENSOR",
 	"apr_apps2",
 	"DATA40_CNTL",
+	"SENSOR",
 	"LOOPBACK",
 };
 
@@ -689,6 +691,7 @@
 	SMD_APPS_DSPS,
 	SMD_APPS_QDSP,
 	SMD_APPS_MODEM,
+	SMD_APPS_QDSP,
 	SMD_APPS_MODEM,
 };
 #endif
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 4282d44..326d11b 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -512,6 +512,7 @@
 static int device_resume(struct device *dev, pm_message_t state, bool async)
 {
 	int error = 0;
+	bool put = false;
 
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
@@ -528,6 +529,9 @@
 	if (!dev->power.is_suspended)
 		goto Unlock;
 
+	pm_runtime_enable(dev);
+	put = true;
+
 	if (dev->pwr_domain) {
 		pm_dev_dbg(dev, state, "power domain ");
 		error = pm_op(dev, &dev->pwr_domain->ops, state);
@@ -570,6 +574,10 @@
 	complete_all(&dev->power.completion);
 
 	TRACE_RESUME(error);
+
+	if (put)
+		pm_runtime_put_sync(dev);
+
 	return error;
 }
 
@@ -877,6 +885,19 @@
 
 	dpm_wait_for_children(dev, async);
 
+	if (async_error)
+		return 0;
+
+	pm_runtime_get_noresume(dev);
+	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
+		pm_wakeup_event(dev, 0);
+
+	if (pm_wakeup_pending()) {
+		pm_runtime_put_sync(dev);
+		async_error = -EBUSY;
+		return 0;
+	}
+
 	data.dev = dev;
 	data.tsk = get_current();
 	init_timer_on_stack(&timer);
@@ -887,14 +908,6 @@
 
 	device_lock(dev);
 
-	if (async_error)
-		goto Unlock;
-
-	if (pm_wakeup_pending()) {
-		async_error = -EBUSY;
-		goto Unlock;
-	}
-
 	if (dev->pwr_domain) {
 		pm_dev_dbg(dev, state, "power domain ");
 		error = pm_op(dev, &dev->pwr_domain->ops, state);
@@ -932,7 +945,6 @@
  End:
 	dev->power.is_suspended = !error;
 
- Unlock:
 	device_unlock(dev);
 
 	del_timer_sync(&timer);
@@ -940,8 +952,12 @@
 
 	complete_all(&dev->power.completion);
 
-	if (error)
+	if (error) {
+		pm_runtime_put_sync(dev);
 		async_error = error;
+	} else if (dev->power.is_suspended) {
+		__pm_runtime_disable(dev, false);
+	}
 
 	return error;
 }
@@ -1081,13 +1097,7 @@
 		get_device(dev);
 		mutex_unlock(&dpm_list_mtx);
 
-		pm_runtime_get_noresume(dev);
-		if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
-			pm_wakeup_event(dev, 0);
-
-		pm_runtime_put_sync(dev);
-		error = pm_wakeup_pending() ?
-				-EBUSY : device_prepare(dev, state);
+		error = device_prepare(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 926bd69..7b63610 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -45,7 +45,7 @@
 #define APPS_PROC		1
 #define QDSP_PROC		2
 #define WCNSS_PROC		3
-#define MSG_MASK_SIZE 8000
+#define MSG_MASK_SIZE 9500
 #define LOG_MASK_SIZE 8000
 #define EVENT_MASK_SIZE 1000
 #define USER_SPACE_DATA 8000
@@ -205,9 +205,6 @@
 	struct work_struct diag_read_smd_wcnss_work;
 	struct work_struct diag_read_smd_wcnss_cntl_work;
 	struct workqueue_struct *diag_cntl_wq;
-	struct work_struct diag_msg_mask_update_work;
-	struct work_struct diag_log_mask_update_work;
-	struct work_struct diag_event_mask_update_work;
 	struct work_struct diag_modem_mask_update_work;
 	struct work_struct diag_qdsp_mask_update_work;
 	struct work_struct diag_wcnss_mask_update_work;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 65ddfec..77d84fd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/of.h>
+#include <linux/spinlock.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <mach/usbdiag.h>
 #endif
@@ -36,8 +37,11 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
 #endif
-#define MODE_CMD	41
-#define RESET_ID	2
+#define MODE_CMD		41
+#define RESET_ID		2
+#define ALL_EQUIP_ID		100
+#define ALL_SSID		-1
+#define MAX_SSID_PER_RANGE	100
 
 int diag_debug_buf_idx;
 unsigned char diag_debug_buf[1024];
@@ -53,6 +57,17 @@
 	int num_items;
 	int index;
 };
+spinlock_t diag_cntl_lock;
+
+#define CREATE_MSG_MASK_TBL_ROW(XX)					\
+do {									\
+	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX;			\
+	msg_mask_tbl_ptr += 4;						\
+	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST;		\
+	msg_mask_tbl_ptr += 4;						\
+	/* increment by MAX_SSID_PER_RANGE cells */			\
+	msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int);		\
+} while (0)
 
 #define ENCODE_RSP_AND_SEND(buf_length)				\
 do {									\
@@ -439,7 +454,7 @@
 	int last;
 	uint8_t *ptr = driver->msg_masks;
 	int i = 0;
-
+	pr_info("diag: F3 message mask table\n");
 	while (*(uint32_t *)(ptr + 4)) {
 		first = *(uint32_t *)ptr;
 		ptr += 4;
@@ -448,12 +463,40 @@
 		printk(KERN_INFO "SSID %d - %d\n", first, last);
 		for (i = 0 ; i <= last - first ; i++)
 			printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
-		ptr += ((last - first) + 1)*4;
+		ptr += MAX_SSID_PER_RANGE*4;
 
 	}
 #endif
 }
 
+void diag_create_msg_mask_table(void)
+{
+	uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
+
+	CREATE_MSG_MASK_TBL_ROW(0);
+	CREATE_MSG_MASK_TBL_ROW(1);
+	CREATE_MSG_MASK_TBL_ROW(2);
+	CREATE_MSG_MASK_TBL_ROW(3);
+	CREATE_MSG_MASK_TBL_ROW(4);
+	CREATE_MSG_MASK_TBL_ROW(5);
+	CREATE_MSG_MASK_TBL_ROW(6);
+	CREATE_MSG_MASK_TBL_ROW(7);
+	CREATE_MSG_MASK_TBL_ROW(8);
+	CREATE_MSG_MASK_TBL_ROW(9);
+	CREATE_MSG_MASK_TBL_ROW(10);
+	CREATE_MSG_MASK_TBL_ROW(11);
+	CREATE_MSG_MASK_TBL_ROW(12);
+	CREATE_MSG_MASK_TBL_ROW(13);
+	CREATE_MSG_MASK_TBL_ROW(14);
+	CREATE_MSG_MASK_TBL_ROW(15);
+	CREATE_MSG_MASK_TBL_ROW(16);
+	CREATE_MSG_MASK_TBL_ROW(17);
+	CREATE_MSG_MASK_TBL_ROW(18);
+	CREATE_MSG_MASK_TBL_ROW(19);
+	CREATE_MSG_MASK_TBL_ROW(20);
+	CREATE_MSG_MASK_TBL_ROW(21);
+	CREATE_MSG_MASK_TBL_ROW(22);
+}
 static void diag_update_msg_mask(int start, int end , uint8_t *buf)
 {
 	int found = 0;
@@ -476,9 +519,11 @@
 			if (end <= last)
 				if (CHK_OVERFLOW(ptr_buffer_start, ptr,
 						  ptr_buffer_end,
-						  (((end - start)+1)*4)))
+						  (((end - start)+1)*4))) {
+					pr_debug("diag: update ssid start %d,"
+						 " end %d\n", start, end);
 					memcpy(ptr, buf , ((end - start)+1)*4);
-				else
+				} else
 					printk(KERN_CRIT "Not enough"
 							 " buffer space for"
 							 " MSG_MASK\n");
@@ -489,7 +534,7 @@
 			found = 1;
 			break;
 		} else {
-			ptr += ((last - first) + 1)*4;
+			ptr += MAX_SSID_PER_RANGE*4;
 		}
 	}
 	/* Entry was not found - add new table */
@@ -500,6 +545,8 @@
 			ptr += 4;
 			memcpy(ptr, &(end), 4);
 			ptr += 4;
+			pr_debug("diag: adding NEW ssid start %d, end %d\n",
+								 start, end);
 			memcpy(ptr, buf , ((end - start) + 1)*4);
 		} else
 			printk(KERN_CRIT " Not enough buffer"
@@ -546,8 +593,9 @@
 	int i = 0;
 	unsigned char *ptr_data;
 	int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
-	struct mask_info *ptr = (struct mask_info *)driver->log_masks;
+	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
 
+	pr_debug("diag: received equip id = %d\n", equip_id);
 	mutex_lock(&driver->diagchar_mutex);
 	/* Check if we already know index of this equipment ID */
 	for (i = 0; i < MAX_EQUIP_ID; i++) {
@@ -571,7 +619,7 @@
 					 + LOG_MASK_SIZE, (num_items+7)/8))
 		memcpy(ptr_data, temp , (num_items+7)/8);
 	else
-		printk(KERN_CRIT " Not enough buffer space for LOG_MASK\n");
+		pr_err("diag: Not enough buffer space for LOG_MASK\n");
 	mutex_unlock(&driver->diagchar_mutex);
 }
 
@@ -645,46 +693,36 @@
 
 void diag_modem_mask_update_fn(struct work_struct *work)
 {
-	diag_send_msg_mask_update(driver->ch_cntl);
-	diag_send_log_mask_update(driver->ch_cntl);
+	diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
+					   ALL_SSID, MODEM_PROC);
+	diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
 	diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
 }
 
 void diag_qdsp_mask_update_fn(struct work_struct *work)
 {
-	diag_send_msg_mask_update(driver->chqdsp_cntl);
-	diag_send_log_mask_update(driver->chqdsp_cntl);
+	diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
+						   ALL_SSID, QDSP_PROC);
+	diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
 	diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
 }
 
 void diag_wcnss_mask_update_fn(struct work_struct *work)
 {
-	diag_send_msg_mask_update(driver->ch_wcnss_cntl);
-	diag_send_log_mask_update(driver->ch_wcnss_cntl);
+	diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
+						   ALL_SSID, WCNSS_PROC);
+	diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
 	diag_send_event_mask_update(driver->ch_wcnss_cntl,
 						 diag_event_num_bytes);
 }
 
-void diag_msg_mask_update_fn(struct work_struct *work)
-{
-	diag_send_msg_mask_update(driver->ch_cntl);
-	diag_send_msg_mask_update(driver->chqdsp_cntl);
-	diag_send_msg_mask_update(driver->ch_wcnss_cntl);
-}
-
-void diag_log_mask_update_fn(struct work_struct *work)
-{
-	diag_send_log_mask_update(driver->ch_cntl);
-	diag_send_log_mask_update(driver->chqdsp_cntl);
-	diag_send_log_mask_update(driver->ch_wcnss_cntl);
-}
-
-void diag_send_log_mask_update(smd_channel_t *ch)
+void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
 {
 	void *buf = driver->buf_log_mask_update;
 	int header_size = sizeof(struct diag_ctrl_log_mask);
 	struct mask_info *ptr = (struct mask_info *)driver->log_masks;
-	int i, size;
+	int i, size, wr_size = -ENOMEM, retry_count = 0;
+	unsigned long flags = 0;
 
 	for (i = 0; i < MAX_EQUIP_ID; i++) {
 		size = (ptr->num_items+7)/8;
@@ -698,11 +736,36 @@
 		driver->log_mask->status = 3; /* status for valid mask */
 		driver->log_mask->equip_id = ptr->equip_id;
 		driver->log_mask->log_mask_size = size;
-		memcpy(buf, driver->log_mask, header_size);
-		memcpy(buf+header_size, driver->log_masks+ptr->index, size);
-		msleep(100);
-		if (ch)
-			smd_write(ch, buf, header_size + size);
+		/* send only desired update, NOT ALL */
+		if (equip_id == ALL_EQUIP_ID || equip_id ==
+					 driver->log_mask->equip_id) {
+			memcpy(buf, driver->log_mask, header_size);
+			memcpy(buf+header_size, driver->log_masks+ptr->index,
+									 size);
+			if (ch) {
+				while (retry_count < 3) {
+					spin_lock_irqsave(&diag_cntl_lock,
+									 flags);
+					wr_size = smd_write(ch, buf,
+							 header_size + size);
+					spin_unlock_irqrestore(&diag_cntl_lock,
+									 flags);
+					if (wr_size == -ENOMEM) {
+						retry_count++;
+						usleep(20000);
+					} else
+						break;
+				}
+				if (wr_size != header_size + size)
+					pr_err("diag: log mask update failed"
+				 " %d, tried %d", wr_size, header_size + size);
+				else
+					pr_debug("diag: updated log equip ID %d"
+					",len %d\n", driver->log_mask->equip_id,
+					 driver->log_mask->log_mask_size);
+			} else
+				pr_err("diag: ch not valid for log update\n");
+		}
 		ptr++;
 	}
 }
@@ -711,6 +774,8 @@
 {
 	void *buf = driver->buf_event_mask_update;
 	int header_size = sizeof(struct diag_ctrl_event_mask);
+	int wr_size = -ENOMEM, retry_count = 0;
+	unsigned long flags = 0;
 
 	/* send event mask update */
 	driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
@@ -721,43 +786,79 @@
 	driver->event_mask->event_mask_size = num_bytes;
 	memcpy(buf, driver->event_mask, header_size);
 	memcpy(buf+header_size, driver->event_masks, num_bytes);
-	msleep(100);
-	if (ch)
-		smd_write(ch, buf, header_size + num_bytes);
+	if (ch) {
+		while (retry_count < 3) {
+			spin_lock_irqsave(&diag_cntl_lock, flags);
+			wr_size = smd_write(ch, buf, header_size + num_bytes);
+			spin_unlock_irqrestore(&diag_cntl_lock, flags);
+			if (wr_size == -ENOMEM) {
+				retry_count++;
+				usleep(20000);
+			} else
+				break;
+		}
+		if (wr_size != header_size + num_bytes)
+			pr_err("diag: error writing event mask %d, tried %d\n",
+					 wr_size, header_size + num_bytes);
+	} else
+		pr_err("diag: ch not valid for event update\n");
 }
 
-void diag_send_msg_mask_update(smd_channel_t *ch)
+void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
+						int updated_ssid_last, int proc)
 {
 	void *buf = driver->buf_msg_mask_update;
-	int first, last;
+	int first, last, size = -ENOMEM, retry_count = 0;
 	int header_size = sizeof(struct diag_ctrl_msg_mask);
 	uint8_t *ptr = driver->msg_masks;
+	unsigned long flags = 0;
 
 	while (*(uint32_t *)(ptr + 4)) {
 		first = *(uint32_t *)ptr;
 		ptr += 4;
 		last = *(uint32_t *)ptr;
 		ptr += 4;
-		/* send event mask update */
-		driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
-		driver->msg_mask->msg_mask_size = last - first + 1;
-		driver->msg_mask->data_len = 11 +
-				 4 * (driver->msg_mask->msg_mask_size);
-		driver->msg_mask->stream_id = 1; /* 2, if dual stream */
-		driver->msg_mask->status = 3; /* status for valid mask */
-		driver->msg_mask->msg_mode = 0; /* Legcay mode */
-		driver->msg_mask->ssid_first = first;
-		driver->msg_mask->ssid_last = last;
-		memcpy(buf, driver->msg_mask, header_size);
-		memcpy(buf+header_size, ptr,
-			 4 * (driver->msg_mask->msg_mask_size));
-		/* since mask updates are slow, so sleep needed as to
-		   prevent modem running out of DSM items */
-		msleep(100);
-		if (ch)
-			smd_write(ch, buf,
+		if ((updated_ssid_first >= first && updated_ssid_last <= last)
+					 || (updated_ssid_first == ALL_SSID)) {
+			/* send f3 mask update */
+			driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
+			driver->msg_mask->msg_mask_size = last - first + 1;
+			driver->msg_mask->data_len = 11 +
+					 4 * (driver->msg_mask->msg_mask_size);
+			driver->msg_mask->stream_id = 1; /* 2, if dual stream */
+			driver->msg_mask->status = 3; /* status valid mask */
+			driver->msg_mask->msg_mode = 0; /* Legcay mode */
+			driver->msg_mask->ssid_first = first;
+			driver->msg_mask->ssid_last = last;
+			memcpy(buf, driver->msg_mask, header_size);
+			memcpy(buf+header_size, ptr,
+				 4 * (driver->msg_mask->msg_mask_size));
+			if (ch) {
+				while (retry_count < 3) {
+					spin_lock_irqsave(&diag_cntl_lock,
+									 flags);
+					size = smd_write(ch, buf, header_size +
+					 4*(driver->msg_mask->msg_mask_size));
+					spin_unlock_irqrestore(&diag_cntl_lock,
+									 flags);
+					if (size == -ENOMEM) {
+						retry_count++;
+						usleep(20000);
+					} else
+						break;
+				}
+				if (size != header_size +
+					 4*(driver->msg_mask->msg_mask_size))
+					pr_err("diag:  msg mask update fail %d,"
+							" tried %d\n", size,
 			 header_size + 4*(driver->msg_mask->msg_mask_size));
-		ptr += ((last - first) + 1)*4;
+				else
+					pr_debug("diag: sending mask update for"
+		" ssid first %d, last %d on PROC %d\n", first, last, proc);
+			} else
+				pr_err("diag: ch invalid msg mask update\n");
+		}
+		ptr += MAX_SSID_PER_RANGE*4;
 	}
 }
 
@@ -787,8 +888,15 @@
 			payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
 			for (i = 0; i < payload_length; i++)
 				*(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
-			queue_work(driver->diag_cntl_wq,
-				 &(driver->diag_log_mask_update_work));
+			if (driver->ch_cntl)
+				diag_send_log_mask_update(driver->ch_cntl,
+								 *(int *)buf);
+			if (driver->chqdsp_cntl)
+				diag_send_log_mask_update(driver->chqdsp_cntl,
+								 *(int *)buf);
+			if (driver->ch_wcnss_cntl)
+				diag_send_log_mask_update(driver->ch_wcnss_cntl,
+								 *(int *)buf);
 			ENCODE_RSP_AND_SEND(12 + payload_length - 1);
 			return 0;
 		} else
@@ -799,6 +907,8 @@
 		ssid_first = *(uint16_t *)(buf + 2);
 		ssid_last = *(uint16_t *)(buf + 4);
 		ssid_range = 4 * (ssid_last - ssid_first + 1);
+		pr_debug("diag: received mask update for ssid_first = %d,"
+				" ssid_last = %d", ssid_first, ssid_last);
 		diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
 		diag_update_userspace_clients(MSG_MASKS_TYPE);
 #if defined(CONFIG_DIAG_OVER_USB)
@@ -806,8 +916,15 @@
 			for (i = 0; i < 8 + ssid_range; i++)
 				*(driver->apps_rsp_buf + i) = *(buf+i);
 			*(driver->apps_rsp_buf + 6) = 0x1;
-			queue_work(driver->diag_cntl_wq,
-				 &(driver->diag_msg_mask_update_work));
+			if (driver->ch_cntl)
+				diag_send_msg_mask_update(driver->ch_cntl,
+					 ssid_first, ssid_last, MODEM_PROC);
+			if (driver->chqdsp_cntl)
+				diag_send_msg_mask_update(driver->chqdsp_cntl,
+					 ssid_first, ssid_last, QDSP_PROC);
+			if (driver->ch_wcnss_cntl)
+				diag_send_msg_mask_update(driver->ch_wcnss_cntl,
+					 ssid_first, ssid_last, WCNSS_PROC);
 			ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
 			return 0;
 		} else
@@ -827,15 +944,15 @@
 							EVENT_LAST_ID + 1;
 			memcpy(driver->apps_rsp_buf+6, driver->event_masks,
 							 EVENT_LAST_ID/8+1);
-			/* cannot do this on work queue, as each event update
-			needs a num_bytes variable. Each queue_work call will
-			overwrite the previous input, as its the same struct */
-			diag_send_event_mask_update(driver->ch_cntl,
+			if (driver->ch_cntl)
+				diag_send_event_mask_update(driver->ch_cntl,
 							 diag_event_num_bytes);
-			diag_send_event_mask_update(driver->chqdsp_cntl,
+			if (driver->chqdsp_cntl)
+				diag_send_event_mask_update(driver->chqdsp_cntl,
 							 diag_event_num_bytes);
-			diag_send_event_mask_update(driver->ch_wcnss_cntl,
-							 diag_event_num_bytes);
+			if (driver->ch_wcnss_cntl)
+				diag_send_event_mask_update(
+				driver->ch_wcnss_cntl, diag_event_num_bytes);
 			ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
 			return 0;
 		} else
@@ -850,12 +967,15 @@
 			driver->apps_rsp_buf[0] = 0x60;
 			driver->apps_rsp_buf[1] = 0x0;
 			driver->apps_rsp_buf[2] = 0x0;
-			diag_send_event_mask_update(driver->ch_cntl,
+			if (driver->ch_cntl)
+				diag_send_event_mask_update(driver->ch_cntl,
 							 diag_event_num_bytes);
-			diag_send_event_mask_update(driver->chqdsp_cntl,
+			if (driver->chqdsp_cntl)
+				diag_send_event_mask_update(driver->chqdsp_cntl,
 							 diag_event_num_bytes);
-			diag_send_event_mask_update(driver->ch_wcnss_cntl,
-							 diag_event_num_bytes);
+			if (driver->ch_wcnss_cntl)
+				diag_send_event_mask_update(
+				driver->ch_wcnss_cntl, diag_event_num_bytes);
 			ENCODE_RSP_AND_SEND(2);
 			return 0;
 		}
@@ -1643,6 +1763,7 @@
 	    && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
 					     GFP_KERNEL)) == NULL)
 		goto err;
+	diag_create_msg_mask_table();
 	if (driver->log_masks == NULL &&
 	    (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
 		goto err;
@@ -1726,10 +1847,6 @@
 #ifdef CONFIG_DIAG_OVER_USB
 	INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
 	INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
-	INIT_WORK(&(driver->diag_msg_mask_update_work),
-						 diag_msg_mask_update_fn);
-	INIT_WORK(&(driver->diag_log_mask_update_work),
-						 diag_log_mask_update_fn);
 	INIT_WORK(&(driver->diag_modem_mask_update_work),
 						 diag_modem_mask_update_fn);
 	INIT_WORK(&(driver->diag_qdsp_mask_update_work),
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 9ef0199..5744459 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -29,8 +29,9 @@
 void diag_clear_reg(int);
 int chk_apps_only(void);
 void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
-void diag_send_msg_mask_update(smd_channel_t *);
-void diag_send_log_mask_update(smd_channel_t *);
+void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
+					 int ssid_last, int proc);
+void diag_send_log_mask_update(smd_channel_t *, int);
 /* State for diag forwarding */
 #ifdef CONFIG_DIAG_OVER_USB
 int diagfwd_connect(void);
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 59013e3..aec041c 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -106,12 +106,19 @@
 #define checkoffset(offset, size, max_size) \
 	((size) > (max_size) || (offset) > ((max_size) - (size)))
 
+struct msm_rotator_fd_info {
+	int pid;
+	int ref_cnt;
+	struct list_head list;
+};
+
 struct msm_rotator_dev {
 	void __iomem *io_base;
 	int irq;
 	struct msm_rotator_img_info *img_info[MAX_SESSIONS];
 	struct clk *core_clk;
-	int pid_list[MAX_SESSIONS];
+	struct msm_rotator_fd_info *fd_info[MAX_SESSIONS];
+	struct list_head fd_list;
 	struct clk *pclk;
 	int rot_clk_state;
 	struct regulator *regulator;
@@ -204,7 +211,7 @@
 		cancel_delayed_work(&msm_rotator_dev->imem_clk_work);
 		if (msm_rotator_dev->imem_clk_state != CLK_EN
 			&& msm_rotator_dev->imem_clk) {
-			clk_enable(msm_rotator_dev->imem_clk);
+			clk_prepare_enable(msm_rotator_dev->imem_clk);
 			msm_rotator_dev->imem_clk_state = CLK_EN;
 		}
 	}
@@ -233,7 +240,7 @@
 	if (mutex_trylock(&msm_rotator_dev->imem_lock)) {
 		if (msm_rotator_dev->imem_clk_state == CLK_EN
 		     && msm_rotator_dev->imem_clk) {
-			clk_disable(msm_rotator_dev->imem_clk);
+			clk_disable_unprepare(msm_rotator_dev->imem_clk);
 			msm_rotator_dev->imem_clk_state = CLK_DIS;
 		} else if (msm_rotator_dev->imem_clk_state == CLK_SUSPEND)
 			msm_rotator_dev->imem_clk_state = CLK_DIS;
@@ -248,18 +255,18 @@
 	if (msm_rotator_dev->regulator)
 		regulator_enable(msm_rotator_dev->regulator);
 	if (msm_rotator_dev->core_clk != NULL)
-		clk_enable(msm_rotator_dev->core_clk);
+		clk_prepare_enable(msm_rotator_dev->core_clk);
 	if (msm_rotator_dev->pclk != NULL)
-		clk_enable(msm_rotator_dev->pclk);
+		clk_prepare_enable(msm_rotator_dev->pclk);
 }
 
 /* disable clocks needed by rotator block */
 static void disable_rot_clks(void)
 {
 	if (msm_rotator_dev->core_clk != NULL)
-		clk_disable(msm_rotator_dev->core_clk);
+		clk_disable_unprepare(msm_rotator_dev->core_clk);
 	if (msm_rotator_dev->pclk != NULL)
-		clk_disable(msm_rotator_dev->pclk);
+		clk_disable_unprepare(msm_rotator_dev->pclk);
 	if (msm_rotator_dev->regulator)
 		regulator_disable(msm_rotator_dev->regulator);
 }
@@ -1162,7 +1169,8 @@
 
 }
 
-static int msm_rotator_start(unsigned long arg, int pid)
+static int msm_rotator_start(unsigned long arg,
+			     struct msm_rotator_fd_info *fd_info)
 {
 	struct msm_rotator_img_info info;
 	int rc = 0;
@@ -1256,7 +1264,7 @@
 			(unsigned int)msm_rotator_dev->img_info[s]
 			)) {
 			*(msm_rotator_dev->img_info[s]) = info;
-			msm_rotator_dev->pid_list[s] = pid;
+			msm_rotator_dev->fd_info[s] = fd_info;
 
 			if (msm_rotator_dev->last_session_idx == s)
 				msm_rotator_dev->last_session_idx =
@@ -1284,7 +1292,7 @@
 		info.session_id = (unsigned int)
 			msm_rotator_dev->img_info[first_free_index];
 		*(msm_rotator_dev->img_info[first_free_index]) = info;
-		msm_rotator_dev->pid_list[first_free_index] = pid;
+		msm_rotator_dev->fd_info[first_free_index] = fd_info;
 
 		if (copy_to_user((void __user *)arg, &info, sizeof(info)))
 			rc = -EFAULT;
@@ -1319,7 +1327,7 @@
 					INVALID_SESSION;
 			kfree(msm_rotator_dev->img_info[s]);
 			msm_rotator_dev->img_info[s] = NULL;
-			msm_rotator_dev->pid_list[s] = 0;
+			msm_rotator_dev->fd_info[s] = NULL;
 			break;
 		}
 	}
@@ -1337,24 +1345,45 @@
 static int
 msm_rotator_open(struct inode *inode, struct file *filp)
 {
-	int *id;
+	struct msm_rotator_fd_info *tmp, *fd_info = NULL;
 	int i;
 
 	if (filp->private_data)
 		return -EBUSY;
 
 	mutex_lock(&msm_rotator_dev->rotator_lock);
-	id = &msm_rotator_dev->pid_list[0];
-	for (i = 0; i < MAX_SESSIONS; i++, id++) {
-		if (*id == 0)
+	for (i = 0; i < MAX_SESSIONS; i++) {
+		if (msm_rotator_dev->fd_info[i] == NULL)
 			break;
 	}
+
+	if (i == MAX_SESSIONS) {
+		mutex_unlock(&msm_rotator_dev->rotator_lock);
+		return -EBUSY;
+	}
+
+	list_for_each_entry(tmp, &msm_rotator_dev->fd_list, list) {
+		if (tmp->pid == current->pid) {
+			fd_info = tmp;
+			break;
+		}
+	}
+
+	if (!fd_info) {
+		fd_info = kzalloc(sizeof(*fd_info), GFP_KERNEL);
+		if (!fd_info) {
+			mutex_unlock(&msm_rotator_dev->rotator_lock);
+			pr_err("%s: insufficient memory to alloc resources\n",
+			       __func__);
+			return -ENOMEM;
+		}
+		list_add(&fd_info->list, &msm_rotator_dev->fd_list);
+		fd_info->pid = current->pid;
+	}
+	fd_info->ref_cnt++;
 	mutex_unlock(&msm_rotator_dev->rotator_lock);
 
-	if (i == MAX_SESSIONS)
-		return -EBUSY;
-
-	filp->private_data = (void *)current->pid;
+	filp->private_data = fd_info;
 
 	return 0;
 }
@@ -1362,21 +1391,33 @@
 static int
 msm_rotator_close(struct inode *inode, struct file *filp)
 {
+	struct msm_rotator_fd_info *fd_info;
 	int s;
-	int pid;
 
-	pid = (int)filp->private_data;
+	fd_info = (struct msm_rotator_fd_info *)filp->private_data;
+
 	mutex_lock(&msm_rotator_dev->rotator_lock);
+	if (--fd_info->ref_cnt > 0) {
+		mutex_unlock(&msm_rotator_dev->rotator_lock);
+		return 0;
+	}
+
 	for (s = 0; s < MAX_SESSIONS; s++) {
 		if (msm_rotator_dev->img_info[s] != NULL &&
-			msm_rotator_dev->pid_list[s] == pid) {
+			msm_rotator_dev->fd_info[s] == fd_info) {
+			pr_debug("%s: freeing rotator session %p (pid %d)\n",
+				 __func__, msm_rotator_dev->img_info[s],
+				 fd_info->pid);
 			kfree(msm_rotator_dev->img_info[s]);
 			msm_rotator_dev->img_info[s] = NULL;
+			msm_rotator_dev->fd_info[s] = NULL;
 			if (msm_rotator_dev->last_session_idx == s)
 				msm_rotator_dev->last_session_idx =
 					INVALID_SESSION;
 		}
 	}
+	list_del(&fd_info->list);
+	kfree(fd_info);
 	mutex_unlock(&msm_rotator_dev->rotator_lock);
 
 	return 0;
@@ -1385,16 +1426,16 @@
 static long msm_rotator_ioctl(struct file *file, unsigned cmd,
 						 unsigned long arg)
 {
-	int pid;
+	struct msm_rotator_fd_info *fd_info;
 
 	if (_IOC_TYPE(cmd) != MSM_ROTATOR_IOCTL_MAGIC)
 		return -ENOTTY;
 
-	pid = (int)file->private_data;
+	fd_info = (struct msm_rotator_fd_info *)file->private_data;
 
 	switch (cmd) {
 	case MSM_ROTATOR_IOCTL_START:
-		return msm_rotator_start(arg, pid);
+		return msm_rotator_start(arg, fd_info);
 	case MSM_ROTATOR_IOCTL_ROTATE:
 		return msm_rotator_do_rotate(arg);
 	case MSM_ROTATOR_IOCTL_FINISH:
@@ -1437,6 +1478,7 @@
 
 	msm_rotator_dev->imem_owner = IMEM_NO_OWNER;
 	mutex_init(&msm_rotator_dev->imem_lock);
+	INIT_LIST_HEAD(&msm_rotator_dev->fd_list);
 	msm_rotator_dev->imem_clk_state = CLK_DIS;
 	INIT_DELAYED_WORK(&msm_rotator_dev->imem_clk_work,
 			  msm_rotator_imem_clk_work_f);
@@ -1537,7 +1579,7 @@
 
 #ifdef CONFIG_MSM_ROTATOR_USE_IMEM
 	if (msm_rotator_dev->imem_clk)
-		clk_enable(msm_rotator_dev->imem_clk);
+		clk_prepare_enable(msm_rotator_dev->imem_clk);
 #endif
 	enable_rot_clks();
 	ver = ioread32(MSM_ROTATOR_HW_VERSION);
@@ -1545,7 +1587,7 @@
 
 #ifdef CONFIG_MSM_ROTATOR_USE_IMEM
 	if (msm_rotator_dev->imem_clk)
-		clk_disable(msm_rotator_dev->imem_clk);
+		clk_disable_unprepare(msm_rotator_dev->imem_clk);
 #endif
 	if (ver != pdata->hardware_version_number)
 		pr_info("%s: invalid HW version ver 0x%x\n",
@@ -1646,7 +1688,7 @@
 	iounmap(msm_rotator_dev->io_base);
 	if (msm_rotator_dev->imem_clk) {
 		if (msm_rotator_dev->imem_clk_state == CLK_EN)
-			clk_disable(msm_rotator_dev->imem_clk);
+			clk_disable_unprepare(msm_rotator_dev->imem_clk);
 		clk_put(msm_rotator_dev->imem_clk);
 		msm_rotator_dev->imem_clk = NULL;
 	}
@@ -1672,7 +1714,7 @@
 	mutex_lock(&msm_rotator_dev->imem_lock);
 	if (msm_rotator_dev->imem_clk_state == CLK_EN
 		&& msm_rotator_dev->imem_clk) {
-		clk_disable(msm_rotator_dev->imem_clk);
+		clk_disable_unprepare(msm_rotator_dev->imem_clk);
 		msm_rotator_dev->imem_clk_state = CLK_SUSPEND;
 	}
 	mutex_unlock(&msm_rotator_dev->imem_lock);
@@ -1690,7 +1732,7 @@
 	mutex_lock(&msm_rotator_dev->imem_lock);
 	if (msm_rotator_dev->imem_clk_state == CLK_SUSPEND
 		&& msm_rotator_dev->imem_clk) {
-		clk_enable(msm_rotator_dev->imem_clk);
+		clk_prepare_enable(msm_rotator_dev->imem_clk);
 		msm_rotator_dev->imem_clk_state = CLK_EN;
 	}
 	mutex_unlock(&msm_rotator_dev->imem_lock);
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index bc288e7..9bb240c 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -145,6 +145,7 @@
 			unsigned int cmd)
 {
 	unsigned long vstart, pstart;
+	void *vend;
 	void *vtemp;
 	unsigned long ln = 0;
 	void (*op)(unsigned long, unsigned long, unsigned long);
@@ -163,14 +164,32 @@
 		return -EINVAL;
 	}
 
-	for (vtemp = buffer->priv_virt + offset,
-	     vstart = (unsigned long) vaddr;
-			ln < length;
+	vend = buffer->priv_virt + buffer->size;
+	vtemp = buffer->priv_virt + offset;
+
+	if ((vtemp+length) > vend) {
+		pr_err("Trying to flush outside of mapped range.\n");
+		pr_err("End of mapped range: %p, trying to flush to "
+			"address %p\n", vend, vtemp+length);
+		WARN(1, "%s: called with heap name %s, buffer size 0x%x, "
+			"vaddr 0x%p, offset 0x%x, length: 0x%x\n", __func__,
+			heap->name, buffer->size, vaddr, offset, length);
+		return -EINVAL;
+	}
+
+	for (vstart = (unsigned long) vaddr;
+			ln < length && vtemp < vend;
 			vtemp += PAGE_SIZE, ln += PAGE_SIZE,
 			vstart += PAGE_SIZE) {
-		pstart = page_to_phys(vmalloc_to_page(vtemp));
+		struct page *page = vmalloc_to_page(vtemp);
+		if (!page) {
+			WARN(1, "Could not find page for virt. address %p\n",
+				vtemp);
+			return -EINVAL;
+		}
+		pstart = page_to_phys(page);
 		/*
-		 * If vmalloc -> page -> phys is returning NULL, something
+		 * If page -> phys is returning NULL, something
 		 * has really gone wrong...
 		 */
 		if (!pstart) {
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index c3367b5..6cdb5f1 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -27,6 +27,7 @@
 	adreno_a2xx_trace.o \
 	adreno_a2xx_snapshot.o \
 	adreno_a3xx.o \
+	adreno_a3xx_trace.o \
 	adreno_a3xx_snapshot.o \
 	adreno.o
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ba39fe1..c76bfd0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -680,9 +680,7 @@
 	kgsl_sharedmem_writel(&device->memstore,
 			KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp),
 			eoptimestamp);
-	kgsl_sharedmem_writel(&device->memstore,
-			KGSL_MEMSTORE_OFFSET(context_id, soptimestamp),
-			soptimestamp);
+
 	if (num_rb_contents) {
 		kgsl_sharedmem_writel(&device->memstore,
 			KGSL_MEMSTORE_OFFSET(context_id, ref_wait_ts),
@@ -1011,6 +1009,10 @@
 	if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr, size))
 		return &device->memstore;
 
+	if (kgsl_gpuaddr_in_memdesc(&device->mmu.setstate_memory, gpuaddr,
+					size))
+		return &device->mmu.setstate_memory;
+
 	entry = kgsl_get_mem_entry(pt_base, gpuaddr, size);
 
 	if (entry)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 73cc46f..32603bd 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -19,6 +19,7 @@
 #include "kgsl_sharedmem.h"
 #include "kgsl_cffdump.h"
 #include "a3xx_reg.h"
+#include "adreno_a3xx_trace.h"
 
 /*
  * Set of registers to dump for A3XX on postmortem and snapshot.
@@ -2506,6 +2507,8 @@
 		tmp >>= 1;
 	}
 
+	trace_kgsl_a3xx_irq_status(device, status);
+
 	if (status)
 		adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD,
 			status);
diff --git a/drivers/gpu/msm/adreno_a3xx_trace.c b/drivers/gpu/msm/adreno_a3xx_trace.c
new file mode 100644
index 0000000..8b4a80d
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a3xx_trace.c
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "kgsl.h"
+#include "adreno.h"
+
+/* Instantiate tracepoints */
+#define CREATE_TRACE_POINTS
+#include "a3xx_reg.h"
+#include "adreno_a3xx_trace.h"
diff --git a/drivers/gpu/msm/adreno_a3xx_trace.h b/drivers/gpu/msm/adreno_a3xx_trace.h
new file mode 100644
index 0000000..44483a8
--- /dev/null
+++ b/drivers/gpu/msm/adreno_a3xx_trace.h
@@ -0,0 +1,89 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#if !defined(_ADRENO_A3XX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _ADRENO_A3XX_TRACE_H
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kgsl
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE adreno_a3xx_trace
+
+#include <linux/tracepoint.h>
+
+struct kgsl_device;
+
+/*
+ * Tracepoint for a3xx irq. Includes status info
+ */
+TRACE_EVENT(kgsl_a3xx_irq_status,
+
+	TP_PROTO(struct kgsl_device *device, unsigned int status),
+
+	TP_ARGS(device, status),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, status)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->status = status;
+	),
+
+	TP_printk(
+		"d_name=%s status=%s",
+		__get_str(device_name),
+		__entry->status ? __print_flags(__entry->status, "|",
+			{ 1 << A3XX_INT_RBBM_AHB_ERROR, "RBBM_GPU_IDLE" },
+			{ 1 << A3XX_INT_RBBM_AHB_ERROR, "RBBM_AHB_ERR" },
+			{ 1 << A3XX_INT_RBBM_REG_TIMEOUT, "RBBM_REG_TIMEOUT" },
+			{ 1 << A3XX_INT_RBBM_ME_MS_TIMEOUT,
+				"RBBM_ME_MS_TIMEOUT" },
+			{ 1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT,
+				"RBBM_PFP_MS_TIMEOUT" },
+			{ 1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW,
+				"RBBM_ATB_BUS_OVERFLOW" },
+			{ 1 << A3XX_INT_VFD_ERROR, "RBBM_VFD_ERROR" },
+			{ 1 << A3XX_INT_CP_SW_INT, "CP_SW" },
+			{ 1 << A3XX_INT_CP_T0_PACKET_IN_IB,
+				"CP_T0_PACKET_IN_IB" },
+			{ 1 << A3XX_INT_CP_OPCODE_ERROR, "CP_OPCODE_ERROR" },
+			{ 1 << A3XX_INT_CP_RESERVED_BIT_ERROR,
+				"CP_RESERVED_BIT_ERROR" },
+			{ 1 << A3XX_INT_CP_HW_FAULT, "CP_HW_FAULT" },
+			{ 1 << A3XX_INT_CP_DMA, "CP_DMA" },
+			{ 1 << A3XX_INT_CP_IB2_INT, "CP_IB2_INT" },
+			{ 1 << A3XX_INT_CP_IB1_INT, "CP_IB1_INT" },
+			{ 1 << A3XX_INT_CP_RB_INT, "CP_RB_INT" },
+			{ 1 << A3XX_INT_CP_REG_PROTECT_FAULT,
+				"CP_REG_PROTECT_FAULT" },
+			{ 1 << A3XX_INT_CP_RB_DONE_TS, "CP_RB_DONE_TS" },
+			{ 1 << A3XX_INT_CP_VS_DONE_TS, "CP_VS_DONE_TS" },
+			{ 1 << A3XX_INT_CP_PS_DONE_TS, "CP_PS_DONE_TS" },
+			{ 1 << A3XX_INT_CACHE_FLUSH_TS, "CACHE_FLUSH_TS" },
+			{ 1 << A3XX_INT_CP_AHB_ERROR_HALT,
+				"CP_AHB_ERROR_HALT" },
+			{ 1 << A3XX_INT_MISC_HANG_DETECT, "MISC_HANG_DETECT" },
+			{ 1 << A3XX_INT_UCHE_OOB_ACCESS, "UCHE_OOB_ACCESS" })
+		: "None"
+	)
+);
+
+#endif /* _ADRENO_A3XX_TRACE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 334b29f..fece715 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -355,4 +355,13 @@
 int kgsl_device_snapshot(struct kgsl_device *device, int hang);
 void kgsl_device_snapshot_close(struct kgsl_device *device);
 
+static inline struct kgsl_device_platform_data *
+kgsl_device_get_drvdata(struct kgsl_device *dev)
+{
+	struct platform_device *pdev =
+		container_of(dev->parentdev, struct platform_device, dev);
+
+	return pdev->dev.platform_data;
+}
+
 #endif  /* __KGSL_DEVICE_H */
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ea11068..50086d2 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -150,16 +150,15 @@
 static int kgsl_get_iommu_ctxt(struct kgsl_iommu *iommu,
 				struct kgsl_device *device)
 {
-	struct platform_device *pdev =
-		container_of(device->parentdev, struct platform_device, dev);
-	struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
+	struct kgsl_device_platform_data *pdata =
+		kgsl_device_get_drvdata(device);
 	int i, ret = 0;
 
 	/* Go through the IOMMU data and attach all the domains */
 
-	for (i = 0; i < pdata_dev->iommu_count; i++) {
+	for (i = 0; i < pdata->iommu_count; i++) {
 		ret = _get_iommu_ctxs(iommu, device,
-			&pdata_dev->iommu_data[i]);
+			&pdata->iommu_data[i]);
 		if (ret)
 			break;
 	}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 7c451a9..17f978e 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -64,6 +64,9 @@
 		new_level >= pwr->thermal_pwrlevel &&
 		new_level != pwr->active_pwrlevel) {
 		struct kgsl_pwrlevel *pwrlevel = &pwr->pwrlevels[new_level];
+		int diff = new_level - pwr->active_pwrlevel;
+		int d = (diff > 0) ? 1 : -1;
+		int level = pwr->active_pwrlevel;
 		pwr->active_pwrlevel = new_level;
 		if ((test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) ||
 			(device->state == KGSL_STATE_NAP)) {
@@ -75,7 +78,14 @@
 			if (pwr->idle_needed == true)
 				device->ftbl->idle(device,
 						KGSL_TIMEOUT_DEFAULT);
-			clk_set_rate(pwr->grp_clks[0], pwrlevel->gpu_freq);
+			/* Don't shift by more than one level at a time to
+			 * avoid glitches.
+			 */
+			while (level != new_level) {
+				level += d;
+				clk_set_rate(pwr->grp_clks[0],
+						pwr->pwrlevels[level].gpu_freq);
+			}
 		}
 		if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
 			if (pwr->pcl)
@@ -346,22 +356,32 @@
 			for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
 				if (pwr->grp_clks[i])
 					clk_disable(pwr->grp_clks[i]);
+			/* High latency clock maintenance. */
 			if ((pwr->pwrlevels[0].gpu_freq > 0) &&
-				(requested_state != KGSL_STATE_NAP))
+				(requested_state != KGSL_STATE_NAP)) {
 				clk_set_rate(pwr->grp_clks[0],
 					pwr->pwrlevels[pwr->num_pwrlevels - 1].
 					gpu_freq);
+				for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
+					if (pwr->grp_clks[i])
+						clk_unprepare(pwr->grp_clks[i]);
+			}
 			kgsl_pwrctrl_busy_time(device, true);
 		}
 	} else if (state == KGSL_PWRFLAGS_ON) {
 		if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON,
 			&pwr->power_flags)) {
 			trace_kgsl_clk(device, state);
+			/* High latency clock maintenance. */
 			if ((pwr->pwrlevels[0].gpu_freq > 0) &&
-				(device->state != KGSL_STATE_NAP))
+				(device->state != KGSL_STATE_NAP)) {
+				for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
+					if (pwr->grp_clks[i])
+						clk_prepare(pwr->grp_clks[i]);
 				clk_set_rate(pwr->grp_clks[0],
 					pwr->pwrlevels[pwr->active_pwrlevel].
 						gpu_freq);
+			}
 
 			/* as last step, enable grp_clk
 			   this is to let GPU interrupt to come */
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index ddc641d..b2b3071 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -84,10 +84,14 @@
 {
 	int ret;
 
-	if (device->pwrscale.policy)
-		ret = snprintf(buf, PAGE_SIZE, "%s\n",
+	if (device->pwrscale.policy) {
+		ret = snprintf(buf, PAGE_SIZE, "%s",
 			       device->pwrscale.policy->name);
-	else
+		if (device->pwrscale.enabled == 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				" (disabled)");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	} else
 		ret = snprintf(buf, PAGE_SIZE, "none\n");
 
 	return ret;
@@ -210,23 +214,26 @@
 	.release = pwrscale_sysfs_release
 };
 
+#define PWRSCALE_ACTIVE(_d) \
+	((_d)->pwrscale.policy && (_d)->pwrscale.enabled)
+
 void kgsl_pwrscale_sleep(struct kgsl_device *device)
 {
-	if (device->pwrscale.policy && device->pwrscale.policy->sleep)
+	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->sleep)
 		device->pwrscale.policy->sleep(device, &device->pwrscale);
 }
 EXPORT_SYMBOL(kgsl_pwrscale_sleep);
 
 void kgsl_pwrscale_wake(struct kgsl_device *device)
 {
-	if (device->pwrscale.policy && device->pwrscale.policy->wake)
+	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->wake)
 		device->pwrscale.policy->wake(device, &device->pwrscale);
 }
 EXPORT_SYMBOL(kgsl_pwrscale_wake);
 
 void kgsl_pwrscale_busy(struct kgsl_device *device)
 {
-	if (device->pwrscale.policy && device->pwrscale.policy->busy)
+	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->busy)
 		if ((!device->pwrscale.gpu_busy) &&
 			(device->requested_state != KGSL_STATE_SLUMBER))
 			device->pwrscale.policy->busy(device,
@@ -236,7 +243,7 @@
 
 void kgsl_pwrscale_idle(struct kgsl_device *device)
 {
-	if (device->pwrscale.policy && device->pwrscale.policy->idle)
+	if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle)
 		if (device->requested_state !=
 			(KGSL_STATE_SLUMBER | KGSL_STATE_SLEEP))
 			device->pwrscale.policy->idle(device,
@@ -245,6 +252,18 @@
 }
 EXPORT_SYMBOL(kgsl_pwrscale_idle);
 
+void kgsl_pwrscale_disable(struct kgsl_device *device)
+{
+	device->pwrscale.enabled = 0;
+}
+EXPORT_SYMBOL(kgsl_pwrscale_disable);
+
+void kgsl_pwrscale_enable(struct kgsl_device *device)
+{
+	device->pwrscale.enabled = 1;
+}
+EXPORT_SYMBOL(kgsl_pwrscale_enable);
+
 int kgsl_pwrscale_policy_add_files(struct kgsl_device *device,
 				   struct kgsl_pwrscale *pwrscale,
 				   struct attribute_group *attr_group)
@@ -314,6 +333,9 @@
 
 	device->pwrscale.policy = policy;
 
+	/* Pwrscale is enabled by default at attach time */
+	kgsl_pwrscale_enable(device);
+
 	if (policy) {
 		ret = device->pwrscale.policy->init(device, &device->pwrscale);
 		if (ret)
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index 6023476..34698cd 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -37,6 +37,7 @@
 	struct kobject kobj;
 	void *priv;
 	int gpu_busy;
+	int enabled;
 };
 
 struct kgsl_pwrscale_policy_attribute {
@@ -68,6 +69,9 @@
 void kgsl_pwrscale_sleep(struct kgsl_device *device);
 void kgsl_pwrscale_wake(struct kgsl_device *device);
 
+void kgsl_pwrscale_enable(struct kgsl_device *device);
+void kgsl_pwrscale_disable(struct kgsl_device *device);
+
 int kgsl_pwrscale_policy_add_files(struct kgsl_device *device,
 				   struct kgsl_pwrscale *pwrscale,
 				   struct attribute_group *attr_group);
diff --git a/drivers/media/video/msm/actuators/Makefile b/drivers/media/video/msm/actuators/Makefile
index d492155..70a3a19 100644
--- a/drivers/media/video/msm/actuators/Makefile
+++ b/drivers/media/video/msm/actuators/Makefile
@@ -2,6 +2,3 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 obj-$(CONFIG_MSM_ACTUATOR) += msm_actuator.o
-obj-$(CONFIG_IMX074_ACT) += imx074_act.o
-obj-$(CONFIG_DW9712_ACT) += dw9712_act.o
-obj-$(CONFIG_AD5046_ACT) += ad5046_act.o
diff --git a/drivers/media/video/msm/actuators/ad5046_act.c b/drivers/media/video/msm/actuators/ad5046_act.c
deleted file mode 100644
index d99774b..0000000
--- a/drivers/media/video/msm/actuators/ad5046_act.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "msm_actuator.h"
-#include "msm_camera_i2c.h"
-
-#define	AD5046_TOTAL_STEPS_NEAR_TO_FAR			32
-static uint8_t  mode_mask = 0x09;
-DEFINE_MUTEX(ad5046_act_mutex);
-static struct msm_actuator_ctrl_t ad5046_act_t;
-
-static struct region_params_t g_regions[] = {
-	/* step_bound[0] - macro side boundary
-	 * step_bound[1] - infinity side boundary
-	 */
-	/* Region 1 */
-	{
-		.step_bound = {AD5046_TOTAL_STEPS_NEAR_TO_FAR, 0},
-		.code_per_step = 2,
-	},
-};
-
-static uint16_t g_scenario[] = {
-	/* MOVE_NEAR and MOVE_FAR dir*/
-	AD5046_TOTAL_STEPS_NEAR_TO_FAR,
-};
-
-static int32_t ad5046_af_i2c_txdata(unsigned short saddr,
-				unsigned char *txdata, int length,
-				struct msm_actuator_ctrl_t *a_ctrl)
-{
-	struct i2c_msg msg[] = {
-		{
-			.addr = saddr,
-			.flags = 0,
-			.len = length,
-			.buf = txdata,
-		},
-	};
-	if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
-		pr_err("ad5046_af_i2c_txdata faild 0x%x\n", saddr);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int32_t ad5046_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
-			      uint8_t waddr, uint8_t bdata)
-{
-	int32_t rc = -EFAULT;
-	unsigned char buf[2];
-
-	memset(buf, 0, sizeof(buf));
-	buf[0] = waddr;
-	buf[1] = bdata;
-	rc = ad5046_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
-	if (rc < 0)
-		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-				waddr, bdata);
-
-	return rc;
-}
-
-static int32_t ad5046_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
-	int16_t next_lens_position, void *params)
-{
-	uint8_t msb, lsb;
-
-	msb = (next_lens_position & 0xFF00) >> 8;
-	lsb = next_lens_position & 0xFF;
-	ad5046_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
-
-	return 0;
-}
-
-int32_t msm_ad5046_act_move_focus(
-	struct msm_actuator_ctrl_t *a_ctrl,
-	int dir,
-	int32_t num_steps)
-{
-	int32_t rc = 0;
-	int8_t sign_dir = 0;
-	int16_t dest_step_pos = 0;
-	uint8_t code_val_msb, code_val_lsb;
-
-	CDBG("%s called, dir %d, num_steps %d\n",
-		__func__,
-		dir,
-		num_steps);
-
-	/* Determine sign direction */
-	if (dir == MOVE_NEAR)
-		sign_dir = 20;
-	else if (dir == MOVE_FAR)
-		sign_dir = -20;
-	else {
-		pr_err("Illegal focus direction\n");
-		rc = -EINVAL;
-		return rc;
-	}
-
-	/* Determine destination step position */
-	dest_step_pos = a_ctrl->curr_step_pos +
-		(sign_dir * num_steps);
-
-	if (dest_step_pos < 0)
-		dest_step_pos = 0;
-	else if (dest_step_pos > 1023)
-		dest_step_pos = 1023;
-
-	if (dest_step_pos == a_ctrl->curr_step_pos)
-		return rc;
-
-	a_ctrl->curr_step_pos = dest_step_pos;
-
-	code_val_msb = (uint8_t)((dest_step_pos & 0x03FF) >> 4);
-	code_val_lsb = (uint8_t)((dest_step_pos & 0x000F) << 4);
-	code_val_lsb |= mode_mask;
-
-	rc = ad5046_af_i2c_write_b_sensor(a_ctrl, code_val_msb, code_val_lsb);
-	/* DAC Setting */
-	if (rc != 0) {
-		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
-			__func__, code_val_lsb, code_val_msb);
-	} else {
-		CDBG(KERN_ERR "%s: Successful lsb = 0x%x, msb = 0x%x",
-			__func__, code_val_lsb, code_val_msb);
-		/* delay may set based on the steps moved
-		when I2C write successful */
-		msleep(100);
-	}
-	return 0;
-}
-
-static int32_t ad5046_set_default_focus(
-	struct msm_actuator_ctrl_t *a_ctrl)
-{
-	uint8_t  code_val_msb = 0;
-	uint8_t  code_val_lsb = 0;
-	int rc = 0;
-
-	CDBG("ad5046_set_default_focus called\n");
-
-	if (!a_ctrl->step_position_table)
-		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
-
-	a_ctrl->curr_step_pos = 200;
-
-	code_val_msb = (a_ctrl->curr_step_pos & 0x03FF) >> 4;
-	code_val_lsb = (a_ctrl->curr_step_pos & 0x000F) << 4;
-	code_val_lsb |= mode_mask;
-
-	CDBG(KERN_ERR "ad5046_set_default_focus:lens pos = %d",
-		 a_ctrl->curr_step_pos);
-	rc = ad5046_af_i2c_write_b_sensor(a_ctrl, code_val_msb, code_val_lsb);
-	/* DAC Setting */
-	if (rc != 0)
-		CDBG(KERN_ERR "%s: WRITE ERROR lsb = 0x%x, msb = 0x%x",
-			__func__, code_val_lsb, code_val_msb);
-	else
-		CDBG(KERN_ERR "%s: WRITE successful lsb = 0x%x, msb = 0x%x",
-			__func__, code_val_lsb, code_val_msb);
-
-	usleep_range(10000, 11000);
-	return 0;
-}
-
-static const struct i2c_device_id ad5046_act_i2c_id[] = {
-	{"ad5046_act", (kernel_ulong_t)&ad5046_act_t},
-	{ }
-};
-
-static int ad5046_act_config(void __user *argp)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_config(&ad5046_act_t, argp);
-}
-
-static int ad5046_i2c_add_driver_table(void)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_init_table(&ad5046_act_t);
-}
-
-int32_t ad5046_act_i2c_probe(
-	struct i2c_client *client,
-	const struct i2c_device_id *id)
-{
-	int32_t rc = 0;
-
-	rc = msm_actuator_i2c_probe(client, id);
-
-	msleep(50);
-
-	return rc;
-}
-static struct i2c_driver ad5046_act_i2c_driver = {
-	.id_table = ad5046_act_i2c_id,
-	.probe  = ad5046_act_i2c_probe,
-	.remove = __exit_p(ad5046_act_i2c_remove),
-	.driver = {
-		.name = "ad5046_act",
-	},
-};
-
-static int __init ad5046_i2c_add_driver(void)
-{
-	int rc = 0;
-
-	LINFO("%s called :%x\n", __func__, ad5046_act_t.i2c_addr);
-	rc = i2c_add_driver(ad5046_act_t.i2c_driver);
-	LINFO("%s called:%d %x\n", __func__, rc, ad5046_act_t.i2c_addr);
-	return rc;
-}
-
-static struct v4l2_subdev_core_ops ad5046_act_subdev_core_ops;
-
-static struct v4l2_subdev_ops ad5046_act_subdev_ops = {
-	.core = &ad5046_act_subdev_core_ops,
-};
-
-static int32_t ad5046_act_create_subdevice(
-	void *board_info,
-	void *sdev)
-{
-	int rc = 0;
-
-	struct msm_actuator_info *ptr;
-	LINFO("%s called\n", __func__);
-
-	ptr = board_info;
-	ad5046_act_t.vcm_pwd = ptr->vcm_pwd;
-	ad5046_act_t.vcm_enable = ptr->vcm_enable;
-	LINFO("vcm info: %x %x\n", ad5046_act_t.vcm_pwd,
-				ad5046_act_t.vcm_enable);
-	if (ad5046_act_t.vcm_enable) {
-		rc = gpio_request(ad5046_act_t.vcm_pwd, "ov5647_af");
-		if (!rc) {
-			LINFO("Enable VCM PWD\n");
-			gpio_direction_output(ad5046_act_t.vcm_pwd, 1);
-		}
-		msleep(20);
-
-	}
-	return (int) msm_actuator_create_subdevice(&ad5046_act_t,
-		ptr->board_info,
-		(struct v4l2_subdev *)sdev);
-}
-
-static struct msm_actuator_ctrl_t ad5046_act_t = {
-	.i2c_driver = &ad5046_act_i2c_driver,
-	.i2c_addr = 0x18>>1,
-	.act_v4l2_subdev_ops = &ad5046_act_subdev_ops,
-	.actuator_ext_ctrl = {
-		.a_init_table = ad5046_i2c_add_driver_table,
-		.a_create_subdevice = ad5046_act_create_subdevice,
-		.a_config = ad5046_act_config,
-	},
-
-	.i2c_client = {
-		.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
-	},
-
-	.set_info = {
-		.total_steps = AD5046_TOTAL_STEPS_NEAR_TO_FAR,
-	},
-
-	.curr_step_pos = 0,
-	.curr_region_index = 0,
-	.initial_code = 0x0,
-	.actuator_mutex = &ad5046_act_mutex,
-
-	.func_tbl = {
-		.actuator_init_table = msm_actuator_init_table,
-		.actuator_move_focus = msm_ad5046_act_move_focus,
-		.actuator_set_default_focus = ad5046_set_default_focus,
-		.actuator_i2c_write = ad5046_wrapper_i2c_write,
-	},
-
-	.get_info = {
-		.focal_length_num = 46,
-		.focal_length_den = 10,
-		.f_number_num = 265,
-		.f_number_den = 100,
-		.f_pix_num = 14,
-		.f_pix_den = 10,
-		.total_f_dist_num = 197681,
-		.total_f_dist_den = 1000,
-	},
-
-	/* Initialize scenario */
-	.ringing_scenario[MOVE_NEAR] = g_scenario,
-	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
-	.ringing_scenario[MOVE_FAR] = g_scenario,
-	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
-
-	/* Initialize region params */
-	.region_params = g_regions,
-	.region_size = ARRAY_SIZE(g_regions),
-};
-
-subsys_initcall(ad5046_i2c_add_driver);
-MODULE_DESCRIPTION("AD5046 actuator");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/dw9712_act.c b/drivers/media/video/msm/actuators/dw9712_act.c
deleted file mode 100644
index 546cffa..0000000
--- a/drivers/media/video/msm/actuators/dw9712_act.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "msm_actuator.h"
-#include "msm_camera_i2c.h"
-
-#define	DW9712_TOTAL_STEPS_NEAR_TO_FAR			32
-DEFINE_MUTEX(dw9712_act_mutex);
-static struct msm_actuator_ctrl_t dw9712_act_t;
-
-static struct region_params_t g_regions[] = {
-	/* step_bound[0] - macro side boundary
-	 * step_bound[1] - infinity side boundary
-	 */
-	/* Region 1 */
-	{
-		.step_bound = {DW9712_TOTAL_STEPS_NEAR_TO_FAR, 0},
-		.code_per_step = 2,
-	},
-};
-
-static uint16_t g_scenario[] = {
-	/* MOVE_NEAR and MOVE_FAR dir*/
-	DW9712_TOTAL_STEPS_NEAR_TO_FAR,
-};
-
-static int32_t dw9712_af_i2c_txdata(unsigned short saddr,
-				unsigned char *txdata, int length,
-				struct msm_actuator_ctrl_t *a_ctrl)
-{
-	struct i2c_msg msg[] = {
-		{
-			.addr = saddr,
-			.flags = 0,
-			.len = length,
-			.buf = txdata,
-		},
-	};
-	if (i2c_transfer(a_ctrl->i2c_client.client->adapter, msg, 1) < 0) {
-		pr_err("s5k4e1_af_i2c_txdata faild 0x%x\n", saddr);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int32_t dw9712_af_i2c_write_b_sensor(struct msm_actuator_ctrl_t *a_ctrl,
-			      uint8_t waddr, uint8_t bdata)
-{
-	int32_t rc = -EFAULT;
-	unsigned char buf[2];
-
-	memset(buf, 0, sizeof(buf));
-	buf[0] = waddr;
-	buf[1] = bdata;
-	rc = dw9712_af_i2c_txdata(a_ctrl->i2c_addr, buf, 2, a_ctrl);
-	if (rc < 0) {
-		pr_err("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
-				waddr, bdata);
-	}
-	return rc;
-}
-
-static int32_t dw9712_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
-	int16_t next_lens_position, void *params)
-{
-	uint8_t msb, lsb;
-
-	msb = (next_lens_position & 0xFF00) >> 8;
-	lsb = next_lens_position & 0xFF;
-	dw9712_af_i2c_write_b_sensor(a_ctrl, msb, lsb);
-
-	return 0;
-}
-
-int32_t msm_dw9712_act_move_focus(
-	struct msm_actuator_ctrl_t *a_ctrl,
-	int dir,
-	int32_t num_steps)
-{
-	int32_t rc = 0;
-	int8_t sign_dir = 0;
-	int16_t dest_step_pos = 0;
-	uint8_t code_val_msb, code_val_lsb;
-	uint16_t code_val;
-
-	LINFO("%s called, dir %d, num_steps %d\n",
-		__func__,
-		dir,
-		num_steps);
-
-	/* Determine sign direction */
-	if (dir == MOVE_NEAR)
-		sign_dir = 16;
-	else if (dir == MOVE_FAR)
-		sign_dir = -16;
-	else {
-		pr_err("Illegal focus direction\n");
-		rc = -EINVAL;
-		return rc;
-	}
-
-	/* Determine destination step position */
-	dest_step_pos = a_ctrl->curr_step_pos +
-		(sign_dir * num_steps);
-
-	if (dest_step_pos < 0)
-		dest_step_pos = 0;
-	else if (dest_step_pos > 1023)
-		dest_step_pos = 1023;
-
-	if (dest_step_pos == a_ctrl->curr_step_pos)
-		return rc;
-
-	code_val_msb = dest_step_pos >> 4;
-	code_val_lsb = (dest_step_pos & 0x000F) << 4;
-	code_val = (code_val_msb << 8) | (code_val_lsb);
-	rc = dw9712_wrapper_i2c_write(a_ctrl, code_val, NULL);
-	if (rc >= 0) {
-		rc = 0;
-		a_ctrl->curr_step_pos = dest_step_pos;
-	}
-	return 0;
-}
-
-static int32_t dw9712_set_default_focus(
-	struct msm_actuator_ctrl_t *a_ctrl)
-{
-	int32_t rc = 0;
-
-	if (!a_ctrl->step_position_table)
-		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
-
-	if (a_ctrl->curr_step_pos != 0) {
-		rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl,
-				MOVE_FAR, a_ctrl->curr_step_pos);
-		a_ctrl->curr_step_pos = 0;
-	} else
-		rc = dw9712_wrapper_i2c_write(a_ctrl, 0x00, NULL);
-		if (rc >= 0)
-			rc = 0;
-	return rc;
-}
-
-static const struct i2c_device_id dw9712_act_i2c_id[] = {
-	{"dw9712_act", (kernel_ulong_t)&dw9712_act_t},
-	{ }
-};
-
-static int dw9712_act_config(void __user *argp)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_config(&dw9712_act_t, argp);
-}
-
-static int dw9712_i2c_add_driver_table(void)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_init_table(&dw9712_act_t);
-}
-
-static struct i2c_driver dw9712_act_i2c_driver = {
-	.id_table = dw9712_act_i2c_id,
-	.probe  = msm_actuator_i2c_probe,
-	.remove = __exit_p(dw9712_act_i2c_remove),
-	.driver = {
-		.name = "dw9712_act",
-	},
-};
-
-static int __init dw9712_i2c_add_driver(void)
-{
-	int rc = 0;
-
-	LINFO("%s called :%x\n", __func__, dw9712_act_t.i2c_addr);
-	rc = i2c_add_driver(dw9712_act_t.i2c_driver);
-	LINFO("%s called:%d %x\n", __func__, rc, dw9712_act_t.i2c_addr);
-	return rc;
-}
-
-static struct v4l2_subdev_core_ops dw9712_act_subdev_core_ops;
-
-static struct v4l2_subdev_ops dw9712_act_subdev_ops = {
-	.core = &dw9712_act_subdev_core_ops,
-};
-
-static int32_t dw9712_act_create_subdevice(
-	void *board_info,
-	void *sdev)
-{
-	int rc = 0;
-
-	struct msm_actuator_info *ptr;
-	LINFO("%s called\n", __func__);
-
-	ptr = board_info;
-	dw9712_act_t.vcm_pwd = ptr->vcm_pwd;
-	dw9712_act_t.vcm_enable = ptr->vcm_enable;
-	LINFO("vcm info: %x %x\n", dw9712_act_t.vcm_pwd,
-				dw9712_act_t.vcm_enable);
-	if (dw9712_act_t.vcm_enable) {
-		rc = gpio_request(dw9712_act_t.vcm_pwd, "dw9712_af");
-		if (!rc) {
-			LINFO("Enable VCM PWD\n");
-			gpio_direction_output(dw9712_act_t.vcm_pwd, 1);
-		}
-	}
-	return (int) msm_actuator_create_subdevice(&dw9712_act_t,
-		ptr->board_info,
-		(struct v4l2_subdev *)sdev);
-}
-
-static struct msm_actuator_ctrl_t dw9712_act_t = {
-	.i2c_driver = &dw9712_act_i2c_driver,
-	.i2c_addr = 0x8C,
-	.act_v4l2_subdev_ops = &dw9712_act_subdev_ops,
-	.actuator_ext_ctrl = {
-		.a_init_table = dw9712_i2c_add_driver_table,
-		.a_create_subdevice = dw9712_act_create_subdevice,
-		.a_config = dw9712_act_config,
-	},
-
-	.i2c_client = {
-		.addr_type = MSM_CAMERA_I2C_WORD_ADDR,
-	},
-
-	.set_info = {
-		.total_steps = DW9712_TOTAL_STEPS_NEAR_TO_FAR,
-	},
-
-	.curr_step_pos = 0,
-	.curr_region_index = 0,
-	.initial_code = 0x0,
-	.actuator_mutex = &dw9712_act_mutex,
-
-	.func_tbl = {
-		.actuator_init_table = msm_actuator_init_table,
-		.actuator_move_focus = msm_dw9712_act_move_focus,
-		.actuator_set_default_focus = dw9712_set_default_focus,
-		.actuator_i2c_write = dw9712_wrapper_i2c_write,
-	},
-
-	.get_info = {
-		.focal_length_num = 46,
-		.focal_length_den = 10,
-		.f_number_num = 265,
-		.f_number_den = 100,
-		.f_pix_num = 14,
-		.f_pix_den = 10,
-		.total_f_dist_num = 197681,
-		.total_f_dist_den = 1000,
-	},
-
-	/* Initialize scenario */
-	.ringing_scenario[MOVE_NEAR] = g_scenario,
-	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
-	.ringing_scenario[MOVE_FAR] = g_scenario,
-	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
-
-	/* Initialize region params */
-	.region_params = g_regions,
-	.region_size = ARRAY_SIZE(g_regions),
-};
-
-subsys_initcall(dw9712_i2c_add_driver);
-MODULE_DESCRIPTION("DW9712 actuator");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/imx074_act.c b/drivers/media/video/msm/actuators/imx074_act.c
deleted file mode 100644
index aa6f966..0000000
--- a/drivers/media/video/msm/actuators/imx074_act.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include "msm_actuator.h"
-#include "msm_camera_i2c.h"
-
-#define	IMX074_TOTAL_STEPS_NEAR_TO_FAR			41
-DEFINE_MUTEX(imx074_act_mutex);
-static struct msm_actuator_ctrl_t imx074_act_t;
-
-static struct region_params_t g_regions[] = {
-	/* step_bound[0] - macro side boundary
-	 * step_bound[1] - infinity side boundary
-	 */
-	/* Region 1 */
-	{
-		.step_bound = {IMX074_TOTAL_STEPS_NEAR_TO_FAR, 0},
-		.code_per_step = 2,
-	},
-};
-
-static uint16_t g_scenario[] = {
-	/* MOVE_NEAR and MOVE_FAR dir*/
-	IMX074_TOTAL_STEPS_NEAR_TO_FAR,
-};
-
-static struct damping_params_t g_damping[] = {
-	/* MOVE_NEAR Dir */
-	/* Scene 1 => Damping params */
-	{
-		.damping_step = 0xFF,
-		.damping_delay = 0,
-	},
-};
-
-static struct damping_t g_damping_params[] = {
-	/* MOVE_NEAR and MOVE_FAR dir */
-	/* Region 1 */
-	{
-		.ringing_params = g_damping,
-	},
-};
-
-static int32_t imx074_wrapper_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
-	int16_t next_lens_position, void *params)
-{
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-			     0x00,
-			     next_lens_position,
-			     MSM_CAMERA_I2C_BYTE_DATA);
-	return 0;
-}
-
-int32_t imx074_act_write_focus(
-	struct msm_actuator_ctrl_t *a_ctrl,
-	uint16_t curr_lens_pos,
-	struct damping_params_t *damping_params,
-	int8_t sign_direction,
-	int16_t code_boundary)
-{
-	int32_t rc = 0;
-	uint16_t dac_value = 0;
-
-	LINFO("%s called, curr lens pos = %d, code_boundary = %d\n",
-		  __func__,
-		  curr_lens_pos,
-		  code_boundary);
-
-	if (sign_direction == 1)
-		dac_value = (code_boundary - curr_lens_pos) | 0x80;
-	else
-		dac_value = (curr_lens_pos - code_boundary);
-
-	LINFO("%s dac_value = %d\n",
-	      __func__,
-	      dac_value);
-
-	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, dac_value, NULL);
-
-	return rc;
-}
-
-int32_t imx074_act_move_focus(
-	struct msm_actuator_ctrl_t *a_ctrl,
-	int dir,
-	int32_t num_steps)
-{
-	int32_t step_direction, dest_step_position, bit_mask;
-	int32_t rc = 0;
-
-	if (num_steps == 0)
-		return rc;
-
-	if (dir == MOVE_NEAR) {
-		step_direction = 1;
-		bit_mask = 0x80;
-	} else if (dir == MOVE_FAR) {
-		step_direction = -1;
-		bit_mask = 0x00;
-	} else {
-		CDBG("imx074_move_focus: Illegal focus direction");
-		return -EINVAL;
-	}
-	dest_step_position = a_ctrl->curr_step_pos +
-		(step_direction * num_steps);
-	if (dest_step_position < 0)
-		dest_step_position = 0;
-	else if (dest_step_position > IMX074_TOTAL_STEPS_NEAR_TO_FAR)
-		dest_step_position = IMX074_TOTAL_STEPS_NEAR_TO_FAR;
-
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x00,
-		((num_steps * g_regions[0].code_per_step) | bit_mask),
-		MSM_CAMERA_I2C_BYTE_DATA);
-	a_ctrl->curr_step_pos = dest_step_position;
-	return rc;
-}
-
-static int32_t imx074_set_default_focus(
-	struct msm_actuator_ctrl_t *a_ctrl)
-{
-	int32_t rc = 0;
-
-	if (!a_ctrl->step_position_table)
-		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
-
-	if (a_ctrl->curr_step_pos != 0) {
-		rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F, NULL);
-		rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F, NULL);
-		a_ctrl->curr_step_pos = 0;
-	} else if (a_ctrl->func_tbl.actuator_init_focus)
-		rc = a_ctrl->func_tbl.actuator_init_focus(a_ctrl);
-	return rc;
-}
-
-static int32_t imx074_act_init_focus(struct msm_actuator_ctrl_t *a_ctrl)
-{
-	int32_t rc;
-	LINFO("%s called\n",
-	      __func__);
-	/* Initialize to infinity */
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x01,
-		0xA9,
-		MSM_CAMERA_I2C_BYTE_DATA);
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x02,
-		0xD2,
-		MSM_CAMERA_I2C_BYTE_DATA);
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x03,
-		0x0C,
-		MSM_CAMERA_I2C_BYTE_DATA);
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x04,
-		0x14,
-		MSM_CAMERA_I2C_BYTE_DATA);
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x05,
-		0xB6,
-		MSM_CAMERA_I2C_BYTE_DATA);
-	msm_camera_i2c_write(&a_ctrl->i2c_client,
-		0x06,
-		0x4F,
-		MSM_CAMERA_I2C_BYTE_DATA);
-
-	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F, NULL);
-	rc = a_ctrl->func_tbl.actuator_i2c_write(a_ctrl, 0x7F, NULL);
-	a_ctrl->curr_step_pos = 0;
-	return rc;
-}
-
-static const struct i2c_device_id imx074_act_i2c_id[] = {
-	{"imx074_act", (kernel_ulong_t)&imx074_act_t},
-	{ }
-};
-
-static int imx074_act_config(
-	void __user *argp)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_config(&imx074_act_t, argp);
-}
-
-static int imx074_i2c_add_driver_table(
-	void)
-{
-	LINFO("%s called\n", __func__);
-	return (int) msm_actuator_init_table(&imx074_act_t);
-}
-
-static struct i2c_driver imx074_act_i2c_driver = {
-	.id_table = imx074_act_i2c_id,
-	.probe  = msm_actuator_i2c_probe,
-	.remove = __exit_p(imx074_act_i2c_remove),
-	.driver = {
-		.name = "imx074_act",
-	},
-};
-
-static int __init imx074_i2c_add_driver(
-	void)
-{
-	LINFO("%s called\n", __func__);
-	return i2c_add_driver(imx074_act_t.i2c_driver);
-}
-
-static struct v4l2_subdev_core_ops imx074_act_subdev_core_ops;
-
-static struct v4l2_subdev_ops imx074_act_subdev_ops = {
-	.core = &imx074_act_subdev_core_ops,
-};
-
-static int32_t imx074_act_create_subdevice(
-	void *act_info,
-	void *sdev)
-{
-	struct msm_actuator_info *info = (struct msm_actuator_info *)act_info;
-	LINFO("%s called\n", __func__);
-
-	return (int) msm_actuator_create_subdevice(&imx074_act_t,
-		(struct i2c_board_info const *)info->board_info,
-		(struct v4l2_subdev *)sdev);
-}
-
-static int imx074_act_power_down(void *act_info)
-{
-	return (int) msm_actuator_af_power_down(&imx074_act_t);
-}
-
-static struct msm_actuator_ctrl_t imx074_act_t = {
-	.i2c_driver = &imx074_act_i2c_driver,
-	.i2c_addr = 0xE4,
-	.act_v4l2_subdev_ops = &imx074_act_subdev_ops,
-	.actuator_ext_ctrl = {
-		.a_init_table = imx074_i2c_add_driver_table,
-		.a_create_subdevice = imx074_act_create_subdevice,
-		.a_config = imx074_act_config,
-		.a_power_down = imx074_act_power_down,
-	},
-
-	.i2c_client = {
-		.addr_type = MSM_CAMERA_I2C_BYTE_ADDR,
-	},
-
-	.set_info = {
-		.total_steps = IMX074_TOTAL_STEPS_NEAR_TO_FAR,
-	},
-
-	.curr_step_pos = 0,
-	.curr_region_index = 0,
-	.initial_code = 0x7F,
-	.actuator_mutex = &imx074_act_mutex,
-
-	.func_tbl = {
-		.actuator_init_table = msm_actuator_init_table,
-		.actuator_move_focus = imx074_act_move_focus,
-		.actuator_write_focus = imx074_act_write_focus,
-		.actuator_set_default_focus = imx074_set_default_focus,
-		.actuator_init_focus = imx074_act_init_focus,
-		.actuator_i2c_write = imx074_wrapper_i2c_write,
-	},
-
-	.get_info = {
-		.focal_length_num = 46,
-		.focal_length_den = 10,
-		.f_number_num = 265,
-		.f_number_den = 100,
-		.f_pix_num = 14,
-		.f_pix_den = 10,
-		.total_f_dist_num = 197681,
-		.total_f_dist_den = 1000,
-		.hor_view_angle_num = 548,
-		.hor_view_angle_den = 10,
-		.ver_view_angle_num = 425,
-		.ver_view_angle_den = 10,
-	},
-
-	/* Initialize scenario */
-	.ringing_scenario[MOVE_NEAR] = g_scenario,
-	.scenario_size[MOVE_NEAR] = ARRAY_SIZE(g_scenario),
-	.ringing_scenario[MOVE_FAR] = g_scenario,
-	.scenario_size[MOVE_FAR] = ARRAY_SIZE(g_scenario),
-
-	/* Initialize region params */
-	.region_params = g_regions,
-	.region_size = ARRAY_SIZE(g_regions),
-
-	/* Initialize damping params */
-	.damping[MOVE_NEAR] = g_damping_params,
-	.damping[MOVE_FAR] = g_damping_params,
-};
-
-subsys_initcall(imx074_i2c_add_driver);
-MODULE_DESCRIPTION("IMX074 actuator");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index f0023d7..e16766c 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,146 @@
 
 #include "msm_actuator.h"
 
+static struct msm_actuator_ctrl_t msm_actuator_t;
+
+static struct msm_actuator msm_vcm_actuator_table = {
+	.act_type = ACTUATOR_VCM,
+	.func_tbl = {
+		.actuator_init_step_table = msm_actuator_init_step_table,
+		.actuator_move_focus = msm_actuator_move_focus,
+		.actuator_write_focus = msm_actuator_write_focus,
+		.actuator_set_default_focus = msm_actuator_set_default_focus,
+		.actuator_init_focus = msm_actuator_init_focus,
+		.actuator_i2c_write = msm_actuator_i2c_write,
+	},
+};
+
+static struct msm_actuator msm_piezo_actuator_table = {
+	.act_type = ACTUATOR_PIEZO,
+	.func_tbl = {
+		.actuator_init_step_table = NULL,
+		.actuator_move_focus = msm_actuator_piezo_move_focus,
+		.actuator_write_focus = NULL,
+		.actuator_set_default_focus =
+			msm_actuator_piezo_set_default_focus,
+		.actuator_init_focus = msm_actuator_init_focus,
+		.actuator_i2c_write = msm_actuator_i2c_write,
+	},
+};
+
+static struct msm_actuator *actuators[] = {
+	&msm_vcm_actuator_table,
+	&msm_piezo_actuator_table,
+};
+
+int32_t msm_actuator_piezo_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t rc = 0;
+
+	if (a_ctrl->curr_step_pos != 0) {
+		rc = a_ctrl->func_tbl->actuator_i2c_write(a_ctrl,
+			a_ctrl->initial_code, 0);
+		rc = a_ctrl->func_tbl->actuator_i2c_write(a_ctrl,
+			a_ctrl->initial_code, 0);
+		a_ctrl->curr_step_pos = 0;
+	}
+	return rc;
+}
+
+int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+	int16_t next_lens_position, uint32_t hw_params)
+{
+	struct msm_actuator_reg_params_t *write_arr = a_ctrl->reg_tbl;
+	uint32_t hw_dword = hw_params;
+	uint16_t i2c_byte1 = 0, i2c_byte2 = 0;
+	uint16_t value = 0;
+	uint32_t size = a_ctrl->reg_tbl_size, i = 0;
+	int32_t rc = 0;
+	CDBG("%s: IN\n", __func__);
+	for (i = 0; i < size; i++) {
+		if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
+			value = (next_lens_position <<
+				write_arr[i].data_shift) |
+				((hw_dword & write_arr[i].hw_mask) >>
+				write_arr[i].hw_shift);
+
+			if (write_arr[i].reg_addr != 0xFFFF) {
+				i2c_byte1 = write_arr[i].reg_addr;
+				i2c_byte2 = value;
+				if (size != (i+1)) {
+					i2c_byte2 = (i2c_byte2 & 0xFF00) >> 8;
+					CDBG("%s: byte1:0x%x, byte2:0x%x\n",
+					__func__, i2c_byte1, i2c_byte2);
+					rc = msm_camera_i2c_write(
+						&a_ctrl->i2c_client,
+						i2c_byte1, i2c_byte2,
+						a_ctrl->i2c_data_type);
+					if (rc < 0) {
+						pr_err("%s: i2c write error:%d\n",
+							__func__, rc);
+						return rc;
+					}
+
+					i++;
+					i2c_byte1 = write_arr[i].reg_addr;
+					i2c_byte2 = value & 0xFF;
+				}
+			} else {
+				i2c_byte1 = (value & 0xFF00) >> 8;
+				i2c_byte2 = value & 0xFF;
+			}
+		} else {
+			i2c_byte1 = write_arr[i].reg_addr;
+			i2c_byte2 = (hw_dword & write_arr[i].hw_mask) >>
+				write_arr[i].hw_shift;
+		}
+		CDBG("%s: i2c_byte1:0x%x, i2c_byte2:0x%x\n", __func__,
+			i2c_byte1, i2c_byte2);
+		rc = msm_camera_i2c_write(&a_ctrl->i2c_client,
+			i2c_byte1, i2c_byte2, a_ctrl->i2c_data_type);
+	}
+		CDBG("%s: OUT\n", __func__);
+	return rc;
+}
+
+int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
+	uint16_t size, enum msm_actuator_data_type type,
+	struct reg_settings_t *settings)
+{
+	int32_t rc = -EFAULT;
+	int32_t i = 0;
+	CDBG("%s called\n", __func__);
+
+	for (i = 0; i < size; i++) {
+		switch (type) {
+		case MSM_ACTUATOR_BYTE_DATA:
+			rc = msm_camera_i2c_write(
+				&a_ctrl->i2c_client,
+				settings[i].reg_addr,
+				settings[i].reg_data, MSM_CAMERA_I2C_BYTE_DATA);
+			break;
+		case MSM_ACTUATOR_WORD_DATA:
+			rc = msm_camera_i2c_write(
+				&a_ctrl->i2c_client,
+				settings[i].reg_addr,
+				settings[i].reg_data, MSM_CAMERA_I2C_WORD_DATA);
+			break;
+		default:
+			pr_err("%s: Unsupport data type: %d\n",
+				__func__, type);
+			break;
+		}
+		if (rc < 0)
+			break;
+	}
+
+	a_ctrl->curr_step_pos = 0;
+	CDBG("%s Exit:%d\n", __func__, rc);
+	return rc;
+}
+
 int32_t msm_actuator_write_focus(
 	struct msm_actuator_ctrl_t *a_ctrl,
 	uint16_t curr_lens_pos,
@@ -35,15 +175,20 @@
 		next_lens_pos =
 			(next_lens_pos +
 				(sign_direction * damping_code_step))) {
-		rc = a_ctrl->func_tbl.
+		rc = a_ctrl->func_tbl->
 			actuator_i2c_write(a_ctrl, next_lens_pos,
 				damping_params->hw_params);
+		if (rc < 0) {
+			pr_err("%s: error:%d\n",
+				__func__, rc);
+			return rc;
+		}
 		curr_lens_pos = next_lens_pos;
 		usleep(wait_time);
 	}
 
 	if (curr_lens_pos != code_boundary) {
-		rc = a_ctrl->func_tbl.
+		rc = a_ctrl->func_tbl->
 			actuator_i2c_write(a_ctrl, code_boundary,
 				damping_params->hw_params);
 		usleep(wait_time);
@@ -51,59 +196,49 @@
 	return rc;
 }
 
+int32_t msm_actuator_piezo_move_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t dest_step_position = move_params->dest_step_pos;
+	int32_t rc = 0;
+	int32_t num_steps = move_params->num_steps;
+
+	if (num_steps == 0)
+		return rc;
+
+	rc = a_ctrl->func_tbl->
+		actuator_i2c_write(a_ctrl,
+		(num_steps *
+		a_ctrl->region_params[0].code_per_step),
+		move_params->ringing_params[0].hw_params);
+
+	a_ctrl->curr_step_pos = dest_step_position;
+	return rc;
+}
 
 int32_t msm_actuator_move_focus(
 	struct msm_actuator_ctrl_t *a_ctrl,
-	int dir,
-	int32_t num_steps)
+	struct msm_actuator_move_params_t *move_params)
 {
 	int32_t rc = 0;
-	int8_t sign_dir = 0;
-	uint16_t curr_scene = 0;
-	uint16_t scenario_size = 0;
-	uint16_t index = 0;
+	int8_t sign_dir = move_params->sign_dir;
 	uint16_t step_boundary = 0;
 	uint16_t target_step_pos = 0;
 	uint16_t target_lens_pos = 0;
-	int16_t dest_step_pos = 0;
+	int16_t dest_step_pos = move_params->dest_step_pos;
 	uint16_t curr_lens_pos = 0;
-	LINFO("%s called, dir %d, num_steps %d\n",
+	int dir = move_params->dir;
+	int32_t num_steps = move_params->num_steps;
+
+	CDBG("%s called, dir %d, num_steps %d\n",
 		__func__,
 		dir,
 		num_steps);
 
-	/* Determine sign direction */
-	if (dir == MOVE_NEAR)
-		sign_dir = 1;
-	else if (dir == MOVE_FAR)
-		sign_dir = -1;
-	else {
-		pr_err("Illegal focus direction\n");
-		rc = -EINVAL;
-		return rc;
-	}
-
-	/* Determine destination step position */
-	dest_step_pos = a_ctrl->curr_step_pos +
-		(sign_dir * num_steps);
-
-	if (dest_step_pos < 0)
-		dest_step_pos = 0;
-	else if (dest_step_pos > a_ctrl->set_info.total_steps)
-		dest_step_pos = a_ctrl->set_info.total_steps;
-
 	if (dest_step_pos == a_ctrl->curr_step_pos)
 		return rc;
 
-	/* Determine scenario */
-	scenario_size = a_ctrl->scenario_size[dir];
-	for (index = 0; index < scenario_size; index++) {
-		if (num_steps <= a_ctrl->ringing_scenario[dir][index]) {
-			curr_scene = index;
-			break;
-		}
-	}
-
 	curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos];
 	CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n",
 		a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos);
@@ -118,29 +253,41 @@
 			target_step_pos = dest_step_pos;
 			target_lens_pos =
 				a_ctrl->step_position_table[target_step_pos];
-			curr_lens_pos = a_ctrl->func_tbl.
+			rc = a_ctrl->func_tbl->
 				actuator_write_focus(
 					a_ctrl,
 					curr_lens_pos,
-					&(a_ctrl->damping[dir]\
-						[a_ctrl->curr_region_index].
-						ringing_params[curr_scene]),
+					&(move_params->
+						ringing_params[a_ctrl->
+						curr_region_index]),
 					sign_dir,
 					target_lens_pos);
+			if (rc < 0) {
+				pr_err("%s: error:%d\n",
+					__func__, rc);
+				return rc;
+			}
+			curr_lens_pos = target_lens_pos;
 
 		} else {
 			target_step_pos = step_boundary;
 			target_lens_pos =
 				a_ctrl->step_position_table[target_step_pos];
-			curr_lens_pos = a_ctrl->func_tbl.
+			rc = a_ctrl->func_tbl->
 				actuator_write_focus(
 					a_ctrl,
 					curr_lens_pos,
-					&(a_ctrl->damping[dir]\
-						[a_ctrl->curr_region_index].
-						ringing_params[curr_scene]),
+					&(move_params->
+						ringing_params[a_ctrl->
+						curr_region_index]),
 					sign_dir,
 					target_lens_pos);
+			if (rc < 0) {
+				pr_err("%s: error:%d\n",
+					__func__, rc);
+				return rc;
+			}
+			curr_lens_pos = target_lens_pos;
 
 			a_ctrl->curr_region_index += sign_dir;
 		}
@@ -150,24 +297,33 @@
 	return rc;
 }
 
-int32_t msm_actuator_init_table(
-	struct msm_actuator_ctrl_t *a_ctrl)
+int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_set_info_t *set_info)
 {
 	int16_t code_per_step = 0;
 	int32_t rc = 0;
 	int16_t cur_code = 0;
 	int16_t step_index = 0, region_index = 0;
 	uint16_t step_boundary = 0;
-	LINFO("%s called\n", __func__);
+	uint32_t max_code_size = 1;
+	uint16_t data_size = set_info->actuator_params.data_size;
+	CDBG("%s called\n", __func__);
 
-	if (a_ctrl->func_tbl.actuator_set_params)
-		a_ctrl->func_tbl.actuator_set_params(a_ctrl);
+	for (; data_size > 0; data_size--)
+		max_code_size *= 2;
+
+	kfree(a_ctrl->step_position_table);
+	a_ctrl->step_position_table = NULL;
 
 	/* Fill step position table */
 	a_ctrl->step_position_table =
-		kmalloc(sizeof(uint16_t) * (a_ctrl->set_info.total_steps + 1),
-			GFP_KERNEL);
-	cur_code = a_ctrl->initial_code;
+		kmalloc(sizeof(uint16_t) *
+		(set_info->af_tuning_params.total_steps + 1), GFP_KERNEL);
+
+	if (a_ctrl->step_position_table == NULL)
+		return -EFAULT;
+
+	cur_code = set_info->af_tuning_params.initial_code;
 	a_ctrl->step_position_table[step_index++] = cur_code;
 	for (region_index = 0;
 		region_index < a_ctrl->region_size;
@@ -180,58 +336,174 @@
 		for (; step_index <= step_boundary;
 			step_index++) {
 			cur_code += code_per_step;
-			a_ctrl->step_position_table[step_index] = cur_code;
+			if (cur_code < max_code_size)
+				a_ctrl->step_position_table[step_index] =
+					cur_code;
+			else {
+				for (; step_index <
+					set_info->af_tuning_params.total_steps;
+					step_index++)
+					a_ctrl->
+						step_position_table[
+						step_index] =
+						max_code_size;
+
+				return rc;
+			}
 		}
 	}
-	for (step_index = 0;
-		step_index < a_ctrl->set_info.total_steps;
-		step_index++) {
-		CDBG("step_position_table[%d]= %d\n",
-			step_index,
-			a_ctrl->step_position_table[step_index]);
+
+	return rc;
+}
+
+int32_t msm_actuator_set_default_focus(
+	struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_move_params_t *move_params)
+{
+	int32_t rc = 0;
+	CDBG("%s called\n", __func__);
+
+	if (a_ctrl->curr_step_pos != 0)
+		rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl, move_params);
+	return rc;
+}
+
+int32_t msm_actuator_af_power_down(void *cfg_data)
+{
+	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
+	int32_t rc = 0;
+	int16_t step_pos = 0;
+	int16_t i = 0;
+	CDBG("%s called\n", __func__);
+
+	if (a_ctrl->step_position_table) {
+		if (a_ctrl->step_position_table[a_ctrl->curr_step_pos] >=
+			a_ctrl->step_position_table[a_ctrl->pwd_step]) {
+			step_pos = (a_ctrl->
+				step_position_table[a_ctrl->curr_step_pos] -
+				a_ctrl->step_position_table[a_ctrl->
+				pwd_step]) / 10;
+			for (i = 0; i < 10; i++) {
+				rc = a_ctrl->func_tbl->
+					actuator_i2c_write(a_ctrl,
+					i * step_pos, 0);
+				usleep(500);
+			}
+			rc = a_ctrl->func_tbl->actuator_i2c_write(a_ctrl,
+				a_ctrl->step_position_table[a_ctrl->
+				curr_step_pos],
+				0);
+		}
+		CDBG("%s after msm_actuator_set_default_focus\n", __func__);
+		kfree(a_ctrl->step_position_table);
 	}
 
+	if (a_ctrl->vcm_enable) {
+		rc = gpio_direction_output(a_ctrl->vcm_pwd, 0);
+		if (!rc)
+			gpio_free(a_ctrl->vcm_pwd);
+	}
+
+	a_ctrl->step_position_table = NULL;
+	return rc;
+}
+
+int32_t msm_actuator_init(struct msm_actuator_ctrl_t *a_ctrl,
+	struct msm_actuator_set_info_t *set_info) {
+	struct reg_settings_t *init_settings = NULL;
+	int32_t rc = -EFAULT;
+	uint16_t i = 0;
+	CDBG("%s: IN\n", __func__);
+
+	for (i = 0; i < ARRAY_SIZE(actuators); i++) {
+		if (set_info->actuator_params.act_type ==
+			actuators[i]->act_type) {
+			a_ctrl->func_tbl = &actuators[i]->func_tbl;
+			rc = 0;
+		}
+	}
+
+	if (rc < 0) {
+		pr_err("%s: Actuator function table not found\n", __func__);
+		return rc;
+	}
+
+	a_ctrl->region_size = set_info->af_tuning_params.region_size;
+	if (a_ctrl->region_size > MAX_ACTUATOR_REGION) {
+		pr_err("%s: MAX_ACTUATOR_REGION is exceeded.\n", __func__);
+		return -EFAULT;
+	}
+	a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
+	a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step;
+	a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
+
+	if (copy_from_user(&a_ctrl->region_params,
+		(void *)set_info->af_tuning_params.region_params,
+		a_ctrl->region_size * sizeof(struct region_params_t)))
+		return -EFAULT;
+
+	a_ctrl->i2c_data_type = set_info->actuator_params.i2c_data_type;
+	a_ctrl->i2c_client.client->addr = set_info->actuator_params.i2c_addr;
+	a_ctrl->i2c_client.addr_type = set_info->actuator_params.i2c_addr_type;
+	a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
+	if (a_ctrl->reg_tbl_size > MAX_ACTUATOR_REG_TBL_SIZE) {
+		pr_err("%s: MAX_ACTUATOR_REG_TBL_SIZE is exceeded.\n",
+			__func__);
+		return -EFAULT;
+	}
+	if (copy_from_user(&a_ctrl->reg_tbl,
+		(void *)set_info->actuator_params.reg_tbl_params,
+		a_ctrl->reg_tbl_size *
+		sizeof(struct msm_actuator_reg_params_t)))
+		return -EFAULT;
+
+	if (set_info->actuator_params.init_setting_size) {
+		if (a_ctrl->func_tbl->actuator_init_focus) {
+			init_settings = kmalloc(sizeof(struct reg_settings_t) *
+				(set_info->actuator_params.init_setting_size),
+				GFP_KERNEL);
+			if (init_settings == NULL) {
+				pr_err("%s Error allocating memory for init_settings\n",
+					__func__);
+				return -EFAULT;
+			}
+			if (copy_from_user(init_settings,
+				(void *)set_info->actuator_params.init_settings,
+				set_info->actuator_params.init_setting_size *
+				sizeof(struct reg_settings_t))) {
+				kfree(init_settings);
+				pr_err("%s Error copying init_settings\n",
+					__func__);
+				return -EFAULT;
+			}
+			rc = a_ctrl->func_tbl->actuator_init_focus(a_ctrl,
+				set_info->actuator_params.init_setting_size,
+				a_ctrl->i2c_data_type,
+				init_settings);
+			kfree(init_settings);
+			if (rc < 0) {
+				pr_err("%s Error actuator_init_focus\n",
+					__func__);
+				return -EFAULT;
+			}
+		}
+	}
+
+	a_ctrl->initial_code = set_info->af_tuning_params.initial_code;
+	if (a_ctrl->func_tbl->actuator_init_step_table)
+		rc = a_ctrl->func_tbl->
+			actuator_init_step_table(a_ctrl, set_info);
+
 	a_ctrl->curr_step_pos = 0;
 	a_ctrl->curr_region_index = 0;
 
 	return rc;
 }
 
-int32_t msm_actuator_set_default_focus(
-	struct msm_actuator_ctrl_t *a_ctrl)
+
+int32_t msm_actuator_config(void __user *argp)
 {
-	int32_t rc = 0;
-	LINFO("%s called\n", __func__);
-
-	if (!a_ctrl->step_position_table)
-		a_ctrl->func_tbl.actuator_init_table(a_ctrl);
-
-	if (a_ctrl->curr_step_pos != 0)
-		rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl, MOVE_FAR,
-			a_ctrl->curr_step_pos);
-	else if (a_ctrl->func_tbl.actuator_init_focus)
-		rc = a_ctrl->func_tbl.actuator_init_focus(a_ctrl);
-	return rc;
-}
-
-int32_t msm_actuator_af_power_down(struct msm_actuator_ctrl_t *a_ctrl)
-{
-	int32_t rc = 0;
-	LINFO("%s called\n", __func__);
-
-	if (a_ctrl->step_position_table[a_ctrl->curr_step_pos] !=
-		a_ctrl->initial_code) {
-		rc = a_ctrl->func_tbl.actuator_set_default_focus(a_ctrl);
-		LINFO("%s after msm_actuator_set_default_focus\n", __func__);
-	}
-	kfree(a_ctrl->step_position_table);
-	return rc;
-}
-
-int32_t msm_actuator_config(
-	struct msm_actuator_ctrl_t *a_ctrl,
-	void __user *argp)
-{
+	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
 	struct msm_actuator_cfg_data cdata;
 	int32_t rc = 0;
 	if (copy_from_user(&cdata,
@@ -239,35 +511,26 @@
 		sizeof(struct msm_actuator_cfg_data)))
 		return -EFAULT;
 	mutex_lock(a_ctrl->actuator_mutex);
-	LINFO("%s called, type %d\n", __func__, cdata.cfgtype);
+	CDBG("%s called, type %d\n", __func__, cdata.cfgtype);
 	switch (cdata.cfgtype) {
-	case CFG_GET_ACTUATOR_INFO:
-		cdata.is_af_supported = 1;
-		cdata.cfg.get_info = a_ctrl->get_info;
-		if (copy_to_user((void *)argp,
-				 &cdata,
-				 sizeof(struct msm_actuator_cfg_data)))
-			rc = -EFAULT;
-		break;
 	case CFG_SET_ACTUATOR_INFO:
-		a_ctrl->set_info = cdata.cfg.set_info;
-		rc = a_ctrl->func_tbl.actuator_init_table(a_ctrl);
+		rc = msm_actuator_init(a_ctrl, &cdata.cfg.set_info);
 		if (rc < 0)
-			LERROR("%s init table failed %d\n", __func__, rc);
+			pr_err("%s init table failed %d\n", __func__, rc);
 		break;
 
 	case CFG_SET_DEFAULT_FOCUS:
-		rc = a_ctrl->func_tbl.actuator_set_default_focus(a_ctrl);
+		rc = a_ctrl->func_tbl->actuator_set_default_focus(a_ctrl,
+			&cdata.cfg.move);
 		if (rc < 0)
-			LERROR("%s move focus failed %d\n", __func__, rc);
+			pr_err("%s move focus failed %d\n", __func__, rc);
 		break;
 
 	case CFG_MOVE_FOCUS:
-		rc = a_ctrl->func_tbl.actuator_move_focus(a_ctrl,
-			cdata.cfg.move.dir,
-			cdata.cfg.move.num_steps);
+		rc = a_ctrl->func_tbl->actuator_move_focus(a_ctrl,
+			&cdata.cfg.move);
 		if (rc < 0)
-			LERROR("%s move focus failed %d\n", __func__, rc);
+			pr_err("%s move focus failed %d\n", __func__, rc);
 		break;
 
 	default:
@@ -283,7 +546,7 @@
 {
 	int rc = 0;
 	struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
-	LINFO("%s called\n", __func__);
+	CDBG("%s called\n", __func__);
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		pr_err("i2c_check_functionality failed\n");
@@ -292,17 +555,13 @@
 
 	act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
 	i2c_set_clientdata(client, (void *)&act_ctrl_t->actuator_ext_ctrl);
-	LINFO("%s client = %x act ctrl t = %x\n",
+	CDBG("%s client = %x act ctrl t = %x\n",
 		__func__,
 		(unsigned int) client,
 		(unsigned int)&act_ctrl_t->actuator_ext_ctrl);
 	act_ctrl_t->i2c_client.client = client;
-	if (act_ctrl_t->i2c_addr != 0)
-		act_ctrl_t->i2c_client.client->addr =
-			act_ctrl_t->i2c_addr;
 
-	/* act_ctrl_t->func_tbl.actuator_init_table(act_ctrl_t); */
-	LINFO("%s succeeded\n", __func__);
+	CDBG("%s succeeded\n", __func__);
 	return rc;
 
 probe_failure:
@@ -310,13 +569,38 @@
 	return rc;
 }
 
-int32_t msm_actuator_create_subdevice(struct msm_actuator_ctrl_t *a_ctrl,
-	struct i2c_board_info const *board_info,
-	struct v4l2_subdev *sdev)
+int32_t msm_actuator_power_up(void *act_info)
 {
-	int32_t rc = 0;
+	int rc = 0;
+	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
+	struct msm_actuator_info *ptr;
+	CDBG("%s called\n", __func__);
 
-	LINFO("%s called\n", __func__);
+	ptr = act_info;
+	a_ctrl->vcm_pwd = ptr->vcm_pwd;
+	a_ctrl->vcm_enable = ptr->vcm_enable;
+	CDBG("vcm info: %x %x\n", a_ctrl->vcm_pwd,
+		a_ctrl->vcm_enable);
+	if (a_ctrl->vcm_enable) {
+		rc = gpio_request(a_ctrl->vcm_pwd, "msm_actuator");
+		if (!rc) {
+			CDBG("Enable VCM PWD\n");
+			gpio_direction_output(a_ctrl->vcm_pwd, 1);
+		}
+	}
+	return rc;
+}
+
+
+int32_t msm_actuator_create_subdevice(void *info, void *dev)
+{
+	struct msm_actuator_info *act_info = (struct msm_actuator_info *)info;
+	struct i2c_board_info const *board_info = act_info->board_info;
+	struct v4l2_subdev *sdev = (struct v4l2_subdev *)dev;
+	struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
+	int32_t rc = -EFAULT;
+
+	CDBG("%s called\n", __func__);
 
 	/* Store the sub device in actuator structure */
 	a_ctrl->sdev = sdev;
@@ -331,3 +615,52 @@
 
 	return rc;
 }
+
+DEFINE_MUTEX(msm_actuator_mutex);
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+	{"msm_actuator", (kernel_ulong_t)&msm_actuator_t},
+	{ }
+};
+
+static struct i2c_driver msm_actuator_i2c_driver = {
+	.id_table = msm_actuator_i2c_id,
+	.probe  = msm_actuator_i2c_probe,
+	.remove = __exit_p(msm_actuator_i2c_remove),
+	.driver = {
+		.name = "msm_actuator",
+	},
+};
+
+static int __init msm_actuator_i2c_add_driver(
+	void)
+{
+	CDBG("%s called\n", __func__);
+	return i2c_add_driver(msm_actuator_t.i2c_driver);
+}
+
+static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops;
+
+static struct v4l2_subdev_ops msm_actuator_subdev_ops = {
+	.core = &msm_actuator_subdev_core_ops,
+};
+
+static struct msm_actuator_ctrl_t msm_actuator_t = {
+	.i2c_driver = &msm_actuator_i2c_driver,
+	.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+	.actuator_ext_ctrl = {
+		.a_power_up = msm_actuator_power_up,
+		.a_create_subdevice = msm_actuator_create_subdevice,
+		.a_config = msm_actuator_config,
+		.a_power_down = msm_actuator_af_power_down,
+	},
+
+	.curr_step_pos = 0,
+	.curr_region_index = 0,
+	.actuator_mutex = &msm_actuator_mutex,
+
+};
+
+subsys_initcall(msm_actuator_i2c_add_driver);
+MODULE_DESCRIPTION("MSM ACTUATOR");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 9c90282..803a641b 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -39,39 +39,22 @@
 
 struct msm_actuator_ctrl_t;
 
-struct region_params_t {
-	/* [0] = ForwardDirection Macro boundary
-	   [1] = ReverseDirection Inf boundary
-	 */
-	uint16_t step_bound[2];
-	uint16_t code_per_step;
-};
-
-struct damping_params_t {
-	uint16_t damping_step;
-	uint16_t damping_delay;
-	void *hw_params;
-};
-
-struct damping_t {
-	struct damping_params_t *ringing_params;
-};
-
 struct msm_actuator_func_tbl {
 	int32_t (*actuator_i2c_write_b_af)(struct msm_actuator_ctrl_t *,
 			uint8_t,
 			uint8_t);
-	int32_t (*actuator_init_table)(struct msm_actuator_ctrl_t *);
-	int32_t (*actuator_init_focus)(struct msm_actuator_ctrl_t *);
-	int32_t (*actuator_set_default_focus) (struct msm_actuator_ctrl_t *);
-	int32_t (*actuator_set_params)(struct msm_actuator_ctrl_t *);
+	int32_t (*actuator_init_step_table)(struct msm_actuator_ctrl_t *,
+		struct msm_actuator_set_info_t *);
+	int32_t (*actuator_init_focus)(struct msm_actuator_ctrl_t *,
+		uint16_t, enum msm_actuator_data_type, struct reg_settings_t *);
+	int32_t (*actuator_set_default_focus) (struct msm_actuator_ctrl_t *,
+			struct msm_actuator_move_params_t *);
 	int32_t (*actuator_move_focus) (struct msm_actuator_ctrl_t *,
-			int,
-			int32_t);
+			struct msm_actuator_move_params_t *);
 	int (*actuator_power_down) (struct msm_actuator_ctrl_t *);
 	int32_t (*actuator_config)(void __user *);
 	int32_t (*actuator_i2c_write)(struct msm_actuator_ctrl_t *,
-			int16_t, void *);
+			int16_t, uint32_t);
 	int32_t (*actuator_write_focus)(struct msm_actuator_ctrl_t *,
 			uint16_t,
 			struct damping_params_t *,
@@ -79,52 +62,66 @@
 			int16_t);
 };
 
+struct msm_actuator {
+	enum actuator_type act_type;
+	struct msm_actuator_func_tbl func_tbl;
+};
+
 struct msm_actuator_ctrl_t {
-	uint32_t i2c_addr;
 	struct i2c_driver *i2c_driver;
 	struct msm_camera_i2c_client i2c_client;
 	struct mutex *actuator_mutex;
 	struct msm_actuator_ctrl actuator_ext_ctrl;
-	struct msm_actuator_func_tbl func_tbl;
+	struct msm_actuator_func_tbl *func_tbl;
+	enum msm_actuator_data_type i2c_data_type;
 	struct v4l2_subdev *sdev;
 	struct v4l2_subdev_ops *act_v4l2_subdev_ops;
-	struct msm_actuator_set_info_t set_info;
-	struct msm_actuator_get_info_t get_info;
 
-	int16_t initial_code;
 	int16_t curr_step_pos;
 	uint16_t curr_region_index;
 	uint16_t *step_position_table;
-	uint16_t *ringing_scenario[2];
-	uint16_t scenario_size[2];
-	struct region_params_t *region_params;
+	struct region_params_t region_params[MAX_ACTUATOR_REGION];
+	uint16_t reg_tbl_size;
+	struct msm_actuator_reg_params_t reg_tbl[MAX_ACTUATOR_REG_TBL_SIZE];
 	uint16_t region_size;
-	struct damping_t *damping[2];
 	void *user_data;
 	uint32_t vcm_pwd;
 	uint32_t vcm_enable;
+	uint32_t total_steps;
+	uint16_t pwd_step;
+	uint16_t initial_code;
 };
 
+int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
+		int16_t next_lens_position, uint32_t hw_params);
+int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
+		uint16_t size, enum msm_actuator_data_type type,
+		struct reg_settings_t *settings);
 int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
 		uint8_t msb,
 		uint8_t lsb);
-int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
-		void __user *cfg_data);
+int32_t msm_actuator_config(void __user *cfg_data);
 int32_t msm_actuator_move_focus(struct msm_actuator_ctrl_t *a_ctrl,
-		int direction,
-		int32_t num_steps);
-int32_t msm_actuator_init_table(struct msm_actuator_ctrl_t *a_ctrl);
-int32_t msm_actuator_set_default_focus(struct msm_actuator_ctrl_t *a_ctrl);
-int32_t msm_actuator_af_power_down(struct msm_actuator_ctrl_t *a_ctrl);
+		struct msm_actuator_move_params_t *move_params);
+int32_t msm_actuator_piezo_move_focus(
+		struct msm_actuator_ctrl_t *a_ctrl,
+		struct msm_actuator_move_params_t *move_params);
+int32_t msm_actuator_init_step_table(struct msm_actuator_ctrl_t *a_ctrl,
+		struct msm_actuator_set_info_t *set_info);
+int32_t msm_actuator_set_default_focus(struct msm_actuator_ctrl_t *a_ctrl,
+		struct msm_actuator_move_params_t *move_params);
+int32_t msm_actuator_piezo_set_default_focus(
+		struct msm_actuator_ctrl_t *a_ctrl,
+		struct msm_actuator_move_params_t *move_params);
+int32_t msm_actuator_af_power_down(void *cfg_data);
 int32_t msm_actuator_i2c_probe(struct i2c_client *client,
 		const struct i2c_device_id *id);
 int32_t msm_actuator_write_focus(struct msm_actuator_ctrl_t *a_ctrl,
-		uint16_t curr_lens_pos,
-		struct damping_params_t *damping_params,
-		int8_t sign_direction,
-		int16_t code_boundary);
-int32_t msm_actuator_create_subdevice(struct msm_actuator_ctrl_t *a_ctrl,
-		struct i2c_board_info const *board_info,
-		struct v4l2_subdev *sdev);
+		uint16_t curr_lens_pos, struct damping_params_t *damping_params,
+		int8_t sign_direction, int16_t code_boundary);
+int32_t msm_actuator_write_focus2(struct msm_actuator_ctrl_t *a_ctrl,
+		uint16_t curr_lens_pos, struct damping_params_t *damping_params,
+		int8_t sign_direction, int16_t code_boundary);
+int32_t msm_actuator_create_subdevice(void *info, void *dev);
 
 #endif
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 44e260c..da38acc 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -2558,7 +2558,6 @@
 	i2c_put_adapter(adapter);
 	adapter = NULL;
 probe_fail:
-	actctrl->a_init_table = NULL;
 	actctrl->a_power_up = NULL;
 	actctrl->a_power_down = NULL;
 	actctrl->a_config = NULL;
diff --git a/drivers/media/video/msm/msm_io_7x27a_v4l2.c b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
index 63547c8..8b977ba 100644
--- a/drivers/media/video/msm/msm_io_7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_io_7x27a_v4l2.c
@@ -29,6 +29,7 @@
 static struct clk *camio_cam_clk;
 static struct resource *clk_ctrl_mem;
 static struct msm_camera_io_clk camio_clk;
+static int apps_reset;
 void __iomem *appbase;
 
 void msm_io_w(u32 data, void __iomem *addr)
@@ -97,18 +98,27 @@
 	clk_set_rate(clk, rate);
 }
 
-void msm_camio_vfe_blk_reset(void)
+void msm_camio_vfe_blk_reset_2(int vfe_apps_reset)
 {
 	uint32_t val;
 
+	if (apps_reset && !vfe_apps_reset)
+		return;
+
 	/* do apps reset */
 	val = readl_relaxed(appbase + 0x00000210);
-	val |= 0x1;
+	if (apps_reset)
+		val |= 0x10A0001;
+	else
+		val |= 0x1;
 	writel_relaxed(val, appbase + 0x00000210);
 	usleep_range(10000, 11000);
 
 	val = readl_relaxed(appbase + 0x00000210);
-	val &= ~0x1;
+	if (apps_reset)
+		val &= ~(0x10A0001);
+	else
+		val &= ~0x1;
 	writel_relaxed(val, appbase + 0x00000210);
 	usleep_range(10000, 11000);
 
@@ -155,6 +165,7 @@
 {
 	int rc = 0;
 
+	apps_reset = *(int *)pdev->dev.platform_data;
 	clk_ctrl_mem = platform_get_resource_byname(pdev,
 					IORESOURCE_MEM, "clk_ctl");
 	if (!clk_ctrl_mem) {
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 43c25b5..d050599 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -392,6 +392,45 @@
 			break;
 	}
 
+	case MSM_CAM_IOCTL_GET_ACTUATOR_INFO: {
+		struct msm_actuator_cfg_data cdata;
+		CDBG("%s: act_config: %p\n", __func__,
+			p_mctl->sync.actctrl.a_config);
+		if (copy_from_user(&cdata,
+			(void *)argp,
+			sizeof(struct msm_actuator_cfg_data))) {
+			ERR_COPY_FROM_USER();
+			return -EFAULT;
+		}
+		cdata.is_af_supported = 0;
+		rc = 0;
+
+		if (p_mctl->sync.actctrl.a_config) {
+			struct msm_camera_sensor_info *sdata;
+
+			sdata = p_mctl->sync.sdata;
+			CDBG("%s: Act_cam_Name %d\n", __func__,
+				sdata->actuator_info->cam_name);
+
+			cdata.is_af_supported = 1;
+			cdata.cfg.cam_name =
+				(enum af_camera_name)sdata->
+				actuator_info->cam_name;
+
+			CDBG("%s: Af Support:%d\n", __func__,
+				cdata.is_af_supported);
+			CDBG("%s: Act_name:%d\n", __func__, cdata.cfg.cam_name);
+
+		}
+		if (copy_to_user((void *)argp,
+				&cdata,
+				sizeof(struct msm_actuator_cfg_data))) {
+			ERR_COPY_TO_USER();
+			rc = -EFAULT;
+		}
+		break;
+	}
+
 	case MSM_CAM_IOCTL_ACTUATOR_IO_CFG: {
 		struct msm_actuator_cfg_data act_data;
 		if (p_mctl->sync.actctrl.a_config) {
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index e2236191..acd9158 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -341,6 +341,7 @@
 
 struct mutex vfe_lock;
 static void     *vfe_syncdata;
+static int apps_reset;
 static uint8_t vfestopped;
 
 static struct stop_event stopevent;
@@ -1215,7 +1216,8 @@
 		if (queue == QDSP_CMDQUEUE) {
 			switch (vfecmd.id) {
 			case VFE_CMD_RESET:
-				msm_camio_vfe_blk_reset();
+				msm_camio_vfe_blk_reset_2(apps_reset);
+				apps_reset = 0;
 				vfestopped = 0;
 				break;
 			case VFE_CMD_START:
@@ -1717,7 +1719,7 @@
 	msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
 			vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
 	vfe_syncdata = NULL;
-
+	apps_reset = 1;
 	msm_adsp_disable(qcam_mod);
 	msm_adsp_disable(vfe_mod);
 
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 3e8d599..e0fa962 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -623,8 +623,6 @@
 		msm_sensor_disable_i2c_mux(
 			data->sensor_platform_info->i2c_conf);
 
-	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
-	msleep(20);
 	if (data->sensor_platform_info->ext_power_ctrl != NULL)
 		data->sensor_platform_info->ext_power_ctrl(0);
 	msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index acef55e..6e23930 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -344,8 +344,7 @@
 		ch_h[i] = tx[idx].ch_h;
 		sph[i] = tx[idx].sph;
 		slave_port_id = idx ;
-		if ((slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) ||
-		(slave_port_id == 0)) {
+		if (slave_port_id > SB_PGD_MAX_NUMBER_OF_TX_SLAVE_DEV_PORTS) {
 			pr_err("SLIMbus: invalid slave port id: %d",
 							slave_port_id);
 			ret = -EINVAL;
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e0da766..c050718c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -643,6 +643,16 @@
 	  to the fuse block. Currently this is supported only
 	  on FSM targets.
 
+config USB_HSIC_SMSC_HUB
+	tristate "Support for HSIC based MSM on-chip SMSC3503 HUB"
+	depends on USB_EHCI_MSM_HSIC
+	help
+	  Enables support for the HSIC (High Speed Inter-Chip) based
+	  SMSC3503 hub controller present on the Qualcomm chipsets.
+
+	  This adds support for connecting devices like mouse in HSIC
+	  Host mode.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index fb78f4e..a864918 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_APDS9802ALS)	+= apds9802als.o
 obj-$(CONFIG_ISL29003)		+= isl29003.o
 obj-$(CONFIG_ISL29020)		+= isl29020.o
+obj-$(CONFIG_USB_HSIC_SMSC_HUB) += smsc_hub.o
 obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
 obj-$(CONFIG_EP93XX_PWM)	+= ep93xx_pwm.o
 obj-$(CONFIG_DS1682)		+= ds1682.o
diff --git a/drivers/misc/smsc_hub.c b/drivers/misc/smsc_hub.c
new file mode 100644
index 0000000..9232f67
--- /dev/null
+++ b/drivers/misc/smsc_hub.c
@@ -0,0 +1,371 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/smsc3503.h>
+#include <mach/msm_xo.h>
+
+#define SMSC3503_I2C_ADDR 0x08
+#define SMSC_GSBI_I2C_BUS_ID 10
+static const unsigned short normal_i2c[] = {
+SMSC3503_I2C_ADDR, I2C_CLIENT_END };
+
+struct hsic_hub {
+	struct regulator *hsic_hub_reg;
+	struct device *dev;
+	struct i2c_client *client;
+	struct msm_xo_voter *xo_handle;
+};
+static struct hsic_hub *smsc_hub;
+
+/* APIs for setting/clearing bits and for reading/writing values */
+static inline int hsic_hub_get_u8(struct i2c_client *client, u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0)
+		pr_err("%s:i2c_read8 failed\n", __func__);
+	return ret;
+}
+
+static inline int hsic_hub_get_u16(struct i2c_client *client, u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_word_data(client, reg);
+	if (ret < 0)
+		pr_err("%s:i2c_read16 failed\n", __func__);
+	return ret;
+}
+
+static inline int hsic_hub_write_word_data(struct i2c_client *client, u8 reg,
+						u16 value)
+{
+	int ret;
+
+	ret = i2c_smbus_write_word_data(client, reg, value);
+	if (ret)
+		pr_err("%s:i2c_write16 failed\n", __func__);
+	return ret;
+}
+
+static inline int hsic_hub_write_byte_data(struct i2c_client *client, u8 reg,
+						u8 value)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, reg, value);
+	if (ret)
+		pr_err("%s:i2c_write_byte_data failed\n", __func__);
+	return ret;
+}
+
+static inline int hsic_hub_set_bits(struct i2c_client *client, u8 reg,
+					u8 value)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0) {
+		pr_err("%s:i2c_read_byte_data failed\n", __func__);
+		return ret;
+	}
+	return i2c_smbus_write_byte_data(client, reg, (ret | value));
+}
+
+static inline int hsic_hub_clear_bits(struct i2c_client *client, u8 reg,
+					u8 value)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0) {
+		pr_err("%s:i2c_read_byte_data failed\n", __func__);
+		return ret;
+	}
+	return i2c_smbus_write_byte_data(client, reg, (ret & ~value));
+}
+
+static int i2c_hsic_hub_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_WORD_DATA))
+		return -EIO;
+
+	/* CONFIG_N bit in SP_ILOCK register has to be set before changing
+	 * other registers to change default configuration of hsic hub.
+	 */
+	hsic_hub_set_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
+
+	/* Can change default configuartion like VID,PID, strings etc
+	 * by writing new values to hsic hub registers.
+	 */
+	hsic_hub_write_word_data(client, SMSC3503_VENDORID, 0x05C6);
+
+	/* CONFIG_N bit in SP_ILOCK register has to be cleared for new
+	 * values in registers to be effective after writing to
+	 * other registers.
+	 */
+	hsic_hub_clear_bits(client, SMSC3503_SP_ILOCK, CONFIG_N);
+
+	return 0;
+}
+
+static int i2c_hsic_hub_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static const struct i2c_device_id hsic_hub_id[] = {
+	{"i2c_hsic_hub", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, hsichub_id);
+
+static struct i2c_driver hsic_hub_driver = {
+	.driver = {
+		.name = "i2c_hsic_hub",
+	},
+	.probe    = i2c_hsic_hub_probe,
+	.remove   = i2c_hsic_hub_remove,
+	.id_table = hsic_hub_id,
+};
+
+#define HSIC_HUB_VDD_VOL_MIN	1650000 /* uV */
+#define HSIC_HUB_VDD_VOL_MAX	1950000 /* uV */
+#define HSIC_HUB_VDD_LOAD	36000	/* uA */
+static int __devinit smsc_hub_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	const struct smsc_hub_platform_data *pdata;
+	struct i2c_adapter *i2c_adap;
+	struct i2c_board_info i2c_info;
+
+	if (!pdev->dev.platform_data) {
+		dev_err(&pdev->dev, "No platform data\n");
+		return -ENODEV;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata->hub_reset)
+		return -EINVAL;
+
+	smsc_hub = kzalloc(sizeof(*smsc_hub), GFP_KERNEL);
+	if (!smsc_hub)
+		return -ENOMEM;
+
+	smsc_hub->hsic_hub_reg = regulator_get(&pdev->dev, "EXT_HUB_VDDIO");
+	if (IS_ERR(smsc_hub->hsic_hub_reg)) {
+		dev_err(&pdev->dev, "unable to get ext hub vddcx\n");
+		ret = PTR_ERR(smsc_hub->hsic_hub_reg);
+		goto free_mem;
+	}
+
+	ret = gpio_request(pdata->hub_reset, "HSIC_HUB_RESET_GPIO");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "gpio request failed for GPIO%d\n",
+							pdata->hub_reset);
+		goto gpio_req_fail;
+	}
+
+	ret = regulator_set_voltage(smsc_hub->hsic_hub_reg,
+			HSIC_HUB_VDD_VOL_MIN,
+			HSIC_HUB_VDD_VOL_MAX);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to set the voltage"
+				"for hsic hub reg\n");
+		goto reg_set_voltage_fail;
+	}
+
+	ret = regulator_set_optimum_mode(smsc_hub->hsic_hub_reg,
+				HSIC_HUB_VDD_LOAD);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to set optimum mode of regulator:"
+							"VDDCX\n");
+		goto reg_optimum_mode_fail;
+	}
+
+	ret = regulator_enable(smsc_hub->hsic_hub_reg);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to enable ext hub vddcx\n");
+		goto reg_enable_fail;
+	}
+
+	smsc_hub->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic_hub");
+	if (IS_ERR(smsc_hub->xo_handle)) {
+		dev_err(&pdev->dev, "not able to get the handle"
+					 "for TCXO D1 buffer\n");
+			goto disable_regulator;
+	}
+
+	ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_ON);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to vote for TCXO"
+			"D1 buffer\n");
+		goto xo_vote_fail;
+	}
+
+	gpio_direction_output(pdata->hub_reset, 0);
+	/* Hub reset should be asserted for minimum 2microsec
+	 * before deasserting.
+	 */
+	udelay(5);
+	gpio_direction_output(pdata->hub_reset, 1);
+
+	ret = i2c_add_driver(&hsic_hub_driver);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add I2C hsic_hub_driver\n");
+		goto i2c_add_fail;
+	}
+	usleep_range(10000, 12000);
+	i2c_adap = i2c_get_adapter(SMSC_GSBI_I2C_BUS_ID);
+
+	if (!i2c_adap) {
+		dev_err(&pdev->dev, "failed to get i2c adapter\n");
+		i2c_del_driver(&hsic_hub_driver);
+		goto i2c_add_fail;
+	}
+
+	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
+	strlcpy(i2c_info.type, "i2c_hsic_hub", I2C_NAME_SIZE);
+
+	smsc_hub->client = i2c_new_probed_device(i2c_adap, &i2c_info,
+						   normal_i2c, NULL);
+	i2c_put_adapter(i2c_adap);
+	if (!smsc_hub->client)
+		dev_err(&pdev->dev, "failed to connect to smsc_hub"
+			 "through I2C\n");
+
+i2c_add_fail:
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	return 0;
+
+xo_vote_fail:
+	msm_xo_put(smsc_hub->xo_handle);
+disable_regulator:
+	regulator_disable(smsc_hub->hsic_hub_reg);
+reg_enable_fail:
+	regulator_set_optimum_mode(smsc_hub->hsic_hub_reg, 0);
+reg_optimum_mode_fail:
+	regulator_set_voltage(smsc_hub->hsic_hub_reg, 0,
+				HSIC_HUB_VDD_VOL_MIN);
+reg_set_voltage_fail:
+	gpio_free(pdata->hub_reset);
+gpio_req_fail:
+	regulator_put(smsc_hub->hsic_hub_reg);
+free_mem:
+	kfree(smsc_hub);
+
+	return ret;
+}
+
+static int smsc_hub_remove(struct platform_device *pdev)
+{
+	const struct smsc_hub_platform_data *pdata;
+
+	pdata = pdev->dev.platform_data;
+	if (smsc_hub->client) {
+		i2c_unregister_device(smsc_hub->client);
+		smsc_hub->client = NULL;
+		i2c_del_driver(&hsic_hub_driver);
+	}
+	pm_runtime_disable(&pdev->dev);
+	msm_xo_put(smsc_hub->xo_handle);
+
+	regulator_disable(smsc_hub->hsic_hub_reg);
+	regulator_set_optimum_mode(smsc_hub->hsic_hub_reg, 0);
+	regulator_set_voltage(smsc_hub->hsic_hub_reg, 0,
+				HSIC_HUB_VDD_VOL_MIN);
+	gpio_free(pdata->hub_reset);
+	regulator_put(smsc_hub->hsic_hub_reg);
+	kfree(smsc_hub);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_smsc_runtime_idle(struct device *dev)
+{
+	dev_dbg(dev, "SMSC HUB runtime idle\n");
+
+	return 0;
+}
+
+static int smsc_hub_lpm_enter(struct device *dev)
+{
+	int ret;
+
+	ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_OFF);
+	if (ret) {
+		pr_err("%s: failed to devote for TCXO"
+			"D1 buffer%d\n", __func__, ret);
+	}
+	return ret;
+}
+
+static int smsc_hub_lpm_exit(struct device *dev)
+{
+	int ret;
+
+	ret = msm_xo_mode_vote(smsc_hub->xo_handle, MSM_XO_MODE_ON);
+	if (ret) {
+		pr_err("%s: failed to vote for TCXO"
+			"D1 buffer%d\n", __func__, ret);
+	}
+	return ret;
+}
+#endif
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops smsc_hub_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(smsc_hub_lpm_enter, smsc_hub_lpm_exit)
+	SET_RUNTIME_PM_OPS(smsc_hub_lpm_enter, smsc_hub_lpm_exit,
+				msm_smsc_runtime_idle)
+};
+#endif
+
+static struct platform_driver smsc_hub_driver = {
+	.driver = {
+		.name = "msm_smsc_hub",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &smsc_hub_dev_pm_ops,
+#endif
+	},
+	.remove = smsc_hub_remove,
+};
+
+static int __init smsc_hub_init(void)
+{
+	return platform_driver_probe(&smsc_hub_driver, smsc_hub_probe);
+}
+
+static void __exit smsc_hub_exit(void)
+{
+	platform_driver_unregister(&smsc_hub_driver);
+}
+subsys_initcall(smsc_hub_init);
+module_exit(smsc_hub_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SMSC HSIC HUB driver");
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 3622ff3..122c891 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2213,24 +2213,28 @@
 	return 0;
 }
 
+/*
+ * Any function calling msmsdcc_setup_clocks must
+ * acquire clk_mutex. May sleep.
+ */
 static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
 {
 	if (enable) {
 		if (!IS_ERR_OR_NULL(host->dfab_pclk))
-			clk_enable(host->dfab_pclk);
+			clk_prepare_enable(host->dfab_pclk);
 		if (!IS_ERR(host->pclk))
-			clk_enable(host->pclk);
-		clk_enable(host->clk);
+			clk_prepare_enable(host->pclk);
+		clk_prepare_enable(host->clk);
 		mb();
 		msmsdcc_delay(host);
 	} else {
 		mb();
 		msmsdcc_delay(host);
-		clk_disable(host->clk);
+		clk_disable_unprepare(host->clk);
 		if (!IS_ERR(host->pclk))
-			clk_disable(host->pclk);
+			clk_disable_unprepare(host->pclk);
 		if (!IS_ERR_OR_NULL(host->dfab_pclk))
-			clk_disable(host->dfab_pclk);
+			clk_disable_unprepare(host->dfab_pclk);
 	}
 }
 
@@ -2541,7 +2545,6 @@
 	unsigned long flags;
 	unsigned int clock;
 
-	DBG(host, "ios->clock = %u\n", ios->clock);
 
 	/*
 	 * Disable SDCC core interrupt until set_ios is completed.
@@ -2549,8 +2552,12 @@
 	 * when turning on/off the clocks. One possible
 	 * scenario is SDIO operational interrupt while the clock
 	 * is turned off.
+	 * host->lock is being released intermittently below.
+	 * Thus, prevent concurrent access to host.
 	 */
 
+	mutex_lock(&host->clk_mutex);
+	DBG(host, "ios->clock = %u\n", ios->clock);
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->sdcc_irq_disabled) {
 		spin_unlock_irqrestore(&host->lock, flags);
@@ -2565,7 +2572,9 @@
 	spin_lock_irqsave(&host->lock, flags);
 	if (ios->clock) {
 		if (!host->clks_on) {
+			spin_unlock_irqrestore(&host->lock, flags);
 			msmsdcc_setup_clocks(host, true);
+			spin_lock_irqsave(&host->lock, flags);
 			host->clks_on = 1;
 			writel_relaxed(host->mci_irqenable,
 					host->base + MMCIMASK0);
@@ -2596,7 +2605,9 @@
 		}
 
 		if (clock != host->clk_rate) {
+			spin_unlock_irqrestore(&host->lock, flags);
 			rc = clk_set_rate(host->clk, clock);
+			spin_lock_irqsave(&host->lock, flags);
 			if (rc < 0)
 				pr_err("%s: failed to set clk rate %u\n",
 						mmc_hostname(mmc), clock);
@@ -2667,7 +2678,13 @@
 
 	if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
 		msmsdcc_cfg_sdio_wakeup(host, true);
+		spin_unlock_irqrestore(&host->lock, flags);
+		/*
+		 * May get a wake-up interrupt the instant we disable the
+		 * clocks. This would disable the wake-up interrupt.
+		 */
 		msmsdcc_setup_clocks(host, false);
+		spin_lock_irqsave(&host->lock, flags);
 		host->clks_on = 0;
 	}
 
@@ -2682,6 +2699,7 @@
 	}
 
 	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->clk_mutex);
 }
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave)
@@ -2832,12 +2850,16 @@
 
 	msmsdcc_pm_qos_update_latency(host, 1);
 
+	mutex_lock(&host->clk_mutex);
 	spin_lock_irqsave(&host->lock, flags);
 	if (!host->clks_on) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		msmsdcc_setup_clocks(host, true);
+		spin_lock_irqsave(&host->lock, flags);
 		host->clks_on = 1;
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->clk_mutex);
 
 	return 0;
 }
@@ -2852,12 +2874,16 @@
 	if (mmc->card && mmc_card_sdio(mmc->card))
 		return 0;
 
+	mutex_lock(&host->clk_mutex);
 	spin_lock_irqsave(&host->lock, flags);
 	if (host->clks_on) {
+		spin_unlock_irqrestore(&host->lock, flags);
 		msmsdcc_setup_clocks(host, false);
+		spin_lock_irqsave(&host->lock, flags);
 		host->clks_on = 0;
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->clk_mutex);
 
 	return 0;
 }
@@ -3510,18 +3536,8 @@
 		host->sdio_wakeupirq_disabled = 1;
 	}
 	if (host->plat->is_sdio_al_client) {
-		if (!host->clks_on) {
-			msmsdcc_setup_clocks(host, true);
-			host->clks_on = 1;
-		}
-		if (host->sdcc_irq_disabled) {
-			writel_relaxed(host->mci_irqenable,
-				       host->base + MMCIMASK0);
-			mb();
-			enable_irq(host->core_irqres->start);
-			host->sdcc_irq_disabled = 0;
-		}
 		wake_lock(&host->sdio_wlock);
+		mmc_signal_sdio_irq(host->mmc);
 	}
 	spin_unlock(&host->lock);
 
@@ -4380,6 +4396,7 @@
 	host->dmares = dmares;
 	host->dma_crci_res = dma_crci_res;
 	spin_lock_init(&host->lock);
+	mutex_init(&host->clk_mutex);
 
 #ifdef CONFIG_MMC_EMBEDDED_SDIO
 	if (plat->embedded_sdio)
@@ -4416,7 +4433,7 @@
 			ret = clk_set_rate(host->dfab_pclk, 64000000);
 			if (ret)
 				goto dfab_pclk_put;
-			ret = clk_enable(host->dfab_pclk);
+			ret = clk_prepare_enable(host->dfab_pclk);
 			if (ret)
 				goto dfab_pclk_put;
 		} else
@@ -4428,7 +4445,7 @@
 	 */
 	host->pclk = clk_get(&pdev->dev, "iface_clk");
 	if (!IS_ERR(host->pclk)) {
-		ret = clk_enable(host->pclk);
+		ret = clk_prepare_enable(host->pclk);
 		if (ret)
 			goto pclk_put;
 
@@ -4450,7 +4467,7 @@
 		goto clk_put;
 	}
 
-	ret = clk_enable(host->clk);
+	ret = clk_prepare_enable(host->clk);
 	if (ret)
 		goto clk_put;
 
@@ -4771,12 +4788,12 @@
 	clk_put(host->clk);
  pclk_disable:
 	if (!IS_ERR(host->pclk))
-		clk_disable(host->pclk);
+		clk_disable_unprepare(host->pclk);
  pclk_put:
 	if (!IS_ERR(host->pclk))
 		clk_put(host->pclk);
 	if (!IS_ERR_OR_NULL(host->dfab_pclk))
-		clk_disable(host->dfab_pclk);
+		clk_disable_unprepare(host->dfab_pclk);
  dfab_pclk_put:
 	if (!IS_ERR_OR_NULL(host->dfab_pclk))
 		clk_put(host->dfab_pclk);
@@ -4874,6 +4891,7 @@
 	struct msmsdcc_host *host = mmc_priv(mmc);
 	unsigned long flags;
 
+	mutex_lock(&host->clk_mutex);
 	spin_lock_irqsave(&host->lock, flags);
 	pr_debug("%s: %sabling LPM\n", mmc_hostname(mmc),
 			enable ? "En" : "Dis");
@@ -4886,7 +4904,9 @@
 		}
 
 		if (host->clks_on) {
+			spin_unlock_irqrestore(&host->lock, flags);
 			msmsdcc_setup_clocks(host, false);
+			spin_lock_irqsave(&host->lock, flags);
 			host->clks_on = 0;
 		}
 
@@ -4919,7 +4939,9 @@
 		}
 
 		if (!host->clks_on) {
+			spin_unlock_irqrestore(&host->lock, flags);
 			msmsdcc_setup_clocks(host, true);
+			spin_lock_irqsave(&host->lock, flags);
 			host->clks_on = 1;
 		}
 
@@ -4932,6 +4954,7 @@
 		}
 	}
 	spin_unlock_irqrestore(&host->lock, flags);
+	mutex_unlock(&host->clk_mutex);
 	return 0;
 }
 #else
@@ -5121,7 +5144,7 @@
 	 * during suspend and not allowing TCXO.
 	 */
 
-	if (host->clks_on) {
+	if (host->clks_on && !host->plat->is_sdio_al_client) {
 		pr_warn("%s: clocks are on after suspend, aborting system "
 				"suspend\n", mmc_hostname(mmc));
 		rc = -EAGAIN;
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 832e437..406af4f 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -399,6 +399,7 @@
 	bool sdcc_irq_disabled;
 	bool sdcc_suspended;
 	bool sdio_wakeupirq_disabled;
+	struct mutex clk_mutex;
 };
 
 int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index ebd58ab..5bc8e1b 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -231,6 +231,12 @@
 
 	cpkt = urb->transfer_buffer;
 	cpkt_size = urb->actual_length;
+	if (!cpkt_size) {
+		dev->zlp_cnt++;
+		dev_dbg(dev->devicep, "%s: zero length pkt received\n",
+				__func__);
+		goto resubmit_int_urb;
+	}
 
 	list_elem = kmalloc(sizeof(struct ctrl_pkt_list_elem), GFP_ATOMIC);
 	if (!list_elem) {
@@ -827,7 +833,7 @@
 }
 
 #if defined(CONFIG_DEBUG_FS)
-#define DEBUG_BUF_SIZE	1024
+#define DEBUG_BUF_SIZE	4096
 static ssize_t rmnet_usb_ctrl_read_stats(struct file *file, char __user *ubuf,
 		size_t count, loff_t *ppos)
 {
@@ -856,6 +862,7 @@
 				"cbits_tolocal:            %d\n"
 				"cbits_tomdm:              %d\n"
 				"mdm_wait_timeout:         %u\n"
+				"zlp_cnt:                  %u\n"
 				"dev opened:               %s\n",
 				dev, dev->name,
 				dev->snd_encap_cmd_cnt,
@@ -866,6 +873,7 @@
 				dev->cbits_tolocal,
 				dev->cbits_tomdm,
 				dev->mdm_wait_timeout,
+				dev->zlp_cnt,
 				dev->is_opened ? "OPEN" : "CLOSE");
 
 	}
@@ -893,6 +901,7 @@
 		dev->get_encap_resp_cnt = 0;
 		dev->set_ctrl_line_state_cnt = 0;
 		dev->tx_ctrl_err_cnt = 0;
+		dev->zlp_cnt = 0;
 	}
 	return count;
 }
diff --git a/drivers/net/usb/rmnet_usb_ctrl.h b/drivers/net/usb/rmnet_usb_ctrl.h
index f6e5876..bc07726 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.h
+++ b/drivers/net/usb/rmnet_usb_ctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -66,6 +66,7 @@
 	unsigned int		resp_avail_cnt;
 	unsigned int		set_ctrl_line_state_cnt;
 	unsigned int		tx_ctrl_err_cnt;
+	unsigned int		zlp_cnt;
 };
 
 extern struct rmnet_ctrl_dev *ctrl_dev[];
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index d99f13a..cc95fcd 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -44,6 +44,8 @@
 	int		triggered;
 	int		smd_channel_ready;
 	unsigned int	serial_number;
+	int		thermal_mitigation;
+	void		(*tm_notify)(int);
 	struct wcnss_wlan_config wlan_config;
 	struct delayed_work wcnss_work;
 } *penv = NULL;
@@ -75,17 +77,60 @@
 static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR,
 	wcnss_serial_number_show, wcnss_serial_number_store);
 
+
+static ssize_t wcnss_thermal_mitigation_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	if (!penv)
+		return -ENODEV;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", penv->thermal_mitigation);
+}
+
+static ssize_t wcnss_thermal_mitigation_store(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	int value;
+
+	if (!penv)
+		return -ENODEV;
+
+	if (sscanf(buf, "%d", &value) != 1)
+		return -EINVAL;
+	penv->thermal_mitigation = value;
+	if (penv->tm_notify)
+		(penv->tm_notify)(value);
+	return count;
+}
+
+static DEVICE_ATTR(thermal_mitigation, S_IRUSR | S_IWUSR,
+	wcnss_thermal_mitigation_show, wcnss_thermal_mitigation_store);
+
 static int wcnss_create_sysfs(struct device *dev)
 {
+	int ret;
+
 	if (!dev)
 		return -ENODEV;
-	return device_create_file(dev, &dev_attr_serial_number);
+
+	ret = device_create_file(dev, &dev_attr_serial_number);
+	if (ret)
+		return ret;
+
+	ret = device_create_file(dev, &dev_attr_thermal_mitigation);
+	if (ret) {
+		device_remove_file(dev, &dev_attr_serial_number);
+		return ret;
+	}
+	return 0;
 }
 
 static void wcnss_remove_sysfs(struct device *dev)
 {
-	if (dev)
+	if (dev) {
 		device_remove_file(dev, &dev_attr_serial_number);
+		device_remove_file(dev, &dev_attr_thermal_mitigation);
+	}
 }
 
 static void wcnss_post_bootup(struct work_struct *work)
@@ -230,6 +275,23 @@
 }
 EXPORT_SYMBOL(wcnss_wlan_unregister_pm_ops);
 
+void wcnss_register_thermal_mitigation(void (*tm_notify)(int))
+{
+	if (penv && tm_notify)
+		penv->tm_notify = tm_notify;
+}
+EXPORT_SYMBOL(wcnss_register_thermal_mitigation);
+
+void wcnss_unregister_thermal_mitigation(void (*tm_notify)(int))
+{
+	if (penv && tm_notify) {
+		if (tm_notify != penv->tm_notify)
+			pr_err("tm_notify doesn't match registered\n");
+		penv->tm_notify = NULL;
+	}
+}
+EXPORT_SYMBOL(wcnss_unregister_thermal_mitigation);
+
 unsigned int wcnss_get_serial_number(void)
 {
 	if (penv)
@@ -273,6 +335,8 @@
 		has_48mhz_xo = pdata->has_48mhz_xo;
 	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;
 
+	penv->thermal_mitigation = 0;
+
 	penv->gpios_5wire = platform_get_resource_byname(pdev, IORESOURCE_IO,
 							"wcnss_gpios_5wire");
 
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index e21862a..ce748f5 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -94,6 +94,7 @@
 	struct pc_temp_ocv_lut	*pc_temp_ocv_lut;
 	struct sf_lut		*pc_sf_lut;
 	struct sf_lut		*rbatt_sf_lut;
+	int			delta_rbatt_mohm;
 	struct work_struct	calib_hkadc_work;
 	struct delayed_work	calib_ccadc_work;
 	unsigned int		calib_delay_ms;
@@ -125,6 +126,7 @@
 	int			default_rbatt_mohm;
 	int			amux_2_trim_delta;
 	uint16_t		prev_last_good_ocv_raw;
+	unsigned int		rconn_mohm;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -983,13 +985,25 @@
 		pr_debug("RBATT = %d\n", rbatt);
 		return rbatt;
 	}
-
+	/* Convert the batt_temp to DegC from deciDegC */
+	batt_temp = batt_temp / 10;
 	scalefactor = interpolate_scalingfactor(chip, chip->rbatt_sf_lut,
 							batt_temp, soc_rbatt);
 	pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
 				scalefactor, batt_temp, soc_rbatt);
 	rbatt = (rbatt * scalefactor) / 100;
 
+	rbatt += the_chip->rconn_mohm;
+	pr_debug("adding rconn_mohm = %d rbatt = %d\n",
+				the_chip->rconn_mohm, rbatt);
+
+	if (is_between(20, 10, soc_rbatt))
+		rbatt = rbatt
+			+ ((20 - soc_rbatt) * chip->delta_rbatt_mohm) / 10;
+	else
+		if (is_between(10, 0, soc_rbatt))
+			rbatt = rbatt + chip->delta_rbatt_mohm;
+
 	pr_debug("RBATT = %d\n", rbatt);
 	return rbatt;
 }
@@ -1596,10 +1610,12 @@
 			/* new_fcc_uah is outside the scope limit it */
 			if (new_fcc_uah > fcc_uah)
 				new_fcc_uah
-				= (fcc_uah + DELTA_FCC_PERCENT * fcc_uah);
+				= (fcc_uah +
+					(DELTA_FCC_PERCENT * fcc_uah) / 100);
 			else
 				new_fcc_uah
-				= (fcc_uah - DELTA_FCC_PERCENT * fcc_uah);
+				= (fcc_uah -
+					(DELTA_FCC_PERCENT * fcc_uah) / 100);
 
 			pr_debug("delta_fcc=%d > %d percent of fcc=%d"
 					"restring it to %d\n",
@@ -1833,7 +1849,7 @@
 	if (chip->rbatt_sf_lut) {
 		scalefactor = interpolate_scalingfactor(chip,
 						chip->rbatt_sf_lut,
-						chip->batt_temp_suspend,
+						chip->batt_temp_suspend / 10,
 						chip->soc_rbatt_suspend);
 		rbatt = rbatt * 100 / scalefactor;
 	}
@@ -1955,6 +1971,7 @@
 		chip->rbatt_sf_lut = palladium_1500_data.rbatt_sf_lut;
 		chip->default_rbatt_mohm
 				= palladium_1500_data.default_rbatt_mohm;
+		chip->delta_rbatt_mohm = palladium_1500_data.delta_rbatt_mohm;
 		return 0;
 desay:
 		chip->fcc = desay_5200_data.fcc;
@@ -1963,6 +1980,7 @@
 		chip->pc_sf_lut = desay_5200_data.pc_sf_lut;
 		chip->rbatt_sf_lut = desay_5200_data.rbatt_sf_lut;
 		chip->default_rbatt_mohm = desay_5200_data.default_rbatt_mohm;
+		chip->delta_rbatt_mohm = desay_5200_data.delta_rbatt_mohm;
 		return 0;
 }
 
@@ -2305,6 +2323,7 @@
 	chip->calib_delay_ms = pdata->calib_delay_ms;
 	chip->max_voltage_uv = pdata->max_voltage_uv;
 	chip->batt_type = pdata->battery_type;
+	chip->rconn_mohm = pdata->rconn_mohm;
 	chip->start_percent = -EINVAL;
 	chip->end_percent = -EINVAL;
 	rc = set_battery_data(chip);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 1454ca9..d24ce3f 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1223,9 +1223,19 @@
 		    / (high_voltage - low_voltage);
 }
 
+static int get_prop_batt_present(struct pm8921_chg_chip *chip)
+{
+	return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
+}
+
 static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
 {
-	int percent_soc = pm8921_bms_get_percent_charge();
+	int percent_soc;
+
+	if (!get_prop_batt_present(chip))
+		percent_soc = voltage_based_capacity(chip);
+	else
+		percent_soc = pm8921_bms_get_percent_charge();
 
 	if (percent_soc == -ENXIO)
 		percent_soc = voltage_based_capacity(chip);
@@ -1278,11 +1288,6 @@
 	return POWER_SUPPLY_HEALTH_GOOD;
 }
 
-static int get_prop_batt_present(struct pm8921_chg_chip *chip)
-{
-	return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
-}
-
 static int get_prop_charge_type(struct pm8921_chg_chip *chip)
 {
 	int temp;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 289f732..d72e349 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1383,6 +1383,7 @@
 	 * Unbind the interfaces that will need rebinding later.
 	 */
 	} else {
+		pm_runtime_get_sync(dev->parent);
 		status = usb_resume_both(udev, msg);
 		if (status == 0) {
 			pm_runtime_disable(dev);
@@ -1390,6 +1391,7 @@
 			pm_runtime_enable(dev);
 			do_unbind_rebind(udev, DO_REBIND);
 		}
+		pm_runtime_put_sync(dev->parent);
 	}
 
 	/* Avoid PM error messages for devices disconnected while suspended
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index d1299d4..4e6091e 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -20,20 +20,736 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/usb/msm_hsusb.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/list.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/msm_hsusb.h>
+
+#include "core.h"
+#include "gadget.h"
+
+/**
+ *  USB DBM Hardware registers.
+ *
+ */
+#define DBM_EP_CFG(n)		(0x00 + 4 * (n))
+#define DBM_DATA_FIFO(n)	(0x10 + 4 * (n))
+#define DBM_DATA_FIFO_SIZE(n)	(0x20 + 4 * (n))
+#define DBM_DATA_FIFO_EN	(0x30)
+#define DBM_GEVNTADR		(0x34)
+#define DBM_GEVNTSIZ		(0x38)
+#define DBM_DBG_CNFG		(0x3C)
+#define DBM_HW_TRB0_EP(n)	(0x40 + 4 * (n))
+#define DBM_HW_TRB1_EP(n)	(0x50 + 4 * (n))
+#define DBM_HW_TRB2_EP(n)	(0x60 + 4 * (n))
+#define DBM_HW_TRB3_EP(n)	(0x70 + 4 * (n))
+#define DBM_PIPE_CFG		(0x80)
+#define DBM_SOFT_RESET		(0x84)
+
+/**
+ *  USB DBM  Hardware registers bitmask.
+ *
+ */
+/* DBM_EP_CFG */
+#define DBM_EN_EP		0x00000000
+#define DBM_USB3_EP_NUM		0x0000003E
+#define DBM_BAM_PIPE_NUM	0x000000C0
+#define DBM_PRODUCER		0x00000100
+#define DBM_DISABLE_WB		0x00000200
+#define DBM_INT_RAM_ACC		0x00000400
+
+/* DBM_DATA_FIFO_SIZE */
+#define DBM_DATA_FIFO_SIZE_MASK	0x0000ffff
+
+/* DBM_GEVNTSIZ */
+#define DBM_GEVNTSIZ_MASK	0x0000ffff
+
+/* DBM_DBG_CNFG */
+#define DBM_ENABLE_IOC_MASK	0x0000000f
+
+/* DBM_SOFT_RESET */
+#define DBM_SFT_RST_EP0		0x00000001
+#define DBM_SFT_RST_EP1		0x00000002
+#define DBM_SFT_RST_EP2		0x00000004
+#define DBM_SFT_RST_EP3		0x00000008
+#define DBM_SFT_RST_EPS		0x0000000F
+#define DBM_SFT_RST		0x80000000
 
 #define DBM_MAX_EPS		4
 
+struct dwc3_msm_req_complete {
+	struct list_head list_item;
+	struct usb_request *req;
+	void (*orig_complete)(struct usb_ep *ep,
+			      struct usb_request *req);
+};
+
 struct dwc3_msm {
 	struct platform_device *dwc3;
 	struct device *dev;
 	void __iomem *base;
 	u32 resource_size;
 	int dbm_num_eps;
+	u8 ep_num_mapping[DBM_MAX_EPS];
+	const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
+	struct list_head req_complete_list;
 };
 
+static struct dwc3_msm *context;
+
+/**
+ *
+ * Read register with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @offset - register offset.
+ *
+ * @return u32
+ */
+static inline u32 dwc3_msm_read_reg(void *base, u32 offset)
+{
+	u32 val = ioread32(base + offset);
+	return val;
+}
+
+/**
+ * Read register masked field with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @offset - register offset.
+ * @mask - register bitmask.
+ *
+ * @return u32
+ */
+static inline u32 dwc3_msm_read_reg_field(void *base,
+					  u32 offset,
+					  const u32 mask)
+{
+	u32 shift = find_first_bit((void *)&mask, 32);
+	u32 val = ioread32(base + offset);
+	val &= mask;		/* clear other bits */
+	val >>= shift;
+	return val;
+}
+
+/**
+ *
+ * Write register with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @offset - register offset.
+ * @val - value to write.
+ *
+ */
+static inline void dwc3_msm_write_reg(void *base, u32 offset, u32 val)
+{
+	iowrite32(val, base + offset);
+}
+
+/**
+ * Write register masked field with debug info.
+ *
+ * @base - DWC3 base virtual address.
+ * @offset - register offset.
+ * @mask - register bitmask.
+ * @val - value to write.
+ *
+ */
+static inline void dwc3_msm_write_reg_field(void *base, u32 offset,
+					    const u32 mask, u32 val)
+{
+	u32 shift = find_first_bit((void *)&mask, 32);
+	u32 tmp = ioread32(base + offset);
+
+	tmp &= ~mask;		/* clear written bits */
+	val = tmp | (val << shift);
+	iowrite32(val, base + offset);
+}
+
+/**
+ * Return DBM EP number which is not already configured.
+ *
+ */
+static int dwc3_msm_find_avail_dbm_ep(void)
+{
+	int i;
+
+	for (i = 0; i < context->dbm_num_eps; i++)
+		if (!context->ep_num_mapping[i])
+			return i;
+
+	return -ENODEV; /* Not found */
+}
+
+/**
+ * Return DBM EP number according to usb endpoint number.
+ *
+ */
+static int dwc3_msm_find_matching_dbm_ep(u8 usb_ep)
+{
+	int i;
+
+	for (i = 0; i < context->dbm_num_eps; i++)
+		if (context->ep_num_mapping[i] == usb_ep)
+			return i;
+
+	return -ENODEV; /* Not found */
+}
+
+/**
+ * Return number of configured DBM endpoints.
+ *
+ */
+static int dwc3_msm_configured_dbm_ep_num(void)
+{
+	int i;
+	int count = 0;
+
+	for (i = 0; i < context->dbm_num_eps; i++)
+		if (context->ep_num_mapping[i])
+			count++;
+
+	return count;
+}
+
+/**
+ * Configure the DBM with the USB3 core event buffer.
+ * This function is called by the SNPS UDC upon initialization.
+ *
+ * @addr - address of the event buffer.
+ * @size - size of the event buffer.
+ *
+ */
+static int dwc3_msm_event_buffer_config(u32 addr, u16 size)
+{
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	dwc3_msm_write_reg(context->base, DBM_GEVNTADR, addr);
+	dwc3_msm_write_reg_field(context->base, DBM_GEVNTSIZ,
+		DBM_GEVNTSIZ_MASK, size);
+
+	return 0;
+}
+
+/**
+ * Reset the DBM registers upon initialization.
+ *
+ */
+static int dwc3_msm_dbm_soft_reset(void)
+{
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+		DBM_SFT_RST, 1);
+
+	return 0;
+}
+
+/**
+ * Soft reset specific DBM ep.
+ * This function is called by the function driver upon events
+ * such as transfer aborting, USB re-enumeration and USB
+ * disconnection.
+ *
+ * @dbm_ep - DBM ep number.
+ * @enter_reset - should we enter a reset state or get out of it.
+ *
+ */
+static int dwc3_msm_dbm_ep_soft_reset(u8 dbm_ep, bool enter_reset)
+{
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	if (dbm_ep >= context->dbm_num_eps) {
+		dev_err(context->dev,
+				"%s: Invalid DBM ep index\n", __func__);
+		return -ENODEV;
+	}
+
+	if (enter_reset) {
+		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+			DBM_SFT_RST_EPS, 1 << dbm_ep);
+	} else {
+		dwc3_msm_write_reg_field(context->base, DBM_SOFT_RESET,
+			DBM_SFT_RST_EPS, 0);
+	}
+
+	return 0;
+}
+
+/**
+ * Configure a USB DBM ep to work in BAM mode.
+ *
+ *
+ * @usb_ep - USB physical EP number.
+ * @producer - producer/consumer.
+ * @disable_wb - disable write back to system memory.
+ * @internal_mem - use internal USB memory for data fifo.
+ * @ioc - enable interrupt on completion.
+ *
+ * @return int - DBM ep number.
+ */
+static int dwc3_msm_dbm_ep_config(u8 usb_ep, u8 bam_pipe,
+				  bool producer, bool disable_wb,
+				  bool internal_mem, bool ioc)
+{
+	u8 dbm_ep;
+	u8 ioc_mask;
+
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	dbm_ep = dwc3_msm_find_avail_dbm_ep();
+	if (dbm_ep < 0) {
+		dev_err(context->dev, "%s: No more DBM eps\n", __func__);
+		return -ENODEV;
+	}
+
+	context->ep_num_mapping[dbm_ep] = usb_ep;
+
+	/* First, reset the dbm endpoint */
+	dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
+
+	ioc_mask = dwc3_msm_read_reg_field(context->base, DBM_DBG_CNFG,
+		DBM_ENABLE_IOC_MASK);
+	ioc_mask &= ~(ioc << dbm_ep); /* Clear ioc bit for dbm_ep */
+	/* Set ioc bit for dbm_ep if needed */
+	dwc3_msm_write_reg_field(context->base, DBM_DBG_CNFG,
+		DBM_ENABLE_IOC_MASK, ioc_mask | (ioc << dbm_ep));
+
+	dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep),
+		producer | disable_wb | internal_mem);
+	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+		DBM_USB3_EP_NUM, usb_ep);
+	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+		DBM_BAM_PIPE_NUM, bam_pipe);
+	dwc3_msm_write_reg_field(context->base, DBM_EP_CFG(dbm_ep),
+		DBM_EN_EP, 1);
+
+	return dbm_ep;
+}
+
+/**
+ * Configure a USB DBM ep to work in normal mode.
+ *
+ * @usb_ep - USB ep number.
+ *
+ */
+static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
+{
+	u8 dbm_ep;
+
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(usb_ep);
+
+	if (dbm_ep < 0) {
+		dev_err(context->dev,
+				"%s: Invalid usb ep index\n", __func__);
+		return -ENODEV;
+	}
+
+	context->ep_num_mapping[dbm_ep] = 0;
+
+	dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), 0);
+
+	/* Reset the dbm endpoint */
+	dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+
+	return 0;
+}
+
+/**
+ * Configure the DBM with the BAM's data fifo.
+ * This function is called by the USB BAM Driver
+ * upon initialization.
+ *
+ * @ep - pointer to usb endpoint.
+ * @addr - address of data fifo.
+ * @size - size of data fifo.
+ *
+ */
+int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size)
+{
+	u8 dbm_ep;
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+
+	dev_dbg(context->dev, "%s\n", __func__);
+
+	dbm_ep = dwc3_msm_find_matching_dbm_ep(dep->number);
+
+	if (dbm_ep >= context->dbm_num_eps) {
+		dev_err(context->dev,
+				"%s: Invalid DBM ep index\n", __func__);
+		return -ENODEV;
+	}
+
+	dwc3_msm_write_reg(context->base, DBM_DATA_FIFO(dbm_ep), addr);
+	dwc3_msm_write_reg_field(context->base, DBM_DATA_FIFO_SIZE(dbm_ep),
+		DBM_DATA_FIFO_SIZE_MASK, size);
+
+	return 0;
+}
+
+/**
+* Cleanups for msm endpoint on request complete.
+*
+* Also call original request complete.
+*
+* @usb_ep - pointer to usb_ep instance.
+* @request - pointer to usb_request instance.
+*
+* @return int - 0 on success, negetive on error.
+*/
+static void dwc3_msm_req_complete_func(struct usb_ep *ep,
+				       struct usb_request *request)
+{
+	struct dwc3_request *req = to_dwc3_request(request);
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3_msm_req_complete *req_complete = NULL;
+
+	/* Find original request complete function and remove it from list */
+	list_for_each_entry(req_complete,
+				&context->req_complete_list,
+				list_item) {
+		if (req_complete->req == request)
+			break;
+	}
+	if (!req_complete || req_complete->req != request) {
+		dev_err(dep->dwc->dev, "%s: could not find the request\n",
+					__func__);
+		return;
+	}
+	list_del(&req_complete->list_item);
+
+	/*
+	 * Release another one TRB to the pool since DBM queue took 2 TRBs
+	 * (normal and link), and the dwc3/gadget.c :: dwc3_gadget_giveback
+	 * released only one.
+	 */
+	if (req->queued)
+		dep->busy_slot++;
+
+	/* Unconfigure dbm ep */
+	dwc3_msm_dbm_ep_unconfig(dep->number);
+
+	/*
+	 * If this is the last endpoint we unconfigured, than reset also
+	 * the event buffers.
+	 */
+	if (0 == dwc3_msm_configured_dbm_ep_num())
+		dwc3_msm_event_buffer_config(0, 0);
+
+	/*
+	 * Call original complete function, notice that dwc->lock is already
+	 * taken by the caller of this function (dwc3_gadget_giveback()).
+	 */
+	request->complete = req_complete->orig_complete;
+	request->complete(ep, request);
+
+	kfree(req_complete);
+}
+
+/**
+* Helper function.
+* See the header of the dwc3_msm_ep_queue function.
+*
+* @dwc3_ep - pointer to dwc3_ep instance.
+* @req - pointer to dwc3_request instance.
+*
+* @return int - 0 on success, negetive on error.
+*/
+static int __dwc3_msm_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
+{
+	struct dwc3_trb_hw *trb_hw;
+	struct dwc3_trb_hw *trb_link_hw;
+	struct dwc3_trb trb;
+	struct dwc3_gadget_ep_cmd_params params;
+	u32 cmd;
+	int ret = 0;
+
+	if ((req->request.udc_priv & MSM_IS_FINITE_TRANSFER) &&
+	    (req->request.length > 0)) {
+		/* Map the request to a DMA. */
+		dwc3_map_buffer_to_dma(req);
+	}
+
+	/* We push the request to the dep->req_queued list to indicate that
+	 * this request is issued with start transfer. The request will be out
+	 * from this list in 2 cases. The first is that the transfer will be
+	 * completed (not if the transfer is endless using a circular TRBs with
+	 * with link TRB). The second case is an option to do stop stransfer,
+	 * this can be initiated by the function driver when calling dequeue.
+	 */
+	req->queued = true;
+	list_add_tail(&req->list, &dep->req_queued);
+
+	/* First, prepare a normal TRB, point to the fake buffer */
+	trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	dep->free_slot++;
+	memset(&trb, 0, sizeof(trb));
+
+	req->trb = trb_hw;
+
+	trb.bplh = req->request.dma;
+	trb.lst = 0;
+	trb.trbctl = DWC3_TRBCTL_NORMAL;
+	trb.length = req->request.length;
+	trb.hwo = true;
+
+	dwc3_trb_to_hw(&trb, trb_hw);
+	req->trb_dma = dep->trb_pool_dma;
+
+	/* Second, prepare a Link TRB that points to the first TRB*/
+	trb_link_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+	dep->free_slot++;
+	memset(&trb, 0, sizeof(trb));
+
+	trb.bplh = dep->trb_pool_dma;
+	trb.trbctl = DWC3_TRBCTL_LINK_TRB;
+	trb.hwo = true;
+
+	dwc3_trb_to_hw(&trb, trb_link_hw);
+
+	/*
+	 * Now start the transfer
+	 */
+	memset(&params, 0, sizeof(params));
+	params.param0 = upper_32_bits(req->trb_dma);
+	params.param1 = lower_32_bits(req->trb_dma);
+	cmd = DWC3_DEPCMD_STARTTRANSFER;
+	ret = dwc3_send_gadget_ep_cmd(dep->dwc, dep->number, cmd, &params);
+	if (ret < 0) {
+		dev_dbg(dep->dwc->dev,
+			"%s: failed to send STARTTRANSFER command\n",
+			__func__);
+
+		dwc3_unmap_buffer_from_dma(req);
+		list_del(&req->list);
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+* Queue a usb request to the DBM endpoint.
+* This function should be called after the endpoint
+* was enabled by the ep_enable.
+*
+* This function prepares special structure of TRBs which
+* is familier with the DBM HW, so it will possible to use
+* this endpoint in DBM mode.
+*
+* The TRBs prepared by this function, is one normal TRB
+* which point to a fake buffer, followed by a link TRB
+* that points to the first TRB.
+*
+* The API of this function follow the regular API of
+* usb_ep_queue (see usb_ep_ops in include/linuk/usb/gadget.h).
+*
+* @usb_ep - pointer to usb_ep instance.
+* @request - pointer to usb_request instance.
+* @gfp_flags - possible flags.
+*
+* @return int - 0 on success, negetive on error.
+*/
+static int dwc3_msm_ep_queue(struct usb_ep *ep,
+			     struct usb_request *request, gfp_t gfp_flags)
+{
+	struct dwc3_request *req = to_dwc3_request(request);
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm_req_complete *req_complete;
+	unsigned long flags;
+	int ret = 0;
+	u8 bam_pipe;
+	bool producer;
+	bool disable_wb;
+	bool internal_mem;
+	bool ioc;
+
+	if (!(request->udc_priv & MSM_SPS_MODE)) {
+		/* Not SPS mode, call original queue */
+		dev_vdbg(dwc->dev, "%s: not sps mode, use regular queue\n",
+					__func__);
+
+		return (context->original_ep_ops[dep->number])->queue(ep,
+								request,
+								gfp_flags);
+	}
+
+	if (!dep->endpoint.desc) {
+		dev_err(dwc->dev,
+			"%s: trying to queue request %p to disabled ep %s\n",
+			__func__, request, ep->name);
+		return -EPERM;
+	}
+
+	if (dep->number == 0 || dep->number == 1) {
+		dev_err(dwc->dev,
+			"%s: trying to queue dbm request %p to control ep %s\n",
+			__func__, request, ep->name);
+		return -EPERM;
+	}
+
+	if (dep->free_slot > 0 || dep->busy_slot > 0 ||
+		!list_empty(&dep->request_list) ||
+		!list_empty(&dep->req_queued)) {
+
+		dev_err(dwc->dev,
+			"%s: trying to queue dbm request %p tp ep %s\n",
+			__func__, request, ep->name);
+		return -EPERM;
+	}
+
+	/*
+	 * Override req->complete function, but before doing that,
+	 * store it's original pointer in the req_complete_list.
+	 */
+	req_complete = kzalloc(sizeof(*req_complete), GFP_KERNEL);
+	if (!req_complete) {
+		dev_err(dep->dwc->dev, "%s: not enough memory\n", __func__);
+		return -ENOMEM;
+	}
+	req_complete->req = request;
+	req_complete->orig_complete = request->complete;
+	list_add_tail(&req_complete->list_item, &context->req_complete_list);
+	request->complete = dwc3_msm_req_complete_func;
+
+	/*
+	 * Configure dbm event buffers if this is the first
+	 * dbm endpoint we about to configure.
+	 */
+	if (0 == dwc3_msm_configured_dbm_ep_num())
+		dwc3_msm_event_buffer_config(dwc->ev_buffs[0]->dma,
+					     dwc->ev_buffs[0]->length);
+
+	/*
+	 * Configure the DBM endpoint
+	 */
+	bam_pipe = (request->udc_priv & MSM_PIPE_ID_MASK);
+	producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
+	disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
+	internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
+	ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
+
+	ret = dwc3_msm_dbm_ep_config(dep->number,
+					bam_pipe, producer,
+					disable_wb, internal_mem, ioc);
+	if (ret < 0) {
+		dev_err(context->dev,
+			"error %d after calling dwc3_msm_dbm_ep_config\n",
+			ret);
+		return ret;
+	}
+
+	dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
+			__func__, request, ep->name, request->length);
+
+	/*
+	 * We must obtain the lock of the dwc3 core driver,
+	 * including disabling interrupts, so we will be sure
+	 * that we are the only ones that configure the HW device
+	 * core and ensure that we queuing the request will finish
+	 * as soon as possible so we will release back the lock.
+	 */
+	spin_lock_irqsave(&dwc->lock, flags);
+	ret = __dwc3_msm_ep_queue(dep, req);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+	if (ret < 0) {
+		dev_err(context->dev,
+			"error %d after calling __dwc3_msm_ep_queue\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * Configure MSM endpoint.
+ * This function do specific configurations
+ * to an endpoint which need specific implementaion
+ * in the MSM architecture.
+ *
+ * This function should be called by usb function/class
+ * layer which need a support from the specific MSM HW
+ * which wrap the USB3 core. (like DBM specific endpoints)
+ *
+ * @ep - a pointer to some usb_ep instance
+ *
+ * @return int - 0 on success, negetive on error.
+ */
+int msm_ep_config(struct usb_ep *ep)
+{
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct usb_ep_ops *new_ep_ops;
+
+	/* Save original ep ops for future restore*/
+	if (context->original_ep_ops[dep->number]) {
+		dev_err(context->dev,
+			"ep [%s,%d] already configured as msm endpoint\n",
+			ep->name, dep->number);
+		return -EPERM;
+	}
+	context->original_ep_ops[dep->number] = ep->ops;
+
+	/* Set new usb ops as we like */
+	new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_KERNEL);
+	if (!new_ep_ops) {
+		dev_err(context->dev,
+			"%s: unable to allocate mem for new usb ep ops\n",
+			__func__);
+		return -ENOMEM;
+	}
+	(*new_ep_ops) = (*ep->ops);
+	new_ep_ops->queue = dwc3_msm_ep_queue;
+	ep->ops = new_ep_ops;
+
+	/*
+	 * Do HERE more usb endpoint configurations
+	 * which are specific to MSM.
+	 */
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_ep_config);
+
+/**
+ * Un-configure MSM endpoint.
+ * Tear down configurations done in the
+ * dwc3_msm_ep_config function.
+ *
+ * @ep - a pointer to some usb_ep instance
+ *
+ * @return int - 0 on success, negetive on error.
+ */
+int msm_ep_unconfig(struct usb_ep *ep)
+{
+	struct dwc3_ep *dep = to_dwc3_ep(ep);
+	struct usb_ep_ops *old_ep_ops;
+
+	/* Restore original ep ops */
+	if (!context->original_ep_ops[dep->number]) {
+		dev_err(context->dev,
+			"ep [%s,%d] was not configured as msm endpoint\n",
+			ep->name, dep->number);
+		return -EINVAL;
+	}
+	old_ep_ops = (struct usb_ep_ops	*)ep->ops;
+	ep->ops = context->original_ep_ops[dep->number];
+	context->original_ep_ops[dep->number] = NULL;
+	kfree(old_ep_ops);
+
+	/*
+	 * Do HERE more usb endpoint un-configurations
+	 * which are specific to MSM.
+	 */
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_ep_unconfig);
+
 static int __devinit dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -49,6 +765,9 @@
 	}
 
 	platform_set_drvdata(pdev, msm);
+	context = msm;
+
+	INIT_LIST_HEAD(&msm->req_complete_list);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -107,6 +826,9 @@
 		goto err1;
 	}
 
+	/* Reset the DBM */
+	dwc3_msm_dbm_soft_reset();
+
 	return 0;
 
 err1:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fa824cf..2341441 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1327,7 +1327,7 @@
 		const struct dwc3_event_depevt *event, int status)
 {
 	struct dwc3_request	*req;
-	struct dwc3_trb         trb;
+	struct dwc3_trb         trb = {0};
 	unsigned int		count;
 	unsigned int		s_pkt = 0;
 
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 8e0bef0..54d041a 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -64,6 +64,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb.h>
 
 #include "ci13xxx_udc.h"
 
@@ -1676,7 +1677,7 @@
 	if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID) {
 		if (mReq->req.udc_priv & MSM_SPS_MODE) {
 			mReq->ptr->token = TD_STATUS_ACTIVE;
-			if (mReq->req.udc_priv & MSM_TBE)
+			if (mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER)
 				mReq->ptr->next = TD_TERMINATE;
 			else
 				mReq->ptr->next = MSM_ETD_TYPE | mReq->dma;
@@ -1794,7 +1795,7 @@
 
 	if (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID)
 		if ((mReq->req.udc_priv & MSM_SPS_MODE) &&
-			(mReq->req.udc_priv & MSM_TBE))
+			(mReq->req.udc_priv & MSM_IS_FINITE_TRANSFER))
 			return -EBUSY;
 	if (mReq->zptr) {
 		if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 684517b..0c811e1 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -30,15 +30,8 @@
  */
 #define CI13XX_REQ_VENDOR_ID(id)  (id & 0xFFFF0000UL)
 
-/* MSM specific */
-#define MSM_PIPE_ID_MASK         (0x1F)
-#define MSM_TX_PIPE_ID_OFS       (16)
-#define MSM_SPS_MODE             BIT(5)
-#define MSM_TBE                  BIT(6)
-#define MSM_ETD_TYPE             BIT(1)
-#define MSM_ETD_IOC              BIT(9)
-#define MSM_VENDOR_ID            BIT(16)
-#define MSM_EP_PIPE_ID_RESET_VAL 0x1F001F
+#define MSM_ETD_TYPE			BIT(1)
+#define MSM_EP_PIPE_ID_RESET_VAL	0x1F001F
 
 /******************************************************************************
  * STRUCTURES
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index b086428..958ed31 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -414,23 +414,6 @@
 	kfree(f->name);
 }
 
-static void frmnet_suspend(struct usb_function *f)
-{
-	struct f_rmnet *dev = func_to_rmnet(f);
-	unsigned port_num;
-
-	if (!atomic_read(&dev->online))
-		return;
-	/* This is a workaround for a bug in Windows 7/XP hosts in which
-	 * the DTR bit is not set low when going into suspend. Hence force it
-	 * low here when this function driver is suspended.
-	 */
-	if (dev->port.notify_modem) {
-		port_num = rmnet_ports[dev->port_num].ctrl_xport_num;
-		dev->port.notify_modem(&dev->port, port_num, ~ACM_CTRL_DTR);
-	}
-}
-
 static void frmnet_disable(struct usb_function *f)
 {
 	struct f_rmnet *dev = func_to_rmnet(f);
@@ -929,7 +912,6 @@
 	f->disable = frmnet_disable;
 	f->set_alt = frmnet_set_alt;
 	f->setup = frmnet_setup;
-	f->suspend = frmnet_suspend;
 	dev->port.send_cpkt_response = frmnet_send_cpkt_response;
 	dev->port.disconnect = frmnet_disconnect;
 	dev->port.connect = frmnet_connect;
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 36270d4..3113c45 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -79,10 +79,6 @@
 
 #define BAM_CH_OPENED	BIT(0)
 #define BAM_CH_READY	BIT(1)
-#define SPS_PARAMS_PIPE_ID_MASK		(0x1F)
-#define SPS_PARAMS_SPS_MODE			BIT(5)
-#define SPS_PARAMS_TBE		        BIT(6)
-#define MSM_VENDOR_ID				BIT(16)
 
 struct bam_ch_info {
 	unsigned long		flags;
@@ -741,8 +737,8 @@
 	d->rx_req->context = port;
 	d->rx_req->complete = gbam_endless_rx_complete;
 	d->rx_req->length = 0;
-	sps_params = (SPS_PARAMS_SPS_MODE | d->src_pipe_idx |
-				 MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+	sps_params = (MSM_SPS_MODE | d->src_pipe_idx |
+				 MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
 	d->rx_req->udc_priv = sps_params;
 	d->tx_req = usb_ep_alloc_request(port->port_usb->in, GFP_KERNEL);
 	if (!d->tx_req)
@@ -751,8 +747,8 @@
 	d->tx_req->context = port;
 	d->tx_req->complete = gbam_endless_tx_complete;
 	d->tx_req->length = 0;
-	sps_params = (SPS_PARAMS_SPS_MODE | d->dst_pipe_idx |
-				 MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+	sps_params = (MSM_SPS_MODE | d->dst_pipe_idx |
+				 MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
 	d->tx_req->udc_priv = sps_params;
 
 	/* queue in & out requests */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 10a255d..2181504 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -386,7 +386,9 @@
 		req = list_entry(pool->next, struct usb_request, list);
 		len = gs_send_packet(port, req->buf, TX_BUF_SIZE);
 		if (len == 0) {
-			/* Queue zero length packet */
+			/* Queue zero length packet explicitly to make it
+			 * work with UDCs which don't support req->zero flag
+			 */
 			if (prev_len && (prev_len % in->maxpacket == 0)) {
 				req->length = 0;
 				list_del(&req->list);
@@ -411,7 +413,6 @@
 
 		req->length = len;
 		list_del(&req->list);
-		req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0);
 
 		pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n",
 				port->port_num, len, *((u8 *)req->buf),
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index dbbfad4..1457ab2 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -53,7 +53,6 @@
 	struct regulator	*hsic_vddcx;
 	bool			async_int;
 	atomic_t                in_lpm;
-	struct msm_xo_voter	*xo_handle;
 	struct wake_lock	wlock;
 	int			peripheral_status_irq;
 	int			wakeup_irq;
@@ -156,79 +155,6 @@
 	return 0;
 }
 
-#define HSIC_HUB_VDD_VOL_MIN	1650000 /* uV */
-#define HSIC_HUB_VDD_VOL_MAX	1950000 /* uV */
-#define HSIC_HUB_VDD_LOAD	36000	/* uA */
-static int msm_hsic_config_hub(struct msm_hsic_hcd *mehci, int init)
-{
-	int ret = 0;
-	struct msm_hsic_host_platform_data *pdata;
-	static struct regulator *hsic_hub_reg;
-
-	pdata = mehci->dev->platform_data;
-	if (!pdata || !pdata->hub_reset)
-		return ret;
-
-	if (!init)
-		goto disable_reg;
-
-	hsic_hub_reg = devm_regulator_get(mehci->dev, "EXT_HUB_VDDIO");
-	if (IS_ERR(hsic_hub_reg)) {
-		dev_err(mehci->dev, "unable to get ext hub vddcx\n");
-		return PTR_ERR(hsic_hub_reg);
-	}
-
-	ret = gpio_request(pdata->hub_reset, "HSIC_HUB_RESET_GPIO");
-	if (ret < 0) {
-		dev_err(mehci->dev, "gpio request failed for GPIO%d\n",
-							pdata->hub_reset);
-		return ret;
-	}
-
-	ret = regulator_set_voltage(hsic_hub_reg,
-			HSIC_HUB_VDD_VOL_MIN,
-			HSIC_HUB_VDD_VOL_MAX);
-	if (ret) {
-		dev_err(mehci->dev, "unable to set the voltage"
-				"for hsic hub reg\n");
-		goto reg_set_voltage_fail;
-	}
-
-	ret = regulator_set_optimum_mode(hsic_hub_reg,
-				HSIC_HUB_VDD_LOAD);
-	if (ret < 0) {
-		pr_err("%s: Unable to set optimum mode of the regulator:"
-					"VDDCX\n", __func__);
-		goto reg_optimum_mode_fail;
-	}
-
-	ret = regulator_enable(hsic_hub_reg);
-	if (ret) {
-		dev_err(mehci->dev, "unable to enable ext hub vddcx\n");
-		goto reg_enable_fail;
-	}
-
-	gpio_direction_output(pdata->hub_reset, 0);
-	/* Hub reset should be asserted for minimum 2usec before deasserting */
-	udelay(5);
-	gpio_direction_output(pdata->hub_reset, 1);
-
-	return 0;
-
-disable_reg:
-	regulator_disable(hsic_hub_reg);
-reg_enable_fail:
-	regulator_set_optimum_mode(hsic_hub_reg, 0);
-reg_optimum_mode_fail:
-	regulator_set_voltage(hsic_hub_reg, 0,
-				HSIC_HUB_VDD_VOL_MIN);
-reg_set_voltage_fail:
-	gpio_free(pdata->hub_reset);
-
-	return ret;
-
-}
-
 static int msm_hsic_config_gpios(struct msm_hsic_hcd *mehci, int gpio_en)
 {
 	int rc = 0;
@@ -407,7 +333,6 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0, ret;
 	u32 val;
-	struct msm_hsic_host_platform_data *pdata;
 
 	if (atomic_read(&mehci->in_lpm)) {
 		dev_dbg(mehci->dev, "%s called in lpm\n", __func__);
@@ -455,13 +380,6 @@
 	clk_disable_unprepare(mehci->phy_clk);
 	clk_disable_unprepare(mehci->cal_clk);
 	clk_disable_unprepare(mehci->ahb_clk);
-	pdata = mehci->dev->platform_data;
-	if (pdata && pdata->hub_reset) {
-		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_OFF);
-		if (ret)
-			pr_err("%s failed to devote for"
-				"TCXO D1 buffer%d\n", __func__, ret);
-	}
 
 	ret = regulator_set_voltage(mehci->hsic_vddcx,
 				USB_PHY_VDD_DIG_VOL_SUSP_MIN,
@@ -491,7 +409,6 @@
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
 	int cnt = 0, ret;
 	unsigned temp;
-	struct msm_hsic_host_platform_data *pdata;
 
 	if (!atomic_read(&mehci->in_lpm)) {
 		dev_dbg(mehci->dev, "%s called in !in_lpm\n", __func__);
@@ -514,13 +431,6 @@
 	if (ret < 0)
 		dev_err(mehci->dev, "unable to set vddcx voltage: min:1v max:1.3v\n");
 
-	pdata = mehci->dev->platform_data;
-	if (pdata && pdata->hub_reset) {
-		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
-		if (ret)
-			pr_err("%s failed to vote for"
-				"TCXO D1 buffer%d\n", __func__, ret);
-	}
 	clk_prepare_enable(mehci->core_clk);
 	clk_prepare_enable(mehci->phy_clk);
 	clk_prepare_enable(mehci->cal_clk);
@@ -868,6 +778,14 @@
 
 	dev_dbg(&pdev->dev, "ehci_msm-hsic probe\n");
 
+	/* After parent device's probe is executed, it will be put in suspend
+	 * mode. When child device's probe is called, driver core is not
+	 * resuming parent device due to which parent will be in suspend even
+	 * though child is active. Hence resume the parent device explicitly.
+	 */
+	if (pdev->dev.parent)
+		pm_runtime_get_sync(pdev->dev.parent);
+
 	hcd = usb_create_hcd(&msm_hsic_driver, &pdev->dev,
 				dev_name(&pdev->dev));
 	if (!hcd) {
@@ -921,34 +839,10 @@
 		goto deinit_clocks;
 	}
 
-	pdata = mehci->dev->platform_data;
-	if (pdata && pdata->hub_reset) {
-		mehci->xo_handle = msm_xo_get(MSM_XO_TCXO_D1, "hsic");
-		if (IS_ERR(mehci->xo_handle)) {
-			pr_err(" %s not able to get the handle"
-				"to vote for TCXO D1 buffer\n", __func__);
-			ret = PTR_ERR(mehci->xo_handle);
-			goto deinit_vddcx;
-		}
-
-		ret = msm_xo_mode_vote(mehci->xo_handle, MSM_XO_MODE_ON);
-		if (ret) {
-			pr_err("%s failed to vote for TCXO"
-				"D1 buffer%d\n", __func__, ret);
-			goto free_xo_handle;
-		}
-	}
-
-	ret = msm_hsic_config_hub(mehci, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "unable to initialize hsic hub");
-		goto free_xo_handle;
-	}
-
 	ret = msm_hsic_reset(mehci);
 	if (ret) {
 		dev_err(&pdev->dev, "unable to initialize PHY\n");
-		goto deinit_hub;
+		goto deinit_vddcx;
 	}
 
 	ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
@@ -994,6 +888,7 @@
 		dev_dbg(&pdev->dev, "mode debugfs file is"
 			"not available\n");
 
+	pdata = mehci->dev->platform_data;
 	if (pdata && pdata->bus_scale_table) {
 		mehci->bus_perf_client =
 		    msm_bus_scale_register_client(pdata->bus_scale_table);
@@ -1017,16 +912,17 @@
 	 */
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
+	/* Decrement the parent device's counter after probe.
+	 * As child is active, parent will not be put into
+	 * suspend mode.
+	 */
+	if (pdev->dev.parent)
+		pm_runtime_put_sync(pdev->dev.parent);
 
 	return 0;
 
 unconfig_gpio:
 	msm_hsic_config_gpios(mehci, 0);
-deinit_hub:
-	msm_hsic_config_hub(mehci, 0);
-free_xo_handle:
-	if (pdata && pdata->hub_reset)
-		msm_xo_put(mehci->xo_handle);
 deinit_vddcx:
 	msm_hsic_init_vddcx(mehci, 0);
 deinit_clocks:
@@ -1043,7 +939,6 @@
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
-	struct msm_hsic_host_platform_data *pdata;
 
 	if (mehci->peripheral_status_irq)
 		free_irq(mehci->peripheral_status_irq, mehci);
@@ -1063,10 +958,6 @@
 
 	usb_remove_hcd(hcd);
 	msm_hsic_config_gpios(mehci, 0);
-	msm_hsic_config_hub(mehci, 0);
-	pdata = mehci->dev->platform_data;
-	if (pdata && pdata->hub_reset)
-		msm_xo_put(mehci->xo_handle);
 	msm_hsic_init_vddcx(mehci, 0);
 
 	msm_hsic_init_clocks(mehci, 0);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 7aa0430..420f417 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -839,9 +839,15 @@
 	 * line must be disabled till async interrupt enable bit is cleared
 	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to
 	 * block data communication from PHY.
+	 *
+	 * PHY retention mode is disallowed while entering to LPM with wall
+	 * charger connected.  But PHY is put into suspend mode. Hence
+	 * enable asynchronous interrupt to detect charger disconnection when
+	 * PMIC notifications are unavailable.
 	 */
 	cmd_val = readl_relaxed(USB_USBCMD);
-	if (host_bus_suspend)
+	if (host_bus_suspend || (motg->pdata->otg_control == OTG_PHY_CONTROL &&
+				dcp))
 		cmd_val |= ASYNC_INTR_CTRL | ULPI_STP_CTRL;
 	else
 		cmd_val |= ULPI_STP_CTRL;
@@ -3543,35 +3549,28 @@
 #ifdef CONFIG_PM_SLEEP
 static int msm_otg_pm_suspend(struct device *dev)
 {
-	int ret;
+	struct msm_otg *motg = dev_get_drvdata(dev);
 
 	dev_dbg(dev, "OTG PM suspend\n");
-
-#ifdef CONFIG_PM_RUNTIME
-	ret = pm_runtime_suspend(dev);
-	if (ret > 0)
-		ret = 0;
-#else
-	ret =  msm_otg_suspend(dev_get_drvdata(dev));
-#endif
-	return ret;
+	return msm_otg_suspend(motg);
 }
 
 static int msm_otg_pm_resume(struct device *dev)
 {
 	struct msm_otg *motg = dev_get_drvdata(dev);
+	int ret;
 
 	dev_dbg(dev, "OTG PM resume\n");
+	ret = msm_otg_resume(motg);
+	if (ret)
+		return ret;
 
-#ifdef CONFIG_PM_RUNTIME
-	/*
-	 * Do not resume hardware as part of system resume,
-	 * rather, wait for the ASYNC INT from the h/w
-	 */
+	/* Update runtime PM status */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
 	return 0;
-#endif
-
-	return msm_otg_resume(motg);
 }
 #endif
 
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index b3b4d53..578e339 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -885,7 +885,7 @@
 
 choice
 	prompt "Default framebuffer color depth"
-	depends on FB_MSM_MDP40 || FB_MSM_MDP31
+	depends on FB_MSM_MDP40 || FB_MSM_MDP31 || FB_MSM_MDP303
 	default FB_MSM_DEFAULT_DEPTH_RGBA8888
 
 config FB_MSM_DEFAULT_DEPTH_RGB565
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index df501dd..c0fb370 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -344,7 +344,7 @@
 {
 	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
 
-	clk_enable(tv_enc_clk);
+	clk_prepare_enable(tv_enc_clk);
 	external_common_state->dev = &pdev->dev;
 	if (mfd != NULL) {
 		DEV_INFO("adv7520_power: ON (%dx%d %d)\n",
@@ -378,7 +378,7 @@
 	adv7520_chip_off();
 	wake_unlock(&wlock);
 	adv7520_comm_power(0, 1);
-	clk_disable(tv_enc_clk);
+	clk_disable_unprepare(tv_enc_clk);
 	return 0;
 }
 
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 29d500a..5d12e97 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -423,6 +423,40 @@
 	return ret;
 }
 
+static ssize_t hdmi_common_rda_edid_3d_modes(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = 0;
+	int i;
+	char buff_3d[128];
+
+	buf[0] = 0;
+	if (external_common_state->disp_mode_list.num_of_elements) {
+		uint32 *video_mode = external_common_state->disp_mode_list
+			.disp_mode_list;
+		uint32 *video_3d_mode = external_common_state->disp_mode_list
+			.disp_3d_mode_list;
+		for (i = 0; i < external_common_state->disp_mode_list
+			.num_of_elements; ++i) {
+			video_3d_format_2string(*video_3d_mode++, buff_3d);
+			if (ret > 0)
+				ret += snprintf(buf+ret, PAGE_SIZE-ret,
+					",%d=%s",
+					*video_mode++ + 1, buff_3d);
+			else
+				ret += snprintf(buf+ret, PAGE_SIZE-ret,
+					"%d=%s",
+					*video_mode++ + 1, buff_3d);
+		}
+	} else
+		ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+			external_common_state->video_resolution+1);
+
+	DEV_DBG("%s: '%s'\n", __func__, buf);
+	ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+	return ret;
+}
+
 static ssize_t hdmi_common_rda_hdcp(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
@@ -796,6 +830,8 @@
 static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
 	hdmi_common_rda_product_description,
 	hdmi_common_wta_product_description);
+static DEVICE_ATTR(edid_3d_modes, S_IRUGO,
+	hdmi_common_rda_edid_3d_modes, NULL);
 static DEVICE_ATTR(3d_present, S_IRUGO, hdmi_common_rda_3d_present, NULL);
 static DEVICE_ATTR(hdcp_present, S_IRUGO, hdmi_common_rda_hdcp_present, NULL);
 #endif
@@ -818,6 +854,7 @@
 	&dev_attr_scan_info.attr,
 	&dev_attr_vendor_name.attr,
 	&dev_attr_product_description.attr,
+	&dev_attr_edid_3d_modes.attr,
 	&dev_attr_3d_present.attr,
 	&dev_attr_hdcp_present.attr,
 #endif
@@ -1103,6 +1140,9 @@
 	return ((uint32)vsd[3] << 16) + ((uint32)vsd[2] << 8) + (uint32)vsd[1];
 }
 
+#define HDMI_VSDB_3D_DATA_OFFSET(vsd) \
+	(!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
+
 static void hdmi_edid_extract_3d_present(const uint8 *in_buf)
 {
 	uint8 len, offset;
@@ -1115,7 +1155,7 @@
 		return;
 	}
 
-	offset = !(vsd[8] & BIT(7)) ? 9 : 13;
+	offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
 	DEV_DBG("EDID: 3D present @ %d = %02x\n", offset, vsd[offset]);
 	if (vsd[offset] >> 7) { /* 3D format indication present */
 		DEV_INFO("EDID: 3D present, 3D-len=%d\n", vsd[offset+1] & 0x1F);
@@ -1190,7 +1230,6 @@
 static void hdmi_edid_extract_extended_data_blocks(const uint8 *in_buf)
 {
 	uint8 len = 0;
-	uint8 const *prev_etag = in_buf;
 	uint32 start_offset = DBC_START_OFFSET;
 
 	/* A Tage code of 7 identifies extended data blocks */
@@ -1239,8 +1278,7 @@
 		}
 
 		/* There could be more that one extended data block */
-		start_offset = etag - prev_etag + len + 1;
-		prev_etag = etag;
+		start_offset = etag - in_buf + len + 1;
 		etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
 	}
 }
@@ -1377,6 +1415,192 @@
 	}
 }
 
+const char *single_video_3d_format_2string(uint32 format)
+{
+	switch (format) {
+	case TOP_AND_BOTTOM: return "TAB";
+	case FRAME_PACKING: return "FP";
+	case SIDE_BY_SIDE_HALF: return "SSH";
+	}
+	return "";
+}
+
+ssize_t video_3d_format_2string(uint32 format, char *buf)
+{
+	ssize_t ret, len = 0;
+	ret = snprintf(buf, PAGE_SIZE, "%s",
+		single_video_3d_format_2string(format & FRAME_PACKING));
+	len += ret;
+
+	if (len && (format & TOP_AND_BOTTOM))
+		ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+			single_video_3d_format_2string(
+				format & TOP_AND_BOTTOM));
+	else
+		ret = snprintf(buf + len, PAGE_SIZE, "%s",
+			single_video_3d_format_2string(
+				format & TOP_AND_BOTTOM));
+	len += ret;
+
+	if (len && (format & SIDE_BY_SIDE_HALF))
+		ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+			single_video_3d_format_2string(
+				format & SIDE_BY_SIDE_HALF));
+	else
+		ret = snprintf(buf + len, PAGE_SIZE, "%s",
+			single_video_3d_format_2string(
+				format & SIDE_BY_SIDE_HALF));
+	len += ret;
+
+	return len;
+}
+
+static void add_supported_3d_format(
+	struct hdmi_disp_mode_list_type *disp_mode_list,
+	uint32 video_format,
+	uint32 video_3d_format)
+{
+	char string[128];
+	boolean added = FALSE;
+	int i;
+	for (i = 0; i < disp_mode_list->num_of_elements; ++i) {
+		if (disp_mode_list->disp_mode_list[i] == video_format) {
+			disp_mode_list->disp_3d_mode_list[i] |=
+				video_3d_format;
+			added = TRUE;
+			break;
+		}
+	}
+	video_3d_format_2string(video_3d_format, string);
+	DEV_DBG("EDID[3D]: format: %d [%s], %s %s\n",
+		video_format, video_format_2string(video_format),
+		string, added ? "added" : "NOT added");
+}
+
+static void hdmi_edid_get_display_vsd_3d_mode(const uint8 *data_buf,
+	struct hdmi_disp_mode_list_type *disp_mode_list,
+	uint32 num_og_cea_blocks)
+{
+	uint8 len, offset, present_multi_3d, hdmi_vic_len, hdmi_3d_len;
+	uint16 structure_all, structure_mask;
+	const uint8 *vsd = num_og_cea_blocks ?
+		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+				3, &len) : NULL;
+	int i;
+
+	offset = HDMI_VSDB_3D_DATA_OFFSET(vsd);
+	present_multi_3d = (vsd[offset] & 0x60) >> 5;
+
+	offset += 1;
+	hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
+	hdmi_3d_len = vsd[offset] & 0x1F;
+	DEV_DBG("EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n",
+		hdmi_vic_len, hdmi_3d_len);
+
+	offset += (hdmi_vic_len + 1);
+	if (present_multi_3d == 1 || present_multi_3d == 2) {
+		DEV_DBG("EDID[3D]: multi 3D present (%d)\n", present_multi_3d);
+		/* 3d_structure_all */
+		structure_all = (vsd[offset] << 8) | vsd[offset + 1];
+		offset += 2;
+		hdmi_3d_len -= 2;
+		if (present_multi_3d == 2) {
+			/* 3d_structure_mask */
+			structure_mask = (vsd[offset] << 8) | vsd[offset + 1];
+			offset += 2;
+			hdmi_3d_len -= 2;
+		} else
+			structure_mask = 0xffff;
+
+		i = 0;
+		while (i < 16) {
+			if (i >= disp_mode_list->disp_multi_3d_mode_list_cnt)
+				break;
+
+			if (!(structure_mask & BIT(i))) {
+				++i;
+				continue;
+			}
+
+			/* BIT0: FRAME PACKING */
+			if (structure_all & BIT(0))
+				add_supported_3d_format(disp_mode_list,
+					disp_mode_list->
+						disp_multi_3d_mode_list[i],
+					FRAME_PACKING);
+
+			/* BIT6: TOP AND BOTTOM */
+			if (structure_all & BIT(6))
+				add_supported_3d_format(disp_mode_list,
+					disp_mode_list->
+						disp_multi_3d_mode_list[i],
+					TOP_AND_BOTTOM);
+
+			/* BIT8: SIDE BY SIDE HALF */
+			if (structure_all & BIT(8))
+				add_supported_3d_format(disp_mode_list,
+					disp_mode_list->
+						disp_multi_3d_mode_list[i],
+					SIDE_BY_SIDE_HALF);
+
+			++i;
+		}
+	}
+
+	i = 0;
+	while (hdmi_3d_len > 0) {
+		DEV_DBG("EDID[3D]: 3D_Structure_%d @ %d: %02x\n",
+			i + 1, offset, vsd[offset]);
+
+		if ((vsd[offset] >> 4) >=
+			disp_mode_list->disp_multi_3d_mode_list_cnt) {
+			if ((vsd[offset] & 0x0F) >= 8) {
+				offset += 1;
+				hdmi_3d_len -= 1;
+				DEV_DBG("EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+					i + 1, offset, vsd[offset]);
+			}
+			i += 1;
+			offset += 1;
+			hdmi_3d_len -= 1;
+			continue;
+		}
+
+		switch (vsd[offset] & 0x0F) {
+		case 0:
+			/* 0000b: FRAME PACKING */
+			add_supported_3d_format(disp_mode_list,
+				disp_mode_list->disp_multi_3d_mode_list
+					[vsd[offset] >> 4],
+				FRAME_PACKING);
+			break;
+		case 6:
+			/* 0110b: TOP AND BOTTOM */
+			add_supported_3d_format(disp_mode_list,
+				disp_mode_list->disp_multi_3d_mode_list
+					[vsd[offset] >> 4],
+				TOP_AND_BOTTOM);
+			break;
+		case 8:
+			/* 1000b: SIDE BY SIDE HALF */
+			add_supported_3d_format(disp_mode_list,
+				disp_mode_list->disp_multi_3d_mode_list
+					[vsd[offset] >> 4],
+				SIDE_BY_SIDE_HALF);
+			break;
+		}
+		if ((vsd[offset] & 0x0F) >= 8) {
+			offset += 1;
+			hdmi_3d_len -= 1;
+			DEV_DBG("EDID[3D]: 3D_Detail_%d @ %d: %02x\n",
+				i + 1, offset, vsd[offset]);
+		}
+		i += 1;
+		offset += 1;
+		hdmi_3d_len -= 1;
+	}
+}
+
 static void hdmi_edid_get_display_mode(const uint8 *data_buf,
 	struct hdmi_disp_mode_list_type *disp_mode_list,
 	uint32 num_og_cea_blocks)
@@ -1390,8 +1614,12 @@
 	const uint8 *svd = num_og_cea_blocks ?
 		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
 				2, &len) : NULL;
+	boolean has60hz_mode	= FALSE;
+	boolean has50hz_mode	= FALSE;
+
 
 	disp_mode_list->num_of_elements = 0;
+	disp_mode_list->disp_multi_3d_mode_list_cnt = 0;
 	if (svd != NULL) {
 		++svd;
 		for (i = 0; i < len; ++i, ++svd) {
@@ -1406,6 +1634,23 @@
 				external_common_state->preferred_video_format =
 					video_format;
 			}
+			if (i < 16) {
+				disp_mode_list->disp_multi_3d_mode_list[i]
+					= video_format;
+				disp_mode_list->disp_multi_3d_mode_list_cnt++;
+			}
+
+			if (video_format <= HDMI_VFRMT_1920x1080p60_16_9 ||
+				video_format == HDMI_VFRMT_2880x480p60_4_3 ||
+				video_format == HDMI_VFRMT_2880x480p60_16_9)
+				has60hz_mode = TRUE;
+
+			if ((video_format >= HDMI_VFRMT_720x576p50_4_3 &&
+				video_format <= HDMI_VFRMT_1920x1080p50_16_9) ||
+				video_format == HDMI_VFRMT_2880x576p50_4_3 ||
+				video_format == HDMI_VFRMT_2880x576p50_16_9 ||
+				video_format == HDMI_VFRMT_1920x1250i50_16_9)
+				has50hz_mode = TRUE;
 			if (video_format == HDMI_VFRMT_640x480p60_4_3)
 				has480p = TRUE;
 		}
@@ -1491,6 +1736,36 @@
 		}
 	}
 
+	/* mandaroty 3d format */
+	if (external_common_state->present_3d) {
+		if (has60hz_mode) {
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1920x1080p24_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1280x720p60_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1920x1080i60_16_9,
+				SIDE_BY_SIDE_HALF);
+		}
+		if (has50hz_mode) {
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1920x1080p24_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1280x720p50_16_9,
+				FRAME_PACKING | TOP_AND_BOTTOM);
+			add_supported_3d_format(disp_mode_list,
+				HDMI_VFRMT_1920x1080i50_16_9,
+				SIDE_BY_SIDE_HALF);
+		}
+
+		/* 3d format described in Vendor Specific Data */
+		hdmi_edid_get_display_vsd_3d_mode(data_buf, disp_mode_list,
+			num_og_cea_blocks);
+	}
+
 	if (!has480p)
 		/* Need to add default 640 by 480 timings, in case not described
 		 * in the EDID structure.
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index 0f44da5..57c0804 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -194,6 +194,12 @@
  * device */
 struct hdmi_disp_mode_list_type {
 	uint32	disp_mode_list[HDMI_VFRMT_MAX];
+#define TOP_AND_BOTTOM		0x10
+#define FRAME_PACKING		0x20
+#define SIDE_BY_SIDE_HALF	0x40
+	uint32	disp_3d_mode_list[HDMI_VFRMT_MAX];
+	uint32	disp_multi_3d_mode_list[16];
+	uint32	disp_multi_3d_mode_list_cnt;
 	uint32	num_of_elements;
 };
 #endif
@@ -256,6 +262,8 @@
 const struct hdmi_disp_mode_timing_type *hdmi_mhl_get_supported_mode(
 	uint32 mode);
 void hdmi_common_init_panel_info(struct msm_panel_info *pinfo);
+
+ssize_t video_3d_format_2string(uint32 format, char *buf);
 #endif
 
 int external_common_state_create(struct platform_device *pdev);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 354add7..375f82f 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -2407,7 +2407,7 @@
 			[7:0] LINK0_AKSV_1 */
 		/* LINK0_AINFO	= 0x2 FEATURE 1.1 on.
 		 *		= 0x0 FEATURE 1.1 off*/
-		HDMI_OUTP(0x0148, 0x2 << 8);
+		HDMI_OUTP(0x0148, 0x0);
 
 		/* 0x012C HDCP_ENTROPY_CTRL0
 			[31:0] BITS_OF_INFLUENCE_0 */
@@ -4074,30 +4074,30 @@
 
 	DEV_DBG("HDMI Clk: %s\n", on ? "Enable" : "Disable");
 	if (on) {
-		rc = clk_enable(hdmi_msm_state->hdmi_app_clk);
+		rc = clk_prepare_enable(hdmi_msm_state->hdmi_app_clk);
 		if (rc) {
 			DEV_ERR("'hdmi_app_clk' clock enable failed, rc=%d\n",
 				rc);
 			return rc;
 		}
 
-		rc = clk_enable(hdmi_msm_state->hdmi_m_pclk);
+		rc = clk_prepare_enable(hdmi_msm_state->hdmi_m_pclk);
 		if (rc) {
 			DEV_ERR("'hdmi_m_pclk' clock enable failed, rc=%d\n",
 				rc);
 			return rc;
 		}
 
-		rc = clk_enable(hdmi_msm_state->hdmi_s_pclk);
+		rc = clk_prepare_enable(hdmi_msm_state->hdmi_s_pclk);
 		if (rc) {
 			DEV_ERR("'hdmi_s_pclk' clock enable failed, rc=%d\n",
 				rc);
 			return rc;
 		}
 	} else {
-		clk_disable(hdmi_msm_state->hdmi_app_clk);
-		clk_disable(hdmi_msm_state->hdmi_m_pclk);
-		clk_disable(hdmi_msm_state->hdmi_s_pclk);
+		clk_disable_unprepare(hdmi_msm_state->hdmi_app_clk);
+		clk_disable_unprepare(hdmi_msm_state->hdmi_m_pclk);
+		clk_disable_unprepare(hdmi_msm_state->hdmi_s_pclk);
 	}
 
 	return 0;
@@ -4200,7 +4200,7 @@
 {
 	uint32 hpd_ctrl;
 
-	clk_enable(hdmi_msm_state->hdmi_app_clk);
+	clk_prepare_enable(hdmi_msm_state->hdmi_app_clk);
 	hdmi_msm_state->pd->core_power(1, 1);
 	hdmi_msm_state->pd->enable_5v(1);
 	hdmi_msm_set_mode(FALSE);
@@ -4226,7 +4226,7 @@
 	hdmi_msm_set_mode(FALSE);
 	hdmi_msm_state->pd->core_power(0, 1);
 	hdmi_msm_state->pd->enable_5v(0);
-	clk_disable(hdmi_msm_state->hdmi_app_clk);
+	clk_disable_unprepare(hdmi_msm_state->hdmi_app_clk);
 }
 
 static void hdmi_msm_hpd_off(void)
diff --git a/drivers/video/msm/lcdc.c b/drivers/video/msm/lcdc.c
index 9709a07..863d59d 100644
--- a/drivers/video/msm/lcdc.c
+++ b/drivers/video/msm/lcdc.c
@@ -65,8 +65,8 @@
 	mfd = platform_get_drvdata(pdev);
 	ret = panel_next_off(pdev);
 
-	clk_disable(pixel_mdp_clk);
-	clk_disable(pixel_lcdc_clk);
+	clk_disable_unprepare(pixel_mdp_clk);
+	clk_disable_unprepare(pixel_lcdc_clk);
 
 	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
 		lcdc_pdata->lcdc_power_save(0);
@@ -81,7 +81,7 @@
 				pr_err("%s: ebi1_lcdc_clk set rate failed\n",
 					__func__);
 		}
-		clk_disable(mfd->ebi1_clk);
+		clk_disable_unprepare(mfd->ebi1_clk);
 	}
 #else
 	mdp_bus_scale_update_request(0);
@@ -122,7 +122,7 @@
 		} else {
 			clk_set_rate(mfd->ebi1_clk, pm_qos_rate * 1000);
 		}
-		clk_enable(mfd->ebi1_clk);
+		clk_prepare_enable(mfd->ebi1_clk);
 	}
 
 #endif
@@ -137,8 +137,8 @@
 		goto out;
 	}
 
-	clk_enable(pixel_mdp_clk);
-	clk_enable(pixel_lcdc_clk);
+	clk_prepare_enable(pixel_mdp_clk);
+	clk_prepare_enable(pixel_lcdc_clk);
 
 	if (lcdc_pdata && lcdc_pdata->lcdc_power_save)
 		lcdc_pdata->lcdc_power_save(1);
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 1a7619d..8f1e510 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -208,7 +208,7 @@
 	ret = panel_next_off(pdev);
 
 	if (lvds_clk)
-		clk_disable(lvds_clk);
+		clk_disable_unprepare(lvds_clk);
 
 	if (lvds_pdata && lvds_pdata->lcdc_power_save)
 		lvds_pdata->lcdc_power_save(0);
@@ -249,7 +249,7 @@
 				__func__, mfd->fbi->var.pixclock);
 			goto out;
 		}
-		clk_enable(lvds_clk);
+		clk_prepare_enable(lvds_clk);
 	}
 
 	if (lvds_pdata && lvds_pdata->lcdc_power_save)
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 7f5e125..1154913 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -156,11 +156,11 @@
 	}
 
 	if (mddi_clk) {
-		clk_disable(mddi_clk);
+		clk_disable_unprepare(mddi_clk);
 		pmdh_clk_status = 0;
 	}
 	if (mddi_pclk)
-		clk_disable(mddi_pclk);
+		clk_disable_unprepare(mddi_pclk);
 	mutex_unlock(&pmdh_clk_lock);
 }
 
@@ -173,11 +173,11 @@
 	}
 
 	if (mddi_clk) {
-		clk_enable(mddi_clk);
+		clk_prepare_enable(mddi_clk);
 		pmdh_clk_status = 1;
 	}
 	if (mddi_pclk)
-		clk_enable(mddi_pclk);
+		clk_prepare_enable(mddi_pclk);
 
 	if (int_mddi_pri_flag && !irq_enabled) {
 		enable_irq(INT_MDDI_PRI);
@@ -216,7 +216,7 @@
 	mdp_bus_scale_update_request(0);
 #else
 	if (mfd->ebi1_clk)
-		clk_disable(mfd->ebi1_clk);
+		clk_disable_unprepare(mfd->ebi1_clk);
 #endif
 	pm_runtime_put(&pdev->dev);
 	return ret;
@@ -279,7 +279,7 @@
 	mdp_bus_scale_update_request(2);
 #else
 	if (mfd->ebi1_clk)
-		clk_enable(mfd->ebi1_clk);
+		clk_prepare_enable(mfd->ebi1_clk);
 #endif
 	ret = panel_next_on(pdev);
 
diff --git a/drivers/video/msm/mddi_ext.c b/drivers/video/msm/mddi_ext.c
index 09cc201..dc79fed 100644
--- a/drivers/video/msm/mddi_ext.c
+++ b/drivers/video/msm/mddi_ext.c
@@ -155,13 +155,13 @@
 			pr_err("can't find emdh_clk\n");
 			return PTR_ERR(mddi_ext_clk);
 		}
-		clk_enable(mddi_ext_clk);
+		clk_prepare_enable(mddi_ext_clk);
 
 		mddi_ext_pclk = clk_get(&pdev->dev, "iface_clk");
 		if (IS_ERR(mddi_ext_pclk))
 			mddi_ext_pclk = NULL;
 		else
-			clk_enable(mddi_ext_pclk);
+			clk_prepare_enable(mddi_ext_pclk);
 
 		size =  resource_size(&pdev->resource[0]);
 		msm_emdh_base = ioremap(pdev->resource[0].start, size);
@@ -278,9 +278,9 @@
 
 	mddi_ext_is_in_suspend = 1;
 
-	clk_disable(mddi_ext_clk);
+	clk_disable_unprepare(mddi_ext_clk);
 	if (mddi_ext_pclk)
-		clk_disable(mddi_ext_pclk);
+		clk_disable_unprepare(mddi_ext_pclk);
 
 	disable_irq(INT_MDDI_EXT);
 
@@ -299,9 +299,9 @@
 	mddi_ext_is_in_suspend = 0;
 	enable_irq(INT_MDDI_EXT);
 
-	clk_enable(mddi_ext_clk);
+	clk_prepare_enable(mddi_ext_clk);
 	if (mddi_ext_pclk)
-		clk_enable(mddi_ext_pclk);
+		clk_prepare_enable(mddi_ext_pclk);
 
 	return 0;
 }
@@ -343,12 +343,6 @@
 
 	ret = mddi_ext_register_driver();
 	if (ret) {
-		clk_disable(mddi_ext_clk);
-		clk_put(mddi_ext_clk);
-		if (mddi_ext_pclk) {
-			clk_disable(mddi_ext_pclk);
-			clk_put(mddi_ext_pclk);
-		}
 		printk(KERN_ERR "mddi_ext_register_driver() failed!\n");
 		return ret;
 	}
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index fe56263..e749a44 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -88,7 +88,6 @@
 struct workqueue_struct *mdp_vsync_wq;	/*mdp vsync wq */
 
 struct workqueue_struct *mdp_hist_wq;	/*mdp histogram wq */
-struct work_struct mdp_histogram_worker;
 
 static struct workqueue_struct *mdp_pipe_ctrl_wq; /* mdp mdp pipe ctrl wq */
 static struct delayed_work mdp_pipe_ctrl_worker;
@@ -460,7 +459,6 @@
 	return ret;
 }
 
-
 DEFINE_MUTEX(mdp_lut_push_sem);
 static int mdp_lut_i;
 static int mdp_lut_hw_update(struct fb_cmap *cmap)
@@ -554,308 +552,646 @@
 #define MDP_REV42_HIST_MAX_BIN 128
 #define MDP_REV41_HIST_MAX_BIN 32
 
-#ifdef CONFIG_FB_MSM_MDP40
-unsigned int mdp_hist_frame_cnt;
-#else
-static unsigned int mdp_hist_frame_cnt;
-#endif
-struct completion mdp_hist_comp;
-static DEFINE_MUTEX(mdp_hist_mutex);
-static boolean mdp_is_hist_data = FALSE;
-static boolean mdp_is_hist_start = FALSE;
-boolean mdp_is_hist_valid = FALSE;
-static boolean mdp_is_hist_init = FALSE;
-static uint32 mdp_hist_r[128];
-static uint32 mdp_hist_g[128];
-static uint32 mdp_hist_b[128];
+#define MDP_HIST_DATA32_R_OFF 0x0100
+#define MDP_HIST_DATA32_G_OFF 0x0200
+#define MDP_HIST_DATA32_B_OFF 0x0300
 
-void __mdp_histogram_kickoff()
+#define MDP_HIST_DATA128_R_OFF 0x0400
+#define MDP_HIST_DATA128_G_OFF 0x0800
+#define MDP_HIST_DATA128_B_OFF 0x0C00
+
+#define MDP_HIST_DATA_LUMA_OFF 0x0200
+
+#define MDP_HIST_EXTRA_DATA0_OFF 0x0028
+#define MDP_HIST_EXTRA_DATA1_OFF 0x002C
+
+struct mdp_hist_mgmt *mdp_hist_mgmt_array[MDP_HIST_MGMT_MAX];
+
+void __mdp_histogram_kickoff(struct mdp_hist_mgmt *mgmt)
 {
-	char *mdp_hist_base;
-
-	if (mdp_rev >= MDP_REV_40)
-		mdp_hist_base = MDP_BASE + 0x95000;
-	else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
-		mdp_hist_base = MDP_BASE + 0x94000;
-	else {
-		pr_err("%s(): Unsupported MDP rev. %u\n", __func__, mdp_rev);
-		return ;
-	}
-
-	if (mdp_is_hist_data == TRUE) {
-		MDP_OUTP(mdp_hist_base + 0x004,	mdp_hist_frame_cnt);
+	char *mdp_hist_base = MDP_BASE + mgmt->base;
+	if (mgmt->mdp_is_hist_data == TRUE) {
+		MDP_OUTP(mdp_hist_base + 0x0004, mgmt->frame_cnt);
 		MDP_OUTP(mdp_hist_base, 1);
 	}
 }
 
-void __mdp_histogram_reset()
+void __mdp_histogram_reset(struct mdp_hist_mgmt *mgmt)
 {
-	char *mdp_hist_base;
-
-	if (mdp_rev >= MDP_REV_40)
-		mdp_hist_base = MDP_BASE + 0x95000;
-	else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31)
-		mdp_hist_base = MDP_BASE + 0x94000;
-	else {
-		pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
-		return ;
-	}
-
-	MDP_OUTP(mdp_hist_base + 0x00C, 1);
+	char *mdp_hist_base = MDP_BASE + mgmt->base;
+	MDP_OUTP(mdp_hist_base + 0x000C, 1);
 }
 
-static void mdp_hist_read_work(struct work_struct *data)
-{
-	char *mdp_hist_base;
-	uint32 r_data_offset = 0x100, g_data_offset = 0x200;
-	uint32 b_data_offset = 0x300;
-	int num_bins, i = 0;
+static void mdp_hist_read_work(struct work_struct *data);
 
-	if (mdp_rev >= MDP_REV_42) {
-		mdp_hist_base = MDP_BASE + 0x95000;
-		r_data_offset = 0x400;
-		g_data_offset = 0x800;
-		b_data_offset = 0xc00;
-		num_bins = 128;
-	} else if (mdp_rev >= MDP_REV_40 && mdp_rev <= MDP_REV_41) {
-		mdp_hist_base = MDP_BASE + 0x95000;
-		num_bins = 32;
-	} else if (mdp_rev >= MDP_REV_30 && mdp_rev <= MDP_REV_31) {
-		mdp_hist_base = MDP_BASE + 0x94000;
-		num_bins = 32;
-	} else {
-		pr_err("%s(): Unsupported MDP rev %u\n", __func__, mdp_rev);
-		return ;
+static int mdp_hist_init_mgmt(struct mdp_hist_mgmt *mgmt, uint32_t block)
+{
+	uint32_t bins, extra, index, term = 0;
+	init_completion(&mgmt->mdp_hist_comp);
+	mutex_init(&mgmt->mdp_hist_mutex);
+	mutex_init(&mgmt->mdp_do_hist_mutex);
+	mgmt->block = block;
+	mgmt->base = mdp_block2base(block);
+	mgmt->mdp_is_hist_start = FALSE;
+	mgmt->mdp_is_hist_data = FALSE;
+	mgmt->mdp_is_hist_valid = FALSE;
+	mgmt->mdp_is_hist_init = FALSE;
+	mgmt->frame_cnt = 0;
+	mgmt->bit_mask = 0;
+	mgmt->num_bins = 0;
+	switch (block) {
+	case MDP_BLOCK_DMA_P:
+		term = MDP_HISTOGRAM_TERM_DMA_P;
+		bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
+			MDP_REV41_HIST_MAX_BIN;
+		extra = 2;
+		mgmt->base += (mdp_rev >= MDP_REV_40) ? 0x5000 : 0x4000;
+		index = MDP_HIST_MGMT_DMA_P;
+		break;
+	case MDP_BLOCK_DMA_S:
+		term = MDP_HISTOGRAM_TERM_DMA_S;
+		bins = MDP_REV42_HIST_MAX_BIN;
+		extra = 2;
+		mgmt->base += 0x5000;
+		index = MDP_HIST_MGMT_DMA_S;
+		break;
+	case MDP_BLOCK_VG_1:
+		term = MDP_HISTOGRAM_TERM_VG_1;
+		bins = MDP_REV42_HIST_MAX_BIN;
+		extra = 1;
+		mgmt->base += 0x6000;
+		index = MDP_HIST_MGMT_VG_1;
+		break;
+	case MDP_BLOCK_VG_2:
+		term = MDP_HISTOGRAM_TERM_VG_2;
+		bins = MDP_REV42_HIST_MAX_BIN;
+		extra = 1;
+		mgmt->base += 0x6000;
+		index = MDP_HIST_MGMT_VG_2;
+		break;
+	default:
+		term = MDP_HISTOGRAM_TERM_DMA_P;
+		bins = (mdp_rev >= MDP_REV_42) ? MDP_REV42_HIST_MAX_BIN :
+			MDP_REV41_HIST_MAX_BIN;
+		extra = 2;
+		mgmt->base += (mdp_rev >= MDP_REV_40) ? 0x5000 : 0x4000;
+		index = MDP_HIST_MGMT_DMA_P;
+	}
+	mgmt->irq_term = term;
+
+	mgmt->c0 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+	if (mgmt->c0 == NULL)
+		goto error;
+
+	mgmt->c1 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+	if (mgmt->c1 == NULL)
+		goto error_1;
+
+	mgmt->c2 = kmalloc(bins * sizeof(uint32_t), GFP_KERNEL);
+	if (mgmt->c2 == NULL)
+		goto error_2;
+
+	mgmt->extra_info = kmalloc(extra * sizeof(uint32_t), GFP_KERNEL);
+	if (mgmt->extra_info == NULL)
+		goto error_extra;
+
+	INIT_WORK(&mgmt->mdp_histogram_worker, mdp_hist_read_work);
+
+	mdp_hist_mgmt_array[index] = mgmt;
+	return 0;
+
+error_extra:
+	kfree(mgmt->c2);
+error_2:
+	kfree(mgmt->c1);
+error_1:
+	kfree(mgmt->c0);
+error:
+	return -ENOMEM;
+}
+
+static void mdp_hist_del_mgmt(struct mdp_hist_mgmt *mgmt)
+{
+	kfree(mgmt->extra_info);
+	kfree(mgmt->c2);
+	kfree(mgmt->c1);
+	kfree(mgmt->c0);
+}
+
+static int mdp_histogram_init(void)
+{
+	struct mdp_hist_mgmt *temp;
+	int i, ret;
+	mdp_hist_wq = alloc_workqueue("mdp_hist_wq", WQ_UNBOUND, 0);
+
+	for (i = 0; i < MDP_HIST_MGMT_MAX; i++)
+		mdp_hist_mgmt_array[i] = NULL;
+
+	if (mdp_rev >= MDP_REV_30) {
+		temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+		if (!temp)
+			goto exit;
+		ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_DMA_P);
+		if (ret) {
+			kfree(temp);
+			goto exit;
+		}
 	}
 
-	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_data == FALSE) {
-		pr_debug("%s, Histogram disabled before read.\n", __func__);
-		goto error;
+	if (mdp_rev >= MDP_REV_40) {
+		temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+		if (!temp)
+			goto exit_list;
+		ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_VG_1);
+		if (ret)
+			goto exit_list;
+
+		temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+		if (!temp)
+			goto exit_list;
+		ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_VG_2);
+		if (ret)
+			goto exit_list;
+	}
+
+	if (mdp_rev >= MDP_REV_42) {
+		temp = kmalloc(sizeof(struct mdp_hist_mgmt), GFP_KERNEL);
+		if (!temp)
+			goto exit_list;
+		ret = mdp_hist_init_mgmt(temp, MDP_BLOCK_DMA_S);
+		if (ret)
+			goto exit_list;
+	}
+
+	return 0;
+
+exit_list:
+	for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+		temp = mdp_hist_mgmt_array[i];
+		if (!temp)
+			continue;
+		mdp_hist_del_mgmt(temp);
+		kfree(temp);
+		mdp_hist_mgmt_array[i] = NULL;
+	}
+exit:
+	return -ENOMEM;
+}
+
+int mdp_histogram_block2mgmt(uint32_t block, struct mdp_hist_mgmt **mgmt)
+{
+	struct mdp_hist_mgmt *temp, *output;
+	int i, ret = 0;
+
+	output = NULL;
+
+	for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+		temp = mdp_hist_mgmt_array[i];
+		if (!temp)
+			continue;
+
+		if (temp->block == block) {
+			output = temp;
+			break;
+		}
+	}
+
+	if (output == NULL)
+		ret = -EINVAL;
+	else
+		*mgmt = output;
+
+	return ret;
+}
+
+static int mdp_histogram_enable(struct mdp_hist_mgmt *mgmt)
+{
+	uint32_t base;
+	if (mgmt->mdp_is_hist_data == TRUE) {
+		pr_err("%s histogram already started\n", __func__);
+		return -EINVAL;
 	}
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-	for (i = 0; i < num_bins; i++) {
-		mdp_hist_r[i] = inpdw(mdp_hist_base + r_data_offset + (4*i));
-		mdp_hist_g[i] = inpdw(mdp_hist_base + g_data_offset + (4*i));
-		mdp_hist_b[i] = inpdw(mdp_hist_base + b_data_offset + (4*i));
+	mdp_enable_irq(mgmt->irq_term);
+	INIT_COMPLETION(mgmt->mdp_hist_comp);
+
+	base = (uint32_t) (MDP_BASE + mgmt->base);
+	MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+	MDP_OUTP(base + 0x0010, 1);
+	MDP_OUTP(base + 0x001C, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+
+	MDP_OUTP(base + 0x0004, mgmt->frame_cnt);
+	if (mgmt->block != MDP_BLOCK_VG_1 && mgmt->block != MDP_BLOCK_VG_2)
+		MDP_OUTP(base + 0x0008, mgmt->bit_mask);
+	mgmt->mdp_is_hist_data = TRUE;
+	mgmt->mdp_is_hist_valid = TRUE;
+	mgmt->mdp_is_hist_init = FALSE;
+	__mdp_histogram_reset(mgmt);
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+	return 0;
+}
+
+static int mdp_histogram_disable(struct mdp_hist_mgmt *mgmt)
+{
+	uint32_t base, status;
+	if (mgmt->mdp_is_hist_data == FALSE) {
+		pr_err("%s histogram already stopped\n", __func__);
+		return -EINVAL;
 	}
 
-	__mdp_histogram_kickoff();
+	mgmt->mdp_is_hist_data = FALSE;
+	mgmt->mdp_is_hist_valid = FALSE;
+	mgmt->mdp_is_hist_init = FALSE;
 
+	base = (uint32_t) (MDP_BASE + mgmt->base);
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	if (mdp_rev >= MDP_REV_42)
+		MDP_OUTP(base + 0x0020, 1);
+	status = inpdw(base + 0x001C);
+	status &= ~(INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
+	MDP_OUTP(base + 0x001C, status);
+
+	MDP_OUTP(base + 0x0018, INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
-	/* if read was triggered by an underrun, don't wake up readers*/
-	if (mdp_is_hist_valid && mdp_is_hist_init) {
-		complete(&mdp_hist_comp);
-	} else {
-		if (mdp_is_hist_valid == FALSE)
-			mdp_is_hist_valid = TRUE;
-
-		if (mdp_is_hist_init == FALSE)
-			mdp_is_hist_init = TRUE;
-	}
-error:
-	mutex_unlock(&mdp_hist_mutex);
-}
-
-/*should hold mdp_hist_mutex before calling this function*/
-int _mdp_histogram_ctrl(boolean en)
-{
-	unsigned long hist_base;
-	uint32_t status;
-
-	if (mdp_rev >= MDP_REV_40)
-		hist_base = 0x95000;
-	else
-		hist_base = 0x94000;
-
-	if (en == TRUE) {
-		if (mdp_is_hist_data)
-			return -EINVAL;
-
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		mdp_hist_frame_cnt = 1;
-		mdp_enable_irq(MDP_HISTOGRAM_TERM);
-		INIT_COMPLETION(mdp_hist_comp);
-
-		/*Clear the interrupts before enabling them*/
-		MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
-						INTR_HIST_RESET_SEQ_DONE);
-		MDP_OUTP(MDP_BASE + hist_base + 0x10, 1);
-		MDP_OUTP(MDP_BASE + hist_base + 0x1c, INTR_HIST_DONE |
-						INTR_HIST_RESET_SEQ_DONE);
-
-		mdp_is_hist_data = TRUE;
-		mdp_is_hist_valid = TRUE;
-		mdp_is_hist_init = FALSE;
-
-		__mdp_histogram_reset();
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-	} else {
-		if (!mdp_is_hist_data)
-			return -EINVAL;
-
-		mdp_is_hist_data = FALSE;
-		mdp_is_hist_valid = FALSE;
-		mdp_is_hist_init = FALSE;
-
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
-		status = inpdw(MDP_BASE + hist_base + 0x1C);
-		status &= ~(INTR_HIST_DONE | INTR_HIST_RESET_SEQ_DONE);
-		MDP_OUTP(MDP_BASE + hist_base + 0x1C, status);
-		MDP_OUTP(MDP_BASE + hist_base + 0x18, INTR_HIST_DONE |
-						INTR_HIST_RESET_SEQ_DONE);
-		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-		complete(&mdp_hist_comp);
-
-		mdp_disable_irq(MDP_HISTOGRAM_TERM);
-	}
-
+	complete(&mgmt->mdp_hist_comp);
+	mdp_disable_irq(mgmt->irq_term);
 	return 0;
 }
 
-int mdp_histogram_ctrl(boolean en)
+/*call when spanning mgmt_array only*/
+int _mdp_histogram_ctrl(boolean en, struct mdp_hist_mgmt *mgmt)
 {
 	int ret = 0;
-	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_start)
-		ret = _mdp_histogram_ctrl(en);
-	mutex_unlock(&mdp_hist_mutex);
+
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (mgmt->mdp_is_hist_start == TRUE) {
+		if (en)
+			ret = mdp_histogram_enable(mgmt);
+		else
+			ret = mdp_histogram_disable(mgmt);
+	}
+	mutex_unlock(&mgmt->mdp_hist_mutex);
 
 	if (en == false)
-		flush_workqueue(mdp_hist_wq);
+		cancel_work_sync(&mgmt->mdp_histogram_worker);
 
 	return ret;
 }
 
-int mdp_start_histogram(struct fb_info *info)
+int mdp_histogram_ctrl(boolean en, uint32_t block)
 {
-	unsigned long flag;
-
+	struct mdp_hist_mgmt *mgmt = NULL;
 	int ret = 0;
-	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_start == TRUE) {
-		printk(KERN_ERR "%s histogram already started\n", __func__);
-		ret = -EPERM;
-		goto mdp_hist_start_err;
-	}
 
-	ret = _mdp_histogram_ctrl(TRUE);
+	ret = mdp_histogram_block2mgmt(block, &mgmt);
+	if (ret)
+		goto error;
 
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_is_hist_start = TRUE;
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
-mdp_hist_start_err:
-	mutex_unlock(&mdp_hist_mutex);
+	ret = _mdp_histogram_ctrl(en, mgmt);
+error:
 	return ret;
-
 }
 
-int mdp_stop_histogram(struct fb_info *info)
+int mdp_histogram_ctrl_all(boolean en)
 {
-	unsigned long flag;
-	int ret = 0;
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct mdp_hist_mgmt *temp;
+	int i, ret = 0, ret_temp = 0;
 
-	mutex_lock(&mdp_hist_mutex);
-	if (!mdp_is_hist_start) {
-		printk(KERN_ERR "%s histogram already stopped\n", __func__);
-		ret = -EPERM;
-		goto mdp_hist_stop_err;
+	for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+		temp = mdp_hist_mgmt_array[i];
+		if (!temp)
+			continue;
+
+		ret_temp = _mdp_histogram_ctrl(en, temp);
+		if (ret_temp)
+			ret = ret_temp;
+	}
+	return ret;
+}
+
+int mdp_histogram_start(struct mdp_histogram_start_req *req)
+{
+	struct mdp_hist_mgmt *mgmt = NULL;
+	int ret;
+
+	ret = mdp_histogram_block2mgmt(req->block, &mgmt);
+	if (ret) {
+		ret = -ENOTTY;
+		goto error;
 	}
 
-	spin_lock_irqsave(&mdp_spin_lock, flag);
-	mdp_is_hist_start = FALSE;
-	spin_unlock_irqrestore(&mdp_spin_lock, flag);
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (mgmt->mdp_is_hist_start == TRUE) {
+		pr_err("%s histogram already started\n", __func__);
+		ret = -EPERM;
+		goto error_lock;
+	}
+
+	mgmt->block = req->block;
+	mgmt->frame_cnt = req->frame_cnt;
+	mgmt->bit_mask = req->bit_mask;
+	mgmt->num_bins = req->num_bins;
+
+	ret = mdp_histogram_enable(mgmt);
+
+	mgmt->mdp_is_hist_start = TRUE;
+
+error_lock:
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
+	return ret;
+}
+
+int mdp_histogram_stop(struct fb_info *info, uint32_t block)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par;
+	struct mdp_hist_mgmt *mgmt = NULL;
+	int ret;
+
+	ret = mdp_histogram_block2mgmt(block, &mgmt);
+	if (ret) {
+		ret = -ENOTTY;
+		goto error;
+	}
+
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (mgmt->mdp_is_hist_start == FALSE) {
+		pr_err("%s histogram already stopped\n", __func__);
+		ret = -EPERM;
+		goto error_lock;
+	}
+
+	mgmt->mdp_is_hist_start = FALSE;
 
 	if (!mfd->panel_power_on) {
-
-		mdp_is_hist_data = FALSE;
-		complete(&mdp_hist_comp);
+		mgmt->mdp_is_hist_data = FALSE;
+		complete(&mgmt->mdp_hist_comp);
 		ret = -EINVAL;
-		goto mdp_hist_stop_err;
+		goto error_lock;
 	}
 
-	ret = _mdp_histogram_ctrl(FALSE);
+	ret = mdp_histogram_disable(mgmt);
 
-	mutex_unlock(&mdp_hist_mutex);
-	flush_workqueue(mdp_hist_wq);
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+	cancel_work_sync(&mgmt->mdp_histogram_worker);
 	return ret;
 
-mdp_hist_stop_err:
-	mutex_unlock(&mdp_hist_mutex);
+error_lock:
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
 	return ret;
 }
 
-/*call from within mdp_hist_mutex*/
-static int _mdp_copy_hist_data(struct mdp_histogram *hist)
+/*call from within mdp_hist_mutex context*/
+static int _mdp_histogram_read_dma_data(struct mdp_hist_mgmt *mgmt)
 {
-	int ret = 0;
+	char *mdp_hist_base;
+	uint32_t r_data_offset, g_data_offset, b_data_offset;
+	int i, ret = 0;
 
-	if (hist->r) {
-		ret = copy_to_user(hist->r, mdp_hist_r, hist->bin_cnt * 4);
-		if (ret)
-			goto hist_err;
+	mdp_hist_base = MDP_BASE + mgmt->base;
+
+	r_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_R_OFF :
+		MDP_HIST_DATA128_R_OFF;
+	g_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_G_OFF :
+		MDP_HIST_DATA128_G_OFF;
+	b_data_offset = (32 == mgmt->num_bins) ? MDP_HIST_DATA32_B_OFF :
+		MDP_HIST_DATA128_B_OFF;
+
+	if (mgmt->c0 == NULL || mgmt->c1 == NULL || mgmt->c2 == NULL) {
+		ret = -ENOMEM;
+		goto hist_err;
 	}
-	if (hist->g) {
-		ret = copy_to_user(hist->g, mdp_hist_g, hist->bin_cnt * 4);
-		if (ret)
-			goto hist_err;
+
+	if (!mgmt->hist) {
+		pr_err("%s: mgmt->hist not set, mgmt->hist = 0x%08x",
+		__func__, (uint32_t) mgmt->hist);
+		return -EINVAL;
 	}
-	if (hist->b) {
-		ret = copy_to_user(hist->b, mdp_hist_b, hist->bin_cnt * 4);
-		if (ret)
-			goto hist_err;
+
+	if (mgmt->hist->bin_cnt != mgmt->num_bins) {
+		pr_err("%s, bins config = %d, bin requested = %d", __func__,
+					mgmt->num_bins, mgmt->hist->bin_cnt);
+		return -EINVAL;
 	}
-	return 0;
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	for (i = 0; i < mgmt->num_bins; i++) {
+		mgmt->c0[i] = inpdw(mdp_hist_base + r_data_offset + (4*i));
+		mgmt->c1[i] = inpdw(mdp_hist_base + g_data_offset + (4*i));
+		mgmt->c2[i] = inpdw(mdp_hist_base + b_data_offset + (4*i));
+	}
+
+	if (mdp_rev >= MDP_REV_42) {
+		if (mgmt->extra_info) {
+			mgmt->extra_info[0] = inpdw(mdp_hist_base +
+					MDP_HIST_EXTRA_DATA0_OFF);
+			mgmt->extra_info[1] = inpdw(mdp_hist_base +
+					MDP_HIST_EXTRA_DATA0_OFF + 4);
+		} else
+			ret = -ENOMEM;
+	}
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	if (!ret)
+		return ret;
+
 hist_err:
 	pr_err("%s: invalid hist buffer\n", __func__);
 	return ret;
 }
 
-static int mdp_do_histogram(struct fb_info *info, struct mdp_histogram *hist)
+/*call from within mdp_hist_mutex context*/
+static int _mdp_histogram_read_vg_data(struct mdp_hist_mgmt *mgmt)
 {
+	char *mdp_hist_base;
+	int i, ret = 0;
+
+	mdp_hist_base = MDP_BASE + mgmt->base;
+
+	if (mgmt->c0 == NULL) {
+		ret = -ENOMEM;
+		goto hist_err;
+	}
+
+	if (!mgmt->hist) {
+		pr_err("%s: mgmt->hist not set", __func__);
+		return -EINVAL;
+	}
+
+	if (mgmt->hist->bin_cnt != mgmt->num_bins) {
+		pr_err("%s, bins config = %d, bin requested = %d", __func__,
+					mgmt->num_bins, mgmt->hist->bin_cnt);
+		return -EINVAL;
+	}
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	for (i = 0; i < mgmt->num_bins; i++)
+		mgmt->c0[i] = inpdw(mdp_hist_base + MDP_HIST_DATA_LUMA_OFF +
+									(4*i));
+
+	if (mdp_rev >= MDP_REV_42) {
+		if (mgmt->extra_info) {
+			mgmt->extra_info[0] = inpdw(mdp_hist_base +
+						MDP_HIST_EXTRA_DATA0_OFF);
+		} else
+			ret = -ENOMEM;
+	}
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+
+	if (!ret)
+		return ret;
+
+hist_err:
+	pr_err("%s: invalid hist buffer\n", __func__);
+	return ret;
+}
+
+static void mdp_hist_read_work(struct work_struct *data)
+{
+	struct mdp_hist_mgmt *mgmt = container_of(data, struct mdp_hist_mgmt,
+							mdp_histogram_worker);
 	int ret = 0;
-
-	if (!hist->frame_cnt || (hist->bin_cnt == 0))
-		return -EINVAL;
-
-	if ((mdp_rev <= MDP_REV_41 && hist->bin_cnt > MDP_REV41_HIST_MAX_BIN)
-		|| (mdp_rev == MDP_REV_42 &&
-		hist->bin_cnt > MDP_REV42_HIST_MAX_BIN))
-		return -EINVAL;
-
-	mutex_lock(&mdp_hist_mutex);
-	if (!mdp_is_hist_data) {
-		pr_err("%s - histogram not ready\n", __func__);
-		ret = -EPERM;
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (mgmt->mdp_is_hist_data == FALSE) {
+		pr_debug("%s, Histogram disabled before read.\n", __func__);
+		ret = -EINVAL;
 		goto error;
 	}
 
-	if (!mdp_is_hist_start) {
-		pr_err("%s histogram not started\n", __func__);
-		ret = -EPERM;
+	switch (mgmt->block) {
+	case MDP_BLOCK_DMA_P:
+	case MDP_BLOCK_DMA_S:
+		ret = _mdp_histogram_read_dma_data(mgmt);
+		break;
+	case MDP_BLOCK_VG_1:
+	case MDP_BLOCK_VG_2:
+		ret = _mdp_histogram_read_vg_data(mgmt);
+		break;
+	default:
+		pr_err("%s, invalid MDP block = %d\n", __func__, mgmt->block);
+		ret = -EINVAL;
 		goto error;
 	}
 
-	mdp_hist_frame_cnt = hist->frame_cnt;
-	mutex_unlock(&mdp_hist_mutex);
-
-	if (wait_for_completion_killable(&mdp_hist_comp)) {
-		pr_err("%s(): histogram bin collection killed", __func__);
-		return -EINVAL;
+	/* if read was triggered by an underrun, don't wake up readers*/
+	if (mgmt->mdp_is_hist_valid && mgmt->mdp_is_hist_init) {
+		mgmt->hist = NULL;
+		complete(&mgmt->mdp_hist_comp);
 	}
 
-	mutex_lock(&mdp_hist_mutex);
-	if (mdp_is_hist_data && mdp_is_hist_init)
-		ret =  _mdp_copy_hist_data(hist);
+	if (mgmt->mdp_is_hist_valid == FALSE)
+			mgmt->mdp_is_hist_valid = TRUE;
+	if (mgmt->mdp_is_hist_init == FALSE)
+			mgmt->mdp_is_hist_init = TRUE;
+
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+	if (!ret)
+		__mdp_histogram_kickoff(mgmt);
+	else
+		__mdp_histogram_reset(mgmt);
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
 error:
-	mutex_unlock(&mdp_hist_mutex);
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+}
+
+/*call from within mdp_hist_mutex*/
+static int _mdp_copy_hist_data(struct mdp_histogram_data *hist,
+						struct mdp_hist_mgmt *mgmt)
+{
+	int ret;
+
+	if (hist->c0) {
+		ret = copy_to_user(hist->c0, mgmt->c0,
+		sizeof(uint32_t) * (hist->bin_cnt));
+		if (ret)
+			goto err;
+	}
+	if (hist->c1) {
+		ret = copy_to_user(hist->c1, mgmt->c1,
+		sizeof(uint32_t) * (hist->bin_cnt));
+		if (ret)
+			goto err;
+	}
+	if (hist->c2) {
+		ret = copy_to_user(hist->c2, mgmt->c2,
+		sizeof(uint32_t) * (hist->bin_cnt));
+		if (ret)
+			goto err;
+	}
+	if (hist->extra_info) {
+		ret = copy_to_user(hist->extra_info, mgmt->extra_info,
+		sizeof(uint32_t) * ((hist->block > MDP_BLOCK_VG_2) ? 2 : 1));
+		if (ret)
+			goto err;
+	}
+err:
+	return ret;
+}
+
+static int mdp_do_histogram(struct fb_info *info,
+					struct mdp_histogram_data *hist)
+{
+	struct mdp_hist_mgmt *mgmt = NULL;
+	int ret = 0;
+
+	ret = mdp_histogram_block2mgmt(hist->block, &mgmt);
+	if (ret) {
+		pr_info("%s - %d", __func__, __LINE__);
+		ret = -EINVAL;
+		return ret;
+	}
+
+	mutex_lock(&mgmt->mdp_do_hist_mutex);
+	if (!mgmt->frame_cnt || (mgmt->num_bins == 0)) {
+		pr_info("%s - frame_cnt = %d, num_bins = %d", __func__,
+		mgmt->frame_cnt, mgmt->num_bins);
+		ret = -EINVAL;
+		goto error;
+}
+	if ((mdp_rev <= MDP_REV_41 && hist->bin_cnt > MDP_REV41_HIST_MAX_BIN)
+		|| (mdp_rev == MDP_REV_42 &&
+				hist->bin_cnt > MDP_REV42_HIST_MAX_BIN)) {
+		pr_info("%s - mdp_rev = %d, num_bins = %d", __func__, mdp_rev,
+								hist->bin_cnt);
+		ret = -EINVAL;
+		goto error;
+}
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (!mgmt->mdp_is_hist_data) {
+		pr_info("%s - hist_data = false!", __func__);
+		ret = -EINVAL;
+		goto error_lock;
+	}
+
+	if (!mgmt->mdp_is_hist_start) {
+		pr_err("%s histogram not started\n", __func__);
+		ret = -EPERM;
+		goto error_lock;
+	}
+
+	mgmt->hist = hist;
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+
+	if (wait_for_completion_killable(&mgmt->mdp_hist_comp)) {
+		pr_err("%s(): histogram bin collection killed", __func__);
+		ret = -EINVAL;
+		goto error;
+	}
+
+	mutex_lock(&mgmt->mdp_hist_mutex);
+	if (mgmt->mdp_is_hist_data && mgmt->mdp_is_hist_init)
+		ret =  _mdp_copy_hist_data(hist, mgmt);
+	else
+		ret = -ENODATA;
+error_lock:
+	mutex_unlock(&mgmt->mdp_hist_mutex);
+error:
+	mutex_unlock(&mgmt->mdp_do_hist_mutex);
 	return ret;
 }
 #endif
@@ -1157,7 +1493,7 @@
 				}
 				if (mdp_clk != NULL) {
 					mdp_clk_rate = clk_get_rate(mdp_clk);
-					clk_disable(mdp_clk);
+					clk_disable_unprepare(mdp_clk);
 					if (mdp_hw_revision <=
 						MDP4_REVISION_V2_1 &&
 						mdp_clk_rate > 122880000) {
@@ -1167,11 +1503,11 @@
 					MSM_FB_DEBUG("MDP CLK OFF\n");
 				}
 				if (mdp_pclk != NULL) {
-					clk_disable(mdp_pclk);
+					clk_disable_unprepare(mdp_pclk);
 					MSM_FB_DEBUG("MDP PCLK OFF\n");
 				}
 				if (mdp_lut_clk != NULL)
-					clk_disable(mdp_lut_clk);
+					clk_disable_unprepare(mdp_lut_clk);
 			} else {
 				/* send workqueue to turn off mdp power */
 				queue_delayed_work(mdp_pipe_ctrl_wq,
@@ -1195,30 +1531,58 @@
 					clk_set_rate(mdp_clk,
 						 mdp_clk_rate);
 				}
-				clk_enable(mdp_clk);
+				clk_prepare_enable(mdp_clk);
 				MSM_FB_DEBUG("MDP CLK ON\n");
 			}
 			if (mdp_pclk != NULL) {
-				clk_enable(mdp_pclk);
+				clk_prepare_enable(mdp_pclk);
 				MSM_FB_DEBUG("MDP PCLK ON\n");
 			}
 			if (mdp_lut_clk != NULL)
-				clk_enable(mdp_lut_clk);
+				clk_prepare_enable(mdp_lut_clk);
 			mdp_vsync_clk_enable();
 		}
 		up(&mdp_pipe_ctrl_mutex);
 	}
 }
 
+void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt)
+{
+	uint32 isr, mask;
+	char *base_addr = MDP_BASE + mgmt->base;
+	isr = inpdw(base_addr + MDP_HIST_INTR_STATUS_OFF);
+	mask = inpdw(base_addr + MDP_HIST_INTR_ENABLE_OFF);
+	outpdw(base_addr + MDP_HIST_INTR_CLEAR_OFF, isr);
+	mb();
+	isr &= mask;
+	if (isr & INTR_HIST_RESET_SEQ_DONE)
+		__mdp_histogram_kickoff(mgmt);
+
+	if (isr & INTR_HIST_DONE) {
+		if (waitqueue_active(&mgmt->mdp_hist_comp.wait)) {
+			if (!queue_work(mdp_hist_wq,
+						&mgmt->mdp_histogram_worker)) {
+				pr_err("%s %d- can't queue hist_read\n",
+							 __func__, mgmt->block);
+			}
+		} else {
+			__mdp_histogram_reset(mgmt);
+		}
+	}
+}
+
 #ifndef CONFIG_FB_MSM_MDP40
 irqreturn_t mdp_isr(int irq, void *ptr)
 {
-	uint32 hist_interrupt, mdp_interrupt = 0;
+	uint32 mdp_interrupt = 0;
 	struct mdp_dma_data *dma;
 	unsigned long flag;
-
+	struct mdp_hist_mgmt *mgmt = NULL;
+	char *base_addr;
+	int i, ret;
 	/* Ensure all the register write are complete */
 	mb();
+
 	mdp_is_in_isr = TRUE;
 
 	mdp_interrupt = inp32(MDP_INTR_STATUS);
@@ -1246,70 +1610,69 @@
 			complete(&dma->comp);
 		}
 	}
-#ifndef CONFIG_FB_MSM_MDP22
-	if (mdp_interrupt & MDP_HIST_DONE) {
-		hist_interrupt = inp32(MDP_DMA_P_HIST_INTR_STATUS);
-		outp32(MDP_BASE + 0x94018, 0x3);
-		outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
-		if (hist_interrupt & INTR_HIST_RESET_SEQ_DONE)
-			__mdp_histogram_kickoff();
 
-		if (hist_interrupt & INTR_HIST_DONE) {
-			if (waitqueue_active(&mdp_hist_comp.wait)) {
-				if (!queue_work(mdp_hist_wq,
-						&mdp_histogram_worker)) {
-					pr_err("%s: can't queue hist_read\n",
-								__func__);
-				}
-			} else
-				__mdp_histogram_reset();
+	if (mdp_rev >= MDP_REV_30) {
+		/* Only DMA_P histogram exists for this MDP rev*/
+		if (mdp_interrupt & MDP_HIST_DONE) {
+			ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_P, &mgmt);
+			if (!ret)
+				mdp_histogram_handle_isr(mgmt);
+			outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
 		}
-	}
 
-	/* LCDC UnderFlow */
-	if (mdp_interrupt & LCDC_UNDERFLOW) {
-		mdp_lcdc_underflow_cnt++;
-		/*when underflow happens HW resets all the histogram
-		  registers that were set before so restore them back
-		  to normal.*/
-		MDP_OUTP(MDP_BASE + 0x94010, 1);
-		MDP_OUTP(MDP_BASE + 0x9401c, INTR_HIST_DONE);
-		mdp_is_hist_valid = FALSE;
-		__mdp_histogram_reset();
-	}
+		/* LCDC UnderFlow */
+		if (mdp_interrupt & LCDC_UNDERFLOW) {
+			mdp_lcdc_underflow_cnt++;
+			/*when underflow happens HW resets all the histogram
+			  registers that were set before so restore them back
+			  to normal.*/
+			for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+				mgmt = mdp_hist_mgmt_array[i];
+				if (!mgmt)
+					continue;
 
-	/* LCDC Frame Start */
-	if (mdp_interrupt & LCDC_FRAME_START) {
-		dma = &dma2_data;
-		spin_lock_irqsave(&mdp_spin_lock, flag);
-		/* let's disable LCDC interrupt */
-		mdp_intr_mask &= ~LCDC_FRAME_START;
-		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-		if (dma->waiting) {
-			dma->waiting = FALSE;
+				base_addr = MDP_BASE + mgmt->base;
+				outpdw(base_addr + 0x010, 1);
+				outpdw(base_addr + 0x01C, INTR_HIST_DONE |
+						INTR_HIST_RESET_SEQ_DONE);
+				mgmt->mdp_is_hist_valid = FALSE;
+				__mdp_histogram_reset(mgmt);
+			}
+		}
+
+		/* LCDC Frame Start */
+		if (mdp_interrupt & LCDC_FRAME_START) {
+			dma = &dma2_data;
+			spin_lock_irqsave(&mdp_spin_lock, flag);
+			/* let's disable LCDC interrupt */
+			mdp_intr_mask &= ~LCDC_FRAME_START;
+			outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+			if (dma->waiting) {
+				dma->waiting = FALSE;
+				complete(&dma->comp);
+			}
+			spin_unlock_irqrestore(&mdp_spin_lock, flag);
+		}
+
+		/* DMA2 LCD-Out Complete */
+		if (mdp_interrupt & MDP_DMA_S_DONE) {
+			dma = &dma_s_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
+									TRUE);
 			complete(&dma->comp);
 		}
-		spin_unlock_irqrestore(&mdp_spin_lock, flag);
-	}
 
-	/* DMA2 LCD-Out Complete */
-	if (mdp_interrupt & MDP_DMA_S_DONE) {
-		dma = &dma_s_data;
-		dma->busy = FALSE;
-		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+		/* DMA_E LCD-Out Complete */
+		if (mdp_interrupt & MDP_DMA_E_DONE) {
+			dma = &dma_s_data;
+			dma->busy = FALSE;
+			mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF,
+									TRUE);
 			complete(&dma->comp);
+		}
 	}
 
-	/* DMA_E LCD-Out Complete */
-	if (mdp_interrupt & MDP_DMA_E_DONE) {
-		dma = &dma_s_data;
-		dma->busy = FALSE;
-		mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
-		complete(&dma->comp);
-	}
-
-#endif
-
 	/* DMA2 LCD-Out Complete */
 	if (mdp_interrupt & MDP_DMA_P_DONE) {
 		struct timeval now;
@@ -1375,7 +1738,6 @@
 	mdp_dma_wq = create_singlethread_workqueue("mdp_dma_wq");
 	mdp_vsync_wq = create_singlethread_workqueue("mdp_vsync_wq");
 	mdp_hist_wq = create_singlethread_workqueue("mdp_hist_wq");
-	INIT_WORK(&mdp_histogram_worker, mdp_hist_read_work);
 	mdp_pipe_ctrl_wq = create_singlethread_workqueue("mdp_pipe_ctrl_wq");
 	INIT_DELAYED_WORK(&mdp_pipe_ctrl_worker,
 			  mdp_pipe_ctrl_workqueue_handler);
@@ -1416,10 +1778,6 @@
 	mutex_init(&dma_wb_data.ov_mutex);
 #endif
 
-#ifndef CONFIG_FB_MSM_MDP22
-	init_completion(&mdp_hist_comp);
-#endif
-
 	/* initializing mdp power block counter to 0 */
 	for (i = 0; i < MDP_MAX_BLOCK; i++) {
 		atomic_set(&mdp_block_power_cnt[i], 0);
@@ -1508,7 +1866,7 @@
 	int ret = 0;
 	struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
 
-	mdp_histogram_ctrl(FALSE);
+	mdp_histogram_ctrl_all(FALSE);
 
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	ret = panel_next_off(pdev);
@@ -1549,7 +1907,8 @@
 		mdp4_mddi_overlay_restore();
 #endif
 
-	mdp_histogram_ctrl(TRUE);
+	mdp_histogram_ctrl_all(TRUE);
+
 	return ret;
 }
 
@@ -1880,8 +2239,9 @@
 	mfd->ov0_blt_state  = 0;
 	mfd->use_ov0_blt = 0 ;
 
-    /* initialize Post Processing data*/
+	/* initialize Post Processing data*/
 	mdp_hist_lut_init();
+	mdp_histogram_init();
 
 	/* add panel data */
 	if (platform_device_add_data
@@ -1930,6 +2290,8 @@
 			mfd->dma = &dma2_data;
 			mfd->lut_update = mdp_lut_update_nonlcdc;
 			mfd->do_histogram = mdp_do_histogram;
+			mfd->start_histogram = mdp_histogram_start;
+			mfd->stop_histogram = mdp_histogram_stop;
 		} else {
 			mfd->dma_fnc = mdp_dma_s_update;
 			mfd->dma = &dma_s_data;
@@ -1976,6 +2338,8 @@
 		mfd->dma_fnc = mdp4_dsi_video_overlay;
 		mfd->lut_update = mdp_lut_update_lcdc;
 		mfd->do_histogram = mdp_do_histogram;
+		mfd->start_histogram = mdp_histogram_start;
+		mfd->stop_histogram = mdp_histogram_stop;
 		if (mfd->panel_info.pdest == DISPLAY_1) {
 			if_no = PRIMARY_INTF_SEL;
 			mfd->dma = &dma2_data;
@@ -1990,6 +2354,8 @@
 		mfd->hw_refresh = TRUE;
 		mfd->dma_fnc = mdp_dsi_video_update;
 		mfd->do_histogram = mdp_do_histogram;
+		mfd->start_histogram = mdp_histogram_start;
+		mfd->stop_histogram = mdp_histogram_stop;
 		if (mfd->panel_info.pdest == DISPLAY_1)
 			mfd->dma = &dma2_data;
 		else {
@@ -2019,6 +2385,8 @@
 		}
 		mfd->lut_update = mdp_lut_update_nonlcdc;
 		mfd->do_histogram = mdp_do_histogram;
+		mfd->start_histogram = mdp_histogram_start;
+		mfd->stop_histogram = mdp_histogram_stop;
 		mdp4_display_intf_sel(if_no, DSI_CMD_INTF);
 
 		mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
@@ -2030,6 +2398,8 @@
 #else
 		mfd->dma_fnc = mdp_dma2_update;
 		mfd->do_histogram = mdp_do_histogram;
+		mfd->start_histogram = mdp_histogram_start;
+		mfd->stop_histogram = mdp_histogram_stop;
 		if (mfd->panel_info.pdest == DISPLAY_1)
 			mfd->dma = &dma2_data;
 		else {
@@ -2069,6 +2439,8 @@
 #ifndef CONFIG_FB_MSM_MDP22
 		mfd->lut_update = mdp_lut_update_lcdc;
 		mfd->do_histogram = mdp_do_histogram;
+		mfd->start_histogram = mdp_histogram_start;
+		mfd->stop_histogram = mdp_histogram_stop;
 #endif
 #ifdef CONFIG_FB_MSM_OVERLAY
 		mfd->dma_fnc = mdp4_lcdc_overlay;
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index cf3a26a..6224dba 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -45,8 +45,6 @@
 extern struct mdp_csc_cfg mdp_csc_convert[4];
 
 extern struct workqueue_struct *mdp_hist_wq;
-extern struct work_struct mdp_histogram_worker;
-extern boolean mdp_is_hist_valid;
 
 #define MDP4_REVISION_V1		0
 #define MDP4_REVISION_V2		1
@@ -240,6 +238,32 @@
 	int bank_sel;
 };
 
+struct mdp_hist_mgmt {
+	uint32_t block;
+	uint32_t irq_term;
+	uint32_t base;
+	struct completion mdp_hist_comp;
+	struct mutex mdp_hist_mutex;
+	struct mutex mdp_do_hist_mutex;
+	boolean mdp_is_hist_start, mdp_is_hist_data;
+	boolean mdp_is_hist_valid, mdp_is_hist_init;
+	uint8_t frame_cnt, bit_mask, num_bins;
+	struct work_struct mdp_histogram_worker;
+	struct mdp_histogram_data *hist;
+	uint32_t *c0, *c1, *c2;
+	uint32_t *extra_info;
+};
+
+enum {
+	MDP_HIST_MGMT_DMA_P = 0,
+	MDP_HIST_MGMT_DMA_S,
+	MDP_HIST_MGMT_VG_1,
+	MDP_HIST_MGMT_VG_2,
+	MDP_HIST_MGMT_MAX,
+};
+
+extern struct mdp_hist_mgmt *mdp_hist_mgmt_array[];
+
 #define MDP_CMD_DEBUG_ACCESS_BASE   (MDP_BASE+0x10000)
 
 #define MDP_DMA2_TERM 0x1
@@ -251,8 +275,11 @@
 #define MDP_OVERLAY0_TERM 0x20
 #define MDP_OVERLAY1_TERM 0x40
 #endif
-#define MDP_HISTOGRAM_TERM 0x80
-#define MDP_OVERLAY2_TERM 0x100
+#define MDP_OVERLAY2_TERM 0x80
+#define MDP_HISTOGRAM_TERM_DMA_P 0x100
+#define MDP_HISTOGRAM_TERM_DMA_S 0x200
+#define MDP_HISTOGRAM_TERM_VG_1 0x400
+#define MDP_HISTOGRAM_TERM_VG_2 0x800
 
 #define ACTIVE_START_X_EN BIT(31)
 #define ACTIVE_START_Y_EN BIT(31)
@@ -607,6 +634,10 @@
 #define MDDI_VDO_PACKET_DESC	 0x5666	/* 18 bits */
 #define MDDI_VDO_PACKET_DESC_24  0x5888
 
+#define MDP_HIST_INTR_STATUS_OFF	(0x0014)
+#define MDP_HIST_INTR_CLEAR_OFF		(0x0018)
+#define MDP_HIST_INTR_ENABLE_OFF	(0x001C)
+
 #ifdef CONFIG_FB_MSM_MDP40
 #define MDP_INTR_ENABLE		(msm_mdp_base + 0x0050)
 #define MDP_INTR_STATUS		(msm_mdp_base + 0x0054)
@@ -618,6 +649,7 @@
 #define MDP_DMA_P_HIST_INTR_STATUS 	(msm_mdp_base + 0x95014)
 #define MDP_DMA_P_HIST_INTR_CLEAR 	(msm_mdp_base + 0x95018)
 #define MDP_DMA_P_HIST_INTR_ENABLE 	(msm_mdp_base + 0x9501C)
+
 #else
 #define MDP_INTR_ENABLE		(msm_mdp_base + 0x0020)
 #define MDP_INTR_STATUS		(msm_mdp_base + 0x0024)
@@ -761,11 +793,14 @@
 #endif
 
 void mdp_dma_s_update(struct msm_fb_data_type *mfd);
-int mdp_start_histogram(struct fb_info *info);
-int mdp_stop_histogram(struct fb_info *info);
-int mdp_histogram_ctrl(boolean en);
-void __mdp_histogram_kickoff(void);
-void __mdp_histogram_reset(void);
+int mdp_histogram_start(struct mdp_histogram_start_req *req);
+int mdp_histogram_stop(struct fb_info *info, uint32_t block);
+int mdp_histogram_ctrl(boolean en, uint32_t block);
+int mdp_histogram_ctrl_all(boolean en);
+int mdp_histogram_block2mgmt(uint32_t block, struct mdp_hist_mgmt **mgmt);
+void mdp_histogram_handle_isr(struct mdp_hist_mgmt *mgmt);
+void __mdp_histogram_kickoff(struct mdp_hist_mgmt *mgmt);
+void __mdp_histogram_reset(struct mdp_hist_mgmt *mgmt);
 void mdp_footswitch_ctrl(boolean on);
 
 #ifdef CONFIG_FB_MSM_MDP303
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 9c047e5..562c0c8 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -127,13 +127,20 @@
 #define INTR_EXTERNAL_INTF_UDERRUN	BIT(10)
 #define INTR_PRIMARY_READ_PTR		BIT(11)
 #define INTR_DMA_P_HISTOGRAM		BIT(17)
+#define INTR_DMA_S_HISTOGRAM		BIT(26)
 #define INTR_OVERLAY2_DONE		BIT(30)
 
 #ifdef CONFIG_FB_MSM_OVERLAY
-#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_HISTOGRAM)
+#define MDP4_ANY_INTR_MASK	(INTR_DMA_P_HISTOGRAM | \
+				INTR_DMA_S_HISTOGRAM | \
+				INTR_VG1_HISTOGRAM | \
+				INTR_VG2_HISTOGRAM)
 #else
 #define MDP4_ANY_INTR_MASK	(INTR_DMA_P_DONE| \
-				INTR_DMA_P_HISTOGRAM)
+				INTR_DMA_P_HISTOGRAM | \
+				INTR_DMA_S_HISTOGRAM | \
+				INTR_VG1_HISTOGRAM | \
+				INTR_VG2_HISTOGRAM)
 #endif
 
 enum {
diff --git a/drivers/video/msm/mdp4_dtv.c b/drivers/video/msm/mdp4_dtv.c
index 9f2cf8c..f7e74e6 100644
--- a/drivers/video/msm/mdp4_dtv.c
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -91,9 +91,9 @@
 
 	pr_info("%s\n", __func__);
 
-	clk_disable(hdmi_clk);
+	clk_disable_unprepare(hdmi_clk);
 	if (mdp_tv_clk)
-		clk_disable(mdp_tv_clk);
+		clk_disable_unprepare(mdp_tv_clk);
 
 	if (dtv_pdata && dtv_pdata->lcdc_power_save)
 		dtv_pdata->lcdc_power_save(0);
@@ -106,7 +106,7 @@
 							0);
 #else
 	if (ebi1_clk)
-		clk_disable(ebi1_clk);
+		clk_disable_unprepare(ebi1_clk);
 #endif
 	mdp4_extn_disp = 0;
 	return ret;
@@ -134,7 +134,7 @@
 #else
 	if (ebi1_clk) {
 		clk_set_rate(ebi1_clk, pm_qos_rate * 1000);
-		clk_enable(ebi1_clk);
+		clk_prepare_enable(ebi1_clk);
 	}
 #endif
 	mfd = platform_get_drvdata(pdev);
@@ -150,13 +150,13 @@
 	pr_info("%s: tv_src_clk=%dkHz, pm_qos_rate=%ldkHz, [%d]\n", __func__,
 		mfd->fbi->var.pixclock/1000, pm_qos_rate, ret);
 
-	clk_enable(hdmi_clk);
+	clk_prepare_enable(hdmi_clk);
 	clk_reset(hdmi_clk, CLK_RESET_ASSERT);
 	udelay(20);
 	clk_reset(hdmi_clk, CLK_RESET_DEASSERT);
 
 	if (mdp_tv_clk)
-		clk_enable(mdp_tv_clk);
+		clk_prepare_enable(mdp_tv_clk);
 
 	if (dtv_pdata && dtv_pdata->lcdc_power_save)
 		dtv_pdata->lcdc_power_save(1);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 1962ff8..f1f846f 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -411,7 +411,7 @@
 
 	/* dma2 config register */
 	curr = inpdw(MDP_BASE + 0x90000);
-	mask = 0xBFFFFFFF;
+	mask = 0x0FFFFFFF;
 	dma2_cfg_reg = (dma2_cfg_reg & mask) | (curr & ~mask);
 	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
 
@@ -1268,6 +1268,7 @@
 {
 	uint32 data, intf;
 	char *overlay_base;
+	uint32 curr;
 
 	intf = 0;
 	if (pipe->mixer_num == MDP4_MIXER2)
@@ -1309,10 +1310,13 @@
 			outpdw(overlay_base + 0x001c, pipe->blt_addr + off);
 			/* MDDI - BLT + on demand */
 			outpdw(overlay_base + 0x0004, 0x08);
+
+			curr = inpdw(overlay_base + 0x0014);
+			curr &= 0x4;
 #ifdef BLT_RGB565
-			outpdw(overlay_base + 0x0014, 0x1); /* RGB565 */
+			outpdw(overlay_base + 0x0014, curr | 0x1); /* RGB565 */
 #else
-			outpdw(overlay_base + 0x0014, 0x0); /* RGB888 */
+			outpdw(overlay_base + 0x0014, curr | 0x0); /* RGB888 */
 #endif
 		} else if (pipe->mixer_num == MDP4_MIXER2) {
 			if (ctrl->panel_mode & MDP4_PANEL_WRITEBACK) {
@@ -1339,7 +1343,9 @@
 				/* MDDI - BLT + on demand */
 				outpdw(overlay_base + 0x0004, 0x08);
 				/* pseudo planar + writeback */
-				outpdw(overlay_base + 0x0014, 0x012);
+				curr = inpdw(overlay_base + 0x0014);
+				curr &= 0x4;
+				outpdw(overlay_base + 0x0014, curr | 0x012);
 				/* rgb->yuv */
 				outpdw(overlay_base + 0x0200, 0x05);
 			}
@@ -1356,6 +1362,8 @@
 
 	if (pipe->mixer_num == MDP4_MIXER1) {
 		if (intf == TV_INTF) {
+			curr = inpdw(overlay_base + 0x0014);
+			curr &= 0x4;
 			outpdw(overlay_base + 0x0014, 0x02); /* yuv422 */
 			/* overlay1 CSC config */
 			outpdw(overlay_base + 0x0200, 0x05); /* rgb->yuv */
@@ -1363,7 +1371,9 @@
 	}
 
 #ifdef MDP4_IGC_LUT_ENABLE
-	outpdw(overlay_base + 0x0014, 0x4);	/* GC_LUT_EN, 888 */
+	curr = inpdw(overlay_base + 0x0014);
+	curr &= ~0x4;
+	outpdw(overlay_base + 0x0014, curr | 0x4);	/* GC_LUT_EN, 888 */
 #endif
 
 	if (mdp_is_in_isr == FALSE)
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index f06f380..d120071 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -274,7 +274,8 @@
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x30, dsi_hsync_skew);
 	MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE + 0x38, ctrl_polarity);
 	mdp4_overlay_reg_flush(pipe, 1);
-	mdp_histogram_ctrl(TRUE);
+
+	mdp_histogram_ctrl_all(TRUE);
 
 	ret = panel_next_on(pdev);
 	if (ret == 0) {
@@ -300,7 +301,7 @@
 	/* MDP cmd block disable */
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-	mdp_histogram_ctrl(FALSE);
+	mdp_histogram_ctrl_all(FALSE);
 	ret = panel_next_off(pdev);
 
 	/* dis-engage rgb0 from mixer0 */
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index b94d1a4..5e0b0c7 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -370,6 +370,10 @@
 		mdp4_overlay_dtv_alloc_pipe(mfd, OVERLAY_TYPE_RGB);
 	if (dtv_pipe == NULL)
 		return -ENODEV;
+
+	mdp4_init_writeback_buf(mfd, MDP4_MIXER1);
+	dtv_pipe->blt_addr = 0;
+
 	return mdp4_dtv_start(mfd);
 }
 
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index ed4553d..3f90380 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -247,7 +247,7 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	mdp_bus_scale_update_request(2);
 #endif
-	mdp_histogram_ctrl(TRUE);
+	mdp_histogram_ctrl_all(TRUE);
 
 	ret = panel_next_on(pdev);
 	/* MDP cmd block disable */
@@ -273,7 +273,7 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
-	mdp_histogram_ctrl(FALSE);
+	mdp_histogram_ctrl_all(FALSE);
 	ret = panel_next_off(pdev);
 
 	mutex_unlock(&mfd->dma->ov_mutex);
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index a197c90..3aa848c 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -358,6 +358,9 @@
 {
 	uint32 isr, mask, panel;
 	struct mdp_dma_data *dma;
+	struct mdp_hist_mgmt *mgmt = NULL;
+	char *base_addr;
+	int i, ret;
 
 	mdp_is_in_isr = TRUE;
 
@@ -379,10 +382,17 @@
 		/* When underun occurs mdp clear the histogram registers
 		that are set before in hw_init so restore them back so
 		that histogram works.*/
-		MDP_OUTP(MDP_BASE + 0x95010, 1);
-		outpdw(MDP_BASE + 0x9501c, INTR_HIST_DONE);
-		mdp_is_hist_valid = FALSE;
-		__mdp_histogram_reset();
+		for (i = 0; i < MDP_HIST_MGMT_MAX; i++) {
+			mgmt = mdp_hist_mgmt_array[i];
+			if (!mgmt)
+				continue;
+			base_addr = MDP_BASE + mgmt->base;
+			MDP_OUTP(base_addr + 0x010, 1);
+			outpdw(base_addr + 0x01c, INTR_HIST_DONE |
+						INTR_HIST_RESET_SEQ_DONE);
+			mgmt->mdp_is_hist_valid = FALSE;
+			__mdp_histogram_reset(mgmt);
+		}
 	}
 
 	if (isr & INTR_EXTERNAL_INTF_UDERRUN)
@@ -556,24 +566,27 @@
 	}
 	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);
-		mb();
-		isr &= mask;
-		if (isr & INTR_HIST_RESET_SEQ_DONE)
-			__mdp_histogram_kickoff();
-
-		if (isr & INTR_HIST_DONE) {
-			if (waitqueue_active(&mdp_hist_comp.wait)) {
-				if (!queue_work(mdp_hist_wq,
-						&mdp_histogram_worker)) {
-					pr_err("%s - can't queue hist_read\n",
-							__func__);
-				}
-			} else
-				__mdp_histogram_reset();
-		}
+		ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_P, &mgmt);
+		if (!ret)
+			mdp_histogram_handle_isr(mgmt);
+	}
+	if (isr & INTR_DMA_S_HISTOGRAM) {
+		mdp4_stat.intr_histogram++;
+		ret = mdp_histogram_block2mgmt(MDP_BLOCK_DMA_S, &mgmt);
+		if (!ret)
+			mdp_histogram_handle_isr(mgmt);
+	}
+	if (isr & INTR_VG1_HISTOGRAM) {
+		mdp4_stat.intr_histogram++;
+		ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_1, &mgmt);
+		if (!ret)
+			mdp_histogram_handle_isr(mgmt);
+	}
+	if (isr & INTR_VG2_HISTOGRAM) {
+		mdp4_stat.intr_histogram++;
+		ret = mdp_histogram_block2mgmt(MDP_BLOCK_VG_2, &mgmt);
+		if (!ret)
+			mdp_histogram_handle_isr(mgmt);
 	}
 
 out:
diff --git a/drivers/video/msm/mdp_dma_dsi_video.c b/drivers/video/msm/mdp_dma_dsi_video.c
index e1d7acc..1ba5b8d 100644
--- a/drivers/video/msm/mdp_dma_dsi_video.c
+++ b/drivers/video/msm/mdp_dma_dsi_video.c
@@ -73,7 +73,7 @@
 	struct fb_var_screeninfo *var;
 	struct msm_fb_data_type *mfd;
 	int ret;
-	uint32 mask, curr;
+	uint32_t mask, curr;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -142,8 +142,8 @@
 	MDP_OUTP(MDP_BASE + DMA_P_BASE + 0x10, 0);
 
 	/* dma config */
-	curr = inpdw(MDP_BASE + 0x90000);
-	mask = 0xBFFFFFFF;
+	curr = inpdw(MDP_BASE + DMA_P_BASE);
+	mask = 0x0FFFFFFF;
 	dma2_cfg_reg = (dma2_cfg_reg & mask) | (curr & ~mask);
 	MDP_OUTP(MDP_BASE + DMA_P_BASE, dma2_cfg_reg);
 
diff --git a/drivers/video/msm/mdp_dma_lcdc.c b/drivers/video/msm/mdp_dma_lcdc.c
index 7350d91..c418e9c 100644
--- a/drivers/video/msm/mdp_dma_lcdc.c
+++ b/drivers/video/msm/mdp_dma_lcdc.c
@@ -93,6 +93,7 @@
 	uint32 timer_base = LCDC_BASE;
 	uint32 block = MDP_DMA2_BLOCK;
 	int ret;
+	uint32_t mask, curr;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -170,6 +171,9 @@
 	/* x/y coordinate = always 0 for lcdc */
 	MDP_OUTP(MDP_BASE + dma_base + 0x10, 0);
 	/* dma config */
+	curr = inpdw(MDP_BASE + DMA_P_BASE);
+	mask = 0x0FFFFFFF;
+	dma2_cfg_reg = (dma2_cfg_reg & mask) | (curr & ~mask);
 	MDP_OUTP(MDP_BASE + dma_base, dma2_cfg_reg);
 
 	/*
diff --git a/drivers/video/msm/mdp_lcdc.c b/drivers/video/msm/mdp_lcdc.c
index be8d39d..62b0975 100644
--- a/drivers/video/msm/mdp_lcdc.c
+++ b/drivers/video/msm/mdp_lcdc.c
@@ -91,9 +91,9 @@
 	pr_info("%s: suspending\n", __func__);
 
 	mdp_writel(lcdc->mdp, 0, MDP_LCDC_EN);
-	clk_disable(lcdc->pad_pclk);
-	clk_disable(lcdc->pclk);
-	clk_disable(lcdc->mdp_clk);
+	clk_disable_unprepare(lcdc->pad_pclk);
+	clk_disable_unprepare(lcdc->pclk);
+	clk_disable_unprepare(lcdc->mdp_clk);
 
 	return 0;
 }
@@ -104,9 +104,9 @@
 
 	pr_info("%s: resuming\n", __func__);
 
-	clk_enable(lcdc->mdp_clk);
-	clk_enable(lcdc->pclk);
-	clk_enable(lcdc->pad_pclk);
+	clk_prepare_enable(lcdc->mdp_clk);
+	clk_prepare_enable(lcdc->pclk);
+	clk_prepare_enable(lcdc->pad_pclk);
 	mdp_writel(lcdc->mdp, 1, MDP_LCDC_EN);
 
 	return 0;
@@ -117,9 +117,9 @@
 	struct msm_panel_data *fb_panel = &lcdc->fb_panel_data;
 	uint32_t dma_cfg;
 
-	clk_enable(lcdc->mdp_clk);
-	clk_enable(lcdc->pclk);
-	clk_enable(lcdc->pad_pclk);
+	clk_prepare_enable(lcdc->mdp_clk);
+	clk_prepare_enable(lcdc->pclk);
+	clk_prepare_enable(lcdc->pad_pclk);
 
 	clk_set_rate(lcdc->pclk, lcdc->parms.clk_rate);
 	clk_set_rate(lcdc->pad_pclk, lcdc->parms.clk_rate);
diff --git a/drivers/video/msm/mdp_vsync.c b/drivers/video/msm/mdp_vsync.c
index c73de92..87e74d9 100644
--- a/drivers/video/msm/mdp_vsync.c
+++ b/drivers/video/msm/mdp_vsync.c
@@ -79,7 +79,7 @@
 		return;
 	mutex_lock(&vsync_clk_lock);
 	if (mfd->use_mdp_vsync) {
-		clk_enable(mdp_vsync_clk);
+		clk_prepare_enable(mdp_vsync_clk);
 		vsync_clk_status = 1;
 	}
 	mutex_unlock(&vsync_clk_lock);
@@ -91,7 +91,7 @@
 		return;
 	mutex_lock(&vsync_clk_lock);
 	if (mfd->use_mdp_vsync) {
-		clk_disable(mdp_vsync_clk);
+		clk_disable_unprepare(mdp_vsync_clk);
 		vsync_clk_status = 0;
 	}
 	mutex_unlock(&vsync_clk_lock);
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index c6f531e..b84072b 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -18,7 +18,6 @@
 static struct msm_panel_common_pdata *mipi_nt35510_pdata;
 static struct dsi_buf nt35510_tx_buf;
 static struct dsi_buf nt35510_rx_buf;
-spinlock_t bl_spinlock;
 
 #define NT35510_SLEEP_OFF_DELAY 150
 #define NT35510_DISPLAY_ON_DELAY 150
@@ -508,7 +507,7 @@
 	if (pdev->id == 0) {
 		mipi_nt35510_pdata = pdev->dev.platform_data;
 		if (mipi_nt35510_pdata->bl_lock)
-			spin_lock_init(&bl_spinlock);
+			spin_lock_init(&mipi_nt35510_pdata->bl_spinlock);
 		return 0;
 	}
 
@@ -531,9 +530,9 @@
 	bl_level = mfd->bl_level;
 
 	if (mipi_nt35510_pdata->bl_lock) {
-		spin_lock_irqsave(&bl_spinlock, flags);
+		spin_lock_irqsave(&mipi_nt35510_pdata->bl_spinlock, flags);
 		mipi_nt35510_pdata->pmic_backlight(bl_level);
-		spin_unlock_irqrestore(&bl_spinlock, flags);
+		spin_unlock_irqrestore(&mipi_nt35510_pdata->bl_spinlock, flags);
 	} else
 		mipi_nt35510_pdata->pmic_backlight(bl_level);
 }
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index 7e3eb19..b8169d9 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -132,6 +132,7 @@
 	mipi_dsi_ahb_ctrl(0);
 	local_bh_enable();
 
+	mipi_dsi_unprepare_clocks();
 	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
 		mipi_dsi_pdata->dsi_power_save(0);
 
@@ -168,6 +169,8 @@
 		mipi_dsi_pdata->dsi_power_save(1);
 
 	cont_splash_clk_ctrl(0);
+	mipi_dsi_prepare_clocks();
+
 	local_bh_disable();
 	mipi_dsi_ahb_ctrl(1);
 	local_bh_enable();
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index 31ce3ba..ff2910f 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -301,6 +301,8 @@
 			    uint32 *expected_dsi_pclk);
 int mipi_dsi_clk_init(struct platform_device *pdev);
 void mipi_dsi_clk_deinit(struct device *dev);
+void mipi_dsi_prepare_clocks(void);
+void mipi_dsi_unprepare_clocks(void);
 void mipi_dsi_ahb_ctrl(u32 enable);
 void cont_splash_clk_ctrl(int enable);
 void mipi_dsi_turn_on_clks(void);
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e.c b/drivers/video/msm/mipi_truly_tft540960_1_e.c
index 30e255e..e465d46 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e.c
@@ -726,6 +726,8 @@
 
 	if (pdev->id == 0) {
 		mipi_truly_pdata = pdev->dev.platform_data;
+		if (mipi_truly_pdata->bl_lock)
+			spin_lock_init(&mipi_truly_pdata->bl_spinlock);
 		return rc;
 	}
 
@@ -743,7 +745,16 @@
 
 static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
 {
-	return;
+	int bl_level;
+	unsigned long flags;
+	bl_level = mfd->bl_level;
+
+	if (mipi_truly_pdata->bl_lock) {
+		spin_lock_irqsave(&mipi_truly_pdata->bl_spinlock, flags);
+		mipi_truly_pdata->pmic_backlight(bl_level);
+		spin_unlock_irqrestore(&mipi_truly_pdata->bl_spinlock, flags);
+	} else
+		mipi_truly_pdata->pmic_backlight(bl_level);
 }
 
 static struct msm_fb_panel_data truly_panel_data = {
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
index b3805c5..de98177 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
@@ -56,7 +56,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 16;
+	pinfo.bl_max = 31;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
index 0e12813..ea2ff47 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
@@ -59,7 +59,7 @@
 	pinfo.lcdc.hsync_skew = 0;
 	pinfo.clk_rate = 699000000;
 	pinfo.lcd.refx100 = 6000; /* FB driver calc FPS based on this value */
-	pinfo.bl_max = 16;
+	pinfo.bl_max = 31;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/msm_dss_io_7x27a.c b/drivers/video/msm/msm_dss_io_7x27a.c
index 70f8982..9e77e30 100644
--- a/drivers/video/msm/msm_dss_io_7x27a.c
+++ b/drivers/video/msm/msm_dss_io_7x27a.c
@@ -316,6 +316,28 @@
 {
 }
 
+void mipi_dsi_prepare_clocks(void)
+{
+	clk_prepare(dsi_ref_clk);
+	clk_prepare(ahb_m_clk);
+	clk_prepare(ahb_s_clk);
+	clk_prepare(ebi1_dsi_clk);
+	clk_prepare(mdp_dsi_pclk);
+	clk_prepare(dsi_byte_div_clk);
+	clk_prepare(dsi_esc_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+	clk_unprepare(dsi_esc_clk);
+	clk_unprepare(dsi_byte_div_clk);
+	clk_unprepare(mdp_dsi_pclk);
+	clk_unprepare(ebi1_dsi_clk);
+	clk_unprepare(ahb_m_clk);
+	clk_unprepare(ahb_s_clk);
+	clk_unprepare(dsi_ref_clk);
+}
+
 void mipi_dsi_ahb_ctrl(u32 enable)
 {
 	static int ahb_ctrl_done;
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index eb30448..30edbd1 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -548,16 +548,34 @@
 {
 	static int cont_splash_clks_enabled;
 	if (enable && !cont_splash_clks_enabled) {
-			clk_enable(dsi_byte_div_clk);
-			clk_enable(dsi_esc_clk);
+			clk_prepare_enable(dsi_byte_div_clk);
+			clk_prepare_enable(dsi_esc_clk);
 			cont_splash_clks_enabled = 1;
 	} else if (!enable && cont_splash_clks_enabled) {
-			clk_disable(dsi_byte_div_clk);
-			clk_disable(dsi_esc_clk);
+			clk_disable_unprepare(dsi_byte_div_clk);
+			clk_disable_unprepare(dsi_esc_clk);
 			cont_splash_clks_enabled = 0;
 	}
 }
 
+void mipi_dsi_prepare_clocks(void)
+{
+	clk_prepare(amp_pclk);
+	clk_prepare(dsi_m_pclk);
+	clk_prepare(dsi_s_pclk);
+	clk_prepare(dsi_byte_div_clk);
+	clk_prepare(dsi_esc_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+	clk_unprepare(dsi_esc_clk);
+	clk_unprepare(dsi_byte_div_clk);
+	clk_unprepare(dsi_m_pclk);
+	clk_unprepare(dsi_s_pclk);
+	clk_unprepare(amp_pclk);
+}
+
 void mipi_dsi_ahb_ctrl(u32 enable)
 {
 	static int ahb_ctrl_done;
diff --git a/drivers/video/msm/msm_dss_io_8x60.c b/drivers/video/msm/msm_dss_io_8x60.c
index 72d7960..bbee726 100644
--- a/drivers/video/msm/msm_dss_io_8x60.c
+++ b/drivers/video/msm/msm_dss_io_8x60.c
@@ -407,6 +407,24 @@
 {
 }
 
+void mipi_dsi_prepare_clocks(void)
+{
+	clk_prepare(amp_pclk);
+	clk_prepare(dsi_m_pclk);
+	clk_prepare(dsi_s_pclk);
+	clk_prepare(dsi_byte_div_clk);
+	clk_prepare(dsi_esc_clk);
+}
+
+void mipi_dsi_unprepare_clocks(void)
+{
+	clk_unprepare(dsi_esc_clk);
+	clk_unprepare(dsi_byte_div_clk);
+	clk_unprepare(dsi_m_pclk);
+	clk_unprepare(dsi_s_pclk);
+	clk_unprepare(amp_pclk);
+}
+
 void mipi_dsi_ahb_ctrl(u32 enable)
 {
 	static int ahb_ctrl_done;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 74f7ead..76653ec 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2962,7 +2962,6 @@
 
 DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem);
 DEFINE_MUTEX(msm_fb_ioctl_lut_sem);
-DEFINE_MUTEX(msm_fb_ioctl_hist_sem);
 
 /* Set color conversion matrix from user space */
 
@@ -3088,7 +3087,9 @@
 	void __user *argp = (void __user *)arg;
 	struct fb_cursor cursor;
 	struct fb_cmap cmap;
-	struct mdp_histogram hist;
+	struct mdp_histogram_data hist;
+	struct mdp_histogram_start_req hist_req;
+	uint32_t block;
 #ifndef CONFIG_FB_MSM_MDP40
 	struct mdp_ccs ccs_matrix;
 #else
@@ -3309,24 +3310,32 @@
 		if (ret)
 			return ret;
 
-		mutex_lock(&msm_fb_ioctl_hist_sem);
 		ret = mfd->do_histogram(info, &hist);
-		mutex_unlock(&msm_fb_ioctl_hist_sem);
 		break;
 
 	case MSMFB_HISTOGRAM_START:
 		if (!mfd->panel_power_on)
 			return -EPERM;
 
-		if (!mfd->do_histogram)
+		if (!mfd->start_histogram)
 			return -ENODEV;
-		ret = mdp_start_histogram(info);
+
+		ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
+		if (ret)
+			return ret;
+
+		ret = mfd->start_histogram(&hist_req);
 		break;
 
 	case MSMFB_HISTOGRAM_STOP:
-		if (!mfd->do_histogram)
+		if (!mfd->stop_histogram)
 			return -ENODEV;
-		ret = mdp_stop_histogram(info);
+
+		ret = copy_from_user(&block, argp, sizeof(int));
+		if (ret)
+			return ret;
+
+		ret = mfd->stop_histogram(info, block);
 		break;
 
 
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 44d5018..3becc46 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -131,7 +131,9 @@
 	int (*lut_update) (struct fb_info *info,
 			      struct fb_cmap *cmap);
 	int (*do_histogram) (struct fb_info *info,
-			      struct mdp_histogram *hist);
+			      struct mdp_histogram_data *hist);
+	int (*start_histogram) (struct mdp_histogram_start_req *req);
+	int (*stop_histogram) (struct fb_info *info, uint32_t block);
 	void *cursor_buf;
 	void *cursor_buf_phys;
 
diff --git a/drivers/video/msm/tvenc.c b/drivers/video/msm/tvenc.c
index e494cfa..30dc854 100644
--- a/drivers/video/msm/tvenc.c
+++ b/drivers/video/msm/tvenc.c
@@ -101,7 +101,7 @@
 			goto tvsrc_err;
 		}
 #endif
-		ret = clk_enable(tvenc_clk);
+		ret = clk_prepare_enable(tvenc_clk);
 		if (ret) {
 			pr_err("%s: tvenc_clk enable failed! %d\n",
 				__func__, ret);
@@ -109,7 +109,7 @@
 		}
 
 		if (!IS_ERR(tvenc_pclk)) {
-			ret = clk_enable(tvenc_pclk);
+			ret = clk_prepare_enable(tvenc_pclk);
 			if (ret) {
 				pr_err("%s: tvenc_pclk enable failed! %d\n",
 					__func__, ret);
@@ -119,12 +119,12 @@
 		return ret;
 	} else {
 		if (!IS_ERR(tvenc_pclk))
-			clk_disable(tvenc_pclk);
-		clk_disable(tvenc_clk);
+			clk_disable_unprepare(tvenc_pclk);
+		clk_disable_unprepare(tvenc_clk);
 		return ret;
 	}
 tvencp_err:
-	clk_disable(tvenc_clk);
+	clk_disable_unprepare(tvenc_clk);
 tvsrc_err:
 	return ret;
 }
@@ -141,14 +141,14 @@
 				goto tvenc_err;
 			}
 		}
-		ret = clk_enable(tvdac_clk);
+		ret = clk_prepare_enable(tvdac_clk);
 		if (ret) {
 			pr_err("%s: tvdac_clk enable failed! %d\n",
 				__func__, ret);
 			goto tvdac_err;
 		}
 		if (!IS_ERR(mdp_tv_clk)) {
-			ret = clk_enable(mdp_tv_clk);
+			ret = clk_prepare_enable(mdp_tv_clk);
 			if (ret) {
 				pr_err("%s: mdp_tv_clk enable failed! %d\n",
 					__func__, ret);
@@ -158,15 +158,15 @@
 		return ret;
 	} else {
 		if (!IS_ERR(mdp_tv_clk))
-			clk_disable(mdp_tv_clk);
-		clk_disable(tvdac_clk);
+			clk_disable_unprepare(mdp_tv_clk);
+		clk_disable_unprepare(tvdac_clk);
 		if (tvenc_pdata->poll)
 			tvenc_set_encoder_clock(CLOCK_OFF);
 		return ret;
 	}
 
 mdptv_err:
-	clk_disable(tvdac_clk);
+	clk_disable_unprepare(tvdac_clk);
 tvdac_err:
 	tvenc_set_encoder_clock(CLOCK_OFF);
 tvenc_err:
@@ -196,7 +196,7 @@
 							0);
 #else
 	if (mfd->ebi1_clk)
-		clk_disable(mfd->ebi1_clk);
+		clk_disable_unprepare(mfd->ebi1_clk);
 #endif
 
 	if (ret)
@@ -220,7 +220,7 @@
 							1);
 #else
 	if (mfd->ebi1_clk)
-		clk_enable(mfd->ebi1_clk);
+		clk_prepare_enable(mfd->ebi1_clk);
 #endif
 	mdp4_extn_disp = 1;
 	if (tvenc_pdata && tvenc_pdata->pm_vid_en)
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index f983e25..93b1848 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1315,26 +1315,28 @@
 	}
 	case VEN_IOCTL_GET_SEQUENCE_HDR:
 	{
-		struct venc_seqheader seq_header, seq_header_user;
+		struct venc_seqheader seq_header;
 		if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
 			return -EFAULT;
 
-		DBG("VEN_IOCTL_GET_SEQUENCE_HDR\n");
-		if (copy_from_user(&seq_header_user, venc_msg.in,
-			sizeof(seq_header_user)))
+		if (copy_from_user(&seq_header, venc_msg.in,
+			sizeof(seq_header)))
 			return -EFAULT;
-		seq_header.hdrbufptr = NULL;
+
+		DBG("VEN_IOCTL_GET_SEQUENCE_HDR\n");
 		result = vid_enc_get_sequence_header(client_ctx,
 				&seq_header);
-		if (result && ((copy_to_user(seq_header_user.hdrbufptr,
-			seq_header.hdrbufptr, seq_header.hdrlen)) ||
-			(copy_to_user(&seq_header_user.hdrlen,
-			&seq_header.hdrlen,
-			sizeof(seq_header.hdrlen)))))
-				result = false;
-		kfree(seq_header.hdrbufptr);
-		if (!result)
+		if (!result) {
+			ERR("get sequence header failed\n");
 			return -EIO;
+		}
+		DBG("seq_header: buf=%x, sz=%d, hdrlen=%d\n",
+			(int)seq_header.hdrbufptr,
+			(int)seq_header.bufsize,
+			(int)seq_header.hdrlen);
+		if (copy_to_user(venc_msg.out, &seq_header,
+			sizeof(seq_header)))
+			return -EFAULT;
 		break;
 	}
 	case VEN_IOCTL_CMD_REQUEST_IFRAME:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 46dcaf4..ac732c1 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -892,23 +892,17 @@
 	u32 vcd_status = VCD_ERR_FAIL;
 	u32 status = true;
 
-	if (!client_ctx ||
-			!seq_header || !seq_header->bufsize)
+	if (!client_ctx || !seq_header || !seq_header->bufsize)
 		return false;
 
 	vcd_property_hdr.prop_id = VCD_I_SEQ_HEADER;
-	vcd_property_hdr.sz =
-		sizeof(struct vcd_sequence_hdr);
+	vcd_property_hdr.sz = sizeof(struct vcd_sequence_hdr);
 
-	hdr.sequence_header =
-		kzalloc(seq_header->bufsize, GFP_KERNEL);
-	seq_header->hdrbufptr = hdr.sequence_header;
-
-	if (!hdr.sequence_header)
-		return false;
+	hdr.sequence_header = seq_header->hdrbufptr;
 	hdr.sequence_header_len = seq_header->bufsize;
 	vcd_status = vcd_get_property(client_ctx->vcd_handle,
 			&vcd_property_hdr, &hdr);
+	seq_header->hdrlen = hdr.sequence_header_len;
 
 	if (vcd_status) {
 		ERR("%s(): Get VCD_I_SEQ_HEADER Failed\n",
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 09f79a0..86e9ff6 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -96,8 +96,8 @@
 		 cctxt->in_buf_pool.validated != cctxt->in_buf_pool.count) ||
 	    cctxt->out_buf_pool.validated !=
 	    cctxt->out_buf_pool.count) {
-		VCD_MSG_ERROR("Buffer pool is not completely setup yet");
-		return VCD_ERR_BAD_STATE;
+		VCD_MSG_HIGH("%s: Buffer pool is not completely setup yet",
+			__func__);
 	}
 
 	rc = vcd_sched_add_client(cctxt);
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index d4aaa4b..4dc3c80 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -80,8 +80,10 @@
  *			and percent charge
  * @rbatt_sf_lut:	table to get battery resistance scaling factor given
  *			temperature and percent charge
- * default_rbatt_mohm:	the default value of battery resistance to use when
+ * @default_rbatt_mohm:	the default value of battery resistance to use when
  *			readings from bms are not available.
+ * @delta_rbatt_mohm:	the resistance to be added towards lower soc to
+ *			compensate for battery capacitance.
  */
 struct pm8921_bms_battery_data {
 	unsigned int		fcc;
@@ -91,6 +93,7 @@
 	struct sf_lut		*pc_sf_lut;
 	struct sf_lut		*rbatt_sf_lut;
 	int			default_rbatt_mohm;
+	int			delta_rbatt_mohm;
 };
 
 struct pm8xxx_bms_core_data {
@@ -124,6 +127,7 @@
 	unsigned int			v_failure;
 	unsigned int			calib_delay_ms;
 	unsigned int			max_voltage_uv;
+	unsigned int			rconn_mohm;
 };
 
 #if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
diff --git a/include/linux/mfd/wcd9xxx/wcd9304_registers.h b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
index df54e02..65e4728 100644
--- a/include/linux/mfd/wcd9xxx/wcd9304_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9304_registers.h
@@ -413,66 +413,95 @@
 #define SITAR_A_CDC_TX1_VOL_CTL_TIMER__POR			(0x00000000)
 #define SITAR_A_CDC_TX1_VOL_CTL_GAIN			(0x221)
 #define SITAR_A_CDC_TX1_VOL_CTL_GAIN__POR			(0x00000000)
-#define SITAR_A_CDC_TX1_VOL_CTL_CFG			(0x222)
-#define SITAR_A_CDC_TX1_VOL_CTL_CFG__POR			(0x00000000)
+#define SITAR_A_CDC_TX2_VOL_CTL_GAIN			(0x229)
+#define SITAR_A_CDC_TX2_VOL_CTL_GAIN__POR			   (0x00000000)
+#define SITAR_A_CDC_TX3_VOL_CTL_GAIN			(0x231)
+#define SITAR_A_CDC_TX3_VOL_CTL_GAIN__POR			   (0x00000000)
+#define SITAR_A_CDC_TX4_VOL_CTL_GAIN			(0x239)
+#define SITAR_A_CDC_TX4_VOL_CTL_GAIN__POR			   (0x00000000)
+#define SITAR_A_CDC_TX5_VOL_CTL_GAIN			(0x241)
+#define SITAR_A_CDC_TX5_VOL_CTL_GAIN__POR			   (0x00000000)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG			 (0x222)
+#define SITAR_A_CDC_TX1_VOL_CTL_CFG__POR			    (0x00000000)
+#define SITAR_A_CDC_TX2_VOL_CTL_CFG			 (0x22A)
+#define SITAR_A_CDC_TX2_VOL_CTL_CFG__POR			    (0x00000000)
+#define SITAR_A_CDC_TX3_VOL_CTL_CFG			 (0x232)
+#define SITAR_A_CDC_TX3_VOL_CTL_CFG__POR			    (0x00000000)
+#define SITAR_A_CDC_TX4_VOL_CTL_CFG			 (0x23A)
+#define SITAR_A_CDC_TX4_VOL_CTL_CFG__POR			    (0x00000000)
+
 #define SITAR_A_CDC_TX1_MUX_CTL			(0x223)
 #define SITAR_A_CDC_TX1_MUX_CTL__POR			(0x00000008)
 #define SITAR_A_CDC_TX1_CLK_FS_CTL			(0x224)
 #define SITAR_A_CDC_TX1_CLK_FS_CTL__POR			(0x00000003)
 #define SITAR_A_CDC_TX1_DMIC_CTL			(0x225)
 #define SITAR_A_CDC_TX1_DMIC_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_TX2_MUX_CTL                 (0x22B)
+#define SITAR_A_CDC_TX2_MUX_CTL__POR			(0x00000008)
+#define SITAR_A_CDC_TX3_MUX_CTL                 (0x233)
+#define SITAR_A_CDC_TX3_MUX_CTL__POR			(0x00000008)
+#define SITAR_A_CDC_TX4_MUX_CTL                 (0x23B)
+#define SITAR_A_CDC_TX4_MUX_CTL__POR			(0x00000008)
+#define SITAR_A_CDC_TX5_MUX_CTL                 (0x243)
+#define SITAR_A_CDC_TX5_MUX_CTL__POR			(0x00000008)
+
 #define SITAR_A_CDC_SRC1_PDA_CFG			(0x2A0)
 #define SITAR_A_CDC_SRC1_PDA_CFG__POR			(0x00000000)
 #define SITAR_A_CDC_SRC1_FS_CTL			(0x2A1)
 #define SITAR_A_CDC_SRC1_FS_CTL__POR			(0x0000001b)
 
 #define SITAR_A_CDC_RX1_B1_CTL                  (0x000002B0)
-#define SITAR_A_CDC_RX1_B1_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX1_B1_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX2_B1_CTL                  (0x000002B8)
-#define SITAR_A_CDC_RX2_B1_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B1_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX3_B1_CTL                  (0x000002C0)
-#define SITAR_A_CDC_RX3_B1_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B1_CTL__POR			 (0x00000000)
 
 #define SITAR_A_CDC_RX1_B2_CTL                  (0x000002B1)
-#define SITAR_A_CDC_RX1_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX1_B2_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX2_B2_CTL                  (0x000002B9)
-#define SITAR_A_CDC_RX2_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B2_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX3_B2_CTL                  (0x000002C1)
-#define SITAR_A_CDC_RX3_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B2_CTL__POR			 (0x00000000)
 
 #define SITAR_A_CDC_RX1_B3_CTL                  (0x000002B2)
-#define SITAR_A_CDC_RX1_B3_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX1_B3_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX2_B3_CTL                  (0x000002BA)
-#define SITAR_A_CDC_RX2_B3_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B3_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX3_B3_CTL                  (0x000002C2)
-#define SITAR_A_CDC_RX3_B3_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B3_CTL__POR			 (0x00000000)
 
 #define SITAR_A_CDC_RX1_B4_CTL                  (0x000002B3)
-#define SITAR_A_CDC_RX1_B4_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX1_B4_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX2_B4_CTL                  (0x000002BB)
-#define SITAR_A_CDC_RX2_B4_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B4_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX3_B4_CTL                  (0x000002C3)
-#define SITAR_A_CDC_RX3_B4_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B4_CTL__POR			 (0x00000000)
 
 #define SITAR_A_CDC_RX1_B5_CTL                  (0x000002B4)
-#define SITAR_A_CDC_RX1_B5_CTL__POR                     (0x00000060)
+#define SITAR_A_CDC_RX1_B5_CTL__POR			 (0x00000060)
 #define SITAR_A_CDC_RX2_B5_CTL                  (0x000002BC)
-#define SITAR_A_CDC_RX2_B5_CTL__POR                     (0x00000060)
+#define SITAR_A_CDC_RX2_B5_CTL__POR			 (0x00000060)
 #define SITAR_A_CDC_RX3_B5_CTL                  (0x000002C4)
-#define SITAR_A_CDC_RX3_B5_CTL__POR                     (0x00000060)
+#define SITAR_A_CDC_RX3_B5_CTL__POR			 (0x00000060)
 
 #define SITAR_A_CDC_RX1_B6_CTL                  (0x000002B5)
-#define SITAR_A_CDC_RX1_B6_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX1_B6_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX2_B6_CTL                  (0x000002BD)
-#define SITAR_A_CDC_RX2_B6_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX2_B6_CTL__POR			 (0x00000000)
 #define SITAR_A_CDC_RX3_B6_CTL                  (0x000002C5)
-#define SITAR_A_CDC_RX3_B6_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_B6_CTL__POR			 (0x00000000)
 
 
 #define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL			(0x2B6)
 #define SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR			(0x00000000)
 #define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL			(0x2B7)
 #define SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR			(0x00000000)
+#define SITAR_A_CDC_RX2_VOL_CTL_B2_CTL                  (0x2BF)
+#define SITAR_A_CDC_RX2_VOL_CTL_B2_CTL__POR                     (0x00000000)
+#define SITAR_A_CDC_RX3_VOL_CTL_B2_CTL			(0x2C7)
+#define SITAR_A_CDC_RX3_VOL_CTL_B2_CTL__POR                     (0x00000000)
+
 #define SITAR_A_CDC_CLK_ANC_RESET_CTL			(0x300)
 #define SITAR_A_CDC_CLK_ANC_RESET_CTL__POR			(0x00000000)
 #define SITAR_A_CDC_CLK_RX_RESET_CTL			(0x301)
@@ -722,9 +751,9 @@
 #define SITAR_A_CDC_MBHC_SPARE			(0x3DF)
 #define SITAR_A_CDC_MBHC_SPARE__POR			(0x00000000)
 /* SLIMBUS Slave Registers */
-#define SITAR_SLIM_PGD_PORT_INT_EN0                     (0x30)
+#define SITAR_SLIM_PGD_PORT_INT_EN0			 (0x30)
 #define SITAR_SLIM_PGD_PORT_INT_STATUS0                 (0x34)
-#define SITAR_SLIM_PGD_PORT_INT_CLR0                    (0x38)
+#define SITAR_SLIM_PGD_PORT_INT_CLR0			(0x38)
 #define SITAR_SLIM_PGD_PORT_INT_SOURCE0                 (0x60)
 
 /* Macros for Packing Register Writes into a U32 */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index aa54b71..e57df1a 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -352,7 +352,7 @@
 	uint32_t *c0;
 	uint32_t *c1;
 	uint32_t *c2;
-	uint32_t extra_info[2];
+	uint32_t *extra_info;
 };
 
 struct mdp_pcc_coeff {
diff --git a/include/linux/smsc3503.h b/include/linux/smsc3503.h
new file mode 100644
index 0000000..66ba003
--- /dev/null
+++ b/include/linux/smsc3503.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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_SMSC3503_H__
+#define __LINUX_SMSC3503_H__
+
+/*Serial interface Registers*/
+#define SMSC3503_VENDORID	0x00 /*u16 read*/
+#define SMSC3503_PRODUCTID	0x02 /*u16 read*/
+#define SMSC3503_DEVICEID	0x04 /*u16 read*/
+
+#define SMSC3503_CONFIG_BYTE_1	0x06 /*u8 read*/
+#define PORT_PWR	(1<<0)
+#define EOP_DISABLE	(1<<3)
+#define MTT_ENABLE	(1<<4)
+#define HS_DISABLE	(1<<5)
+#define SELF_BUS_PWR	(1<<7)
+
+#define SMSC3503_CONFIG_BYTE_2	0x07 /*u8 read*/
+#define SMSC3503_LANGID		0x11 /*u16 read*/
+#define SMSC3503_MFRSL		0x13 /*u8 read*/
+#define SMSC3503_PRDSL		0x14 /*u8 read*/
+#define SMSC3503_SERSL		0x15 /*u8 read*/
+#define SMSC3503_MANSTR		0x16 /*0x16h-0x53h*/
+#define SMSC3503_PRDSTR		0x54 /*0x54h-0x91h*/
+#define SMSC3503_SERSTR		0x92 /*0x92h-0xCFh*/
+
+#define SMSC3503_SP_ILOCK	0xE7 /*u8 read, set,clear*/
+#define CONFIG_N	(1<<0)
+#define CONNECT_N	(1<<1)
+#define PRTPWRPINSEL	(1<<4)
+#define OCSPINSEL	(1<<5)
+
+struct smsc_hub_platform_data {
+	unsigned hub_reset;
+};
+
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 1a6df8b..a731774 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -19,10 +19,27 @@
 #define __ASM_ARCH_MSM_HSUSB_H
 
 #include <linux/types.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/wakelock.h>
 #include <linux/pm_qos_params.h>
 
+/*
+ * The following are bit fields describing the usb_request.udc_priv word.
+ * These bit fields are set by function drivers that wish to queue
+ * usb_requests with sps/bam parameters.
+ */
+#define MSM_PIPE_ID_MASK		(0x1F)
+#define MSM_TX_PIPE_ID_OFS		(16)
+#define MSM_SPS_MODE			BIT(5)
+#define MSM_IS_FINITE_TRANSFER		BIT(6)
+#define MSM_PRODUCER			BIT(7)
+#define MSM_DISABLE_WB			BIT(8)
+#define MSM_ETD_IOC			BIT(9)
+#define MSM_INTERNAL_MEM		BIT(10)
+#define MSM_VENDOR_ID			BIT(16)
+
 /**
  * Supported USB modes
  *
@@ -330,7 +347,6 @@
 struct msm_hsic_host_platform_data {
 	unsigned strobe;
 	unsigned data;
-	unsigned hub_reset;
 	struct msm_bus_scale_pdata *bus_scale_table;
 };
 
@@ -360,4 +376,9 @@
 	HSUSB_BAM = 0,
 	HSIC_BAM,
 };
+
+int msm_ep_config(struct usb_ep *ep);
+int msm_ep_unconfig(struct usb_ep *ep);
+int msm_data_fifo_config(struct usb_ep *ep, u32 addr, u32 size);
+
 #endif
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 9759b32..1c492f9 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -35,6 +35,8 @@
 				const struct dev_pm_ops *pm_ops);
 void wcnss_wlan_unregister_pm_ops(struct device *dev,
 				const struct dev_pm_ops *pm_ops);
+void wcnss_register_thermal_mitigation(void (*tm_notify)(int));
+void wcnss_unregister_thermal_mitigation(void (*tm_notify)(int));
 struct platform_device *wcnss_get_platform_device(void);
 struct wcnss_wlan_config *wcnss_get_wlan_config(void);
 int wcnss_wlan_power(struct device *dev,
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 92323cb..31977ed 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -190,6 +190,9 @@
 #define MSM_CAM_IOCTL_MCTL_DIVERT_DONE \
 	_IOR(MSM_CAM_IOCTL_MAGIC, 53, struct msm_cam_evt_divert_frame *)
 
+#define MSM_CAM_IOCTL_GET_ACTUATOR_INFO \
+	_IOW(MSM_CAM_IOCTL_MAGIC, 54, struct msm_actuator_cfg_data *)
+
 struct msm_mctl_pp_cmd {
 	int32_t  id;
 	uint16_t length;
@@ -212,6 +215,16 @@
 
 #define MSM_MAX_CAMERA_SENSORS  5
 #define MAX_SENSOR_NAME 32
+#define MAX_CAM_NAME_SIZE 32
+#define MAX_ACT_MOD_NAME_SIZE 32
+#define MAX_ACT_NAME_SIZE 32
+#define NUM_ACTUATOR_DIR 2
+#define MAX_ACTUATOR_SCENARIO 8
+#define MAX_ACTUATOR_REGION 5
+#define MAX_ACTUATOR_INIT_SET 12
+#define MAX_ACTUATOR_TYPE_SIZE 32
+#define MAX_ACTUATOR_REG_TBL_SIZE 8
+
 
 #define MSM_MAX_CAMERA_CONFIGS 2
 
@@ -1121,15 +1134,84 @@
 	} cfg;
 };
 
+struct damping_params_t {
+	uint32_t damping_step;
+	uint32_t damping_delay;
+	uint32_t hw_params;
+};
+
+enum actuator_type {
+	ACTUATOR_VCM,
+	ACTUATOR_PIEZO,
+};
+
+enum msm_actuator_data_type {
+	MSM_ACTUATOR_BYTE_DATA = 1,
+	MSM_ACTUATOR_WORD_DATA,
+};
+
+enum msm_actuator_addr_type {
+	MSM_ACTUATOR_BYTE_ADDR = 1,
+	MSM_ACTUATOR_WORD_ADDR,
+};
+
+enum msm_actuator_write_type {
+	MSM_ACTUATOR_WRITE_HW_DAMP,
+	MSM_ACTUATOR_WRITE_DAC,
+};
+
+struct msm_actuator_reg_params_t {
+	enum msm_actuator_write_type reg_write_type;
+	uint32_t hw_mask;
+	uint16_t reg_addr;
+	uint16_t hw_shift;
+	uint16_t data_shift;
+};
+
+struct reg_settings_t {
+	uint16_t reg_addr;
+	uint16_t reg_data;
+};
+
+struct region_params_t {
+	/* [0] = ForwardDirection Macro boundary
+	   [1] = ReverseDirection Inf boundary
+	 */
+	uint16_t step_bound[2];
+	uint16_t code_per_step;
+};
+
 struct msm_actuator_move_params_t {
 	int8_t dir;
+	int8_t sign_dir;
+	int16_t dest_step_pos;
 	int32_t num_steps;
+	struct damping_params_t *ringing_params;
+};
+
+struct msm_actuator_tuning_params_t {
+	int16_t initial_code;
+	uint16_t pwd_step;
+	uint16_t region_size;
+	uint32_t total_steps;
+	struct region_params_t *region_params;
+};
+
+struct msm_actuator_params_t {
+	enum actuator_type act_type;
+	uint8_t reg_tbl_size;
+	uint16_t data_size;
+	uint16_t init_setting_size;
+	uint32_t i2c_addr;
+	enum msm_actuator_addr_type i2c_addr_type;
+	enum msm_actuator_data_type i2c_data_type;
+	struct msm_actuator_reg_params_t *reg_tbl_params;
+	struct reg_settings_t *init_settings;
 };
 
 struct msm_actuator_set_info_t {
-	uint32_t total_steps;
-	uint16_t gross_steps;
-	uint16_t fine_steps;
+	struct msm_actuator_params_t actuator_params;
+	struct msm_actuator_tuning_params_t af_tuning_params;
 };
 
 struct msm_actuator_get_info_t {
@@ -1147,6 +1229,18 @@
 	uint32_t ver_view_angle_den;
 };
 
+enum af_camera_name {
+	ACTUATOR_MAIN_CAM_0,
+	ACTUATOR_MAIN_CAM_1,
+	ACTUATOR_MAIN_CAM_2,
+	ACTUATOR_MAIN_CAM_3,
+	ACTUATOR_MAIN_CAM_4,
+	ACTUATOR_MAIN_CAM_5,
+	ACTUATOR_WEB_CAM_0,
+	ACTUATOR_WEB_CAM_1,
+	ACTUATOR_WEB_CAM_2,
+};
+
 struct msm_actuator_cfg_data {
 	int cfgtype;
 	uint8_t is_af_supported;
@@ -1154,6 +1248,7 @@
 		struct msm_actuator_move_params_t move;
 		struct msm_actuator_set_info_t set_info;
 		struct msm_actuator_get_info_t get_info;
+		enum af_camera_name cam_name;
 	} cfg;
 };
 
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 5408a52..f71d743 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1033,6 +1033,10 @@
 #define WMA_V9       0x00010BF4
 #define AMR_WB_PLUS  0x00010BF5
 #define AC3_DECODER  0x00010BF6
+#define EAC3_DECODER 0x00010C3C
+#define DTS	0x00010D88
+#define ATRAC	0x00010D89
+#define MAT	0x00010D8A
 #define G711_ALAW_FS 0x00010BF7
 #define G711_MLAW_FS 0x00010BF8
 #define G711_PCM_FS  0x00010BF9
@@ -1059,6 +1063,16 @@
 	u32            format;
 } __attribute__((packed));
 
+#define IEC_61937_MASK	0x00000001
+#define IEC_60958_MASK	0x00000002
+
+#define ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED	0x00010D84
+struct asm_stream_cmd_open_write_compressed {
+	struct apr_hdr hdr;
+	u32	flags;
+	u32	format;
+} __packed;
+
 #define ASM_STREAM_CMD_OPEN_READWRITE                    0x00010BCC
 
 struct asm_stream_cmd_open_read_write {
@@ -1069,6 +1083,15 @@
 	u32                read_format;
 } __attribute__((packed));
 
+#define ADM_CMD_CONNECT_AFE_PORT 0x00010320
+
+struct adm_cmd_connect_afe_port {
+	struct apr_hdr     hdr;
+	u8	mode; /*mode represent the interface is for RX or TX*/
+	u8	session_id; /*ASM session ID*/
+	u16	afe_port_id;
+} __packed;
+
 #define ASM_STREAM_CMD_SET_ENCDEC_PARAM                  0x00010C10
 #define ASM_STREAM_CMD_GET_ENCDEC_PARAM                  0x00010C11
 #define ASM_ENCDEC_CFG_BLK_ID				 0x00010C2C
diff --git a/include/sound/cs8427.h b/include/sound/cs8427.h
index cf7903a..2004ec3 100644
--- a/include/sound/cs8427.h
+++ b/include/sound/cs8427.h
@@ -209,6 +209,7 @@
 	int irq_base;
 	int num_irqs;
 	int reset_gpio;
+	int (*enable) (int enable);
 };
 
 struct snd_pcm_substream;
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index fe25d22..29fb606 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -40,6 +40,8 @@
 int adm_matrix_map(int session_id, int path, int num_copps,
 				unsigned int *port_id, int copp_id);
 
+int adm_connect_afe_port(int mode, int session_id, int port_id);
+
 #ifdef CONFIG_RTAC
 int adm_get_copp_id(int port_id);
 #endif
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 0fabc5b..c3d4bd5 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -43,6 +43,12 @@
 #define FORMAT_AMR_WB_PLUS  0x0010
 #define FORMAT_MPEG4_MULTI_AAC 0x0011
 #define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
+#define FORMAT_AC3	0x0013
+#define FORMAT_DTS	0x0014
+#define FORMAT_EAC3	0x0015
+#define FORMAT_ATRAC	0x0016
+#define FORMAT_MAT	0x0017
+#define FORMAT_AAC	0x0018
 
 #define ENCDEC_SBCBITRATE   0x0001
 #define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -175,6 +181,8 @@
 
 int q6asm_open_write(struct audio_client *ac, uint32_t format);
 
+int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format);
+
 int q6asm_open_read_write(struct audio_client *ac,
 			uint32_t rd_format,
 			uint32_t wr_format);
diff --git a/include/sound/snd_compress_params.h b/include/sound/snd_compress_params.h
index 5080e13..472d0ac 100644
--- a/include/sound/snd_compress_params.h
+++ b/include/sound/snd_compress_params.h
@@ -69,7 +69,9 @@
 #define SND_AUDIOCODEC_IEC61937              ((__u32) 0x0000000B)
 #define SND_AUDIOCODEC_G723_1                ((__u32) 0x0000000C)
 #define SND_AUDIOCODEC_G729                  ((__u32) 0x0000000D)
-
+#define SND_AUDIOCODEC_AC3		     ((__u32) 0x0000000E)
+#define SND_AUDIOCODEC_DTS		     ((__u32) 0x0000000F)
+#define SND_AUDIOCODEC_AC3_PASS_THROUGH		((__u32) 0x00000010)
 /*
  * Profile and modes are listed with bit masks. This allows for a
  * more compact representation of fields that will not evolve
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index de3ab22..3b5ad95 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -7539,6 +7539,17 @@
 			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
 			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
 					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+			if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+				result == L2CAP_CR_SUCCESS) {
+				char buf[128];
+				l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+				l2cap_send_cmd(conn, l2cap_get_ident(conn),
+					       L2CAP_CONF_REQ,
+					       l2cap_build_conf_req(sk, buf),
+					       buf);
+				l2cap_pi(sk)->num_conf_req++;
+			}
 		}
 
 		bh_unlock_sock(sk);
diff --git a/sound/soc/codecs/cs8427.c b/sound/soc/codecs/cs8427.c
index e63e4b4..aa6a9a7 100644
--- a/sound/soc/codecs/cs8427.c
+++ b/sound/soc/codecs/cs8427.c
@@ -649,6 +649,16 @@
 	struct cs8427_platform_data *pdata = chip->client->dev.platform_data;
 	int ret = 0;
 
+	/*enable the 100KHz level shifter*/
+	if (pdata->enable) {
+		ret = pdata->enable(1);
+		if (ret < 0) {
+			dev_err(&chip->client->dev,
+				"failed to enable the level shifter\n");
+			return ret;
+		}
+	}
+
 	ret = gpio_request(pdata->reset_gpio, "cs8427 reset");
 	if (ret < 0) {
 		dev_err(&chip->client->dev,
@@ -843,6 +853,8 @@
 	}
 	pdata = chip->client->dev.platform_data;
 	gpio_free(pdata->reset_gpio);
+	if (pdata->enable)
+		pdata->enable(0);
 	kfree(chip);
 	return 0;
 }
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index c9c8e25..3229bce 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -39,6 +39,17 @@
 #define NUM_DECIMATORS 4
 #define NUM_INTERPOLATORS 3
 #define BITS_PER_REG 8
+#define SITAR_CFILT_FAST_MODE 0x00
+#define SITAR_CFILT_SLOW_MODE 0x40
+#define MBHC_FW_READ_ATTEMPTS 15
+#define MBHC_FW_READ_TIMEOUT 2000000
+
+#define SITAR_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
+
+#define SITAR_I2S_MASTER_MODE_MASK 0x08
+
+#define SITAR_OCP_ATTEMPT 1
+
 #define AIF1_PB 1
 #define AIF1_CAP 2
 #define NUM_CODEC_DAIS 2
@@ -49,15 +60,12 @@
 	u32 ch_act;
 	u32 ch_tot;
 };
-#define SITAR_CFILT_FAST_MODE 0x00
-#define SITAR_CFILT_SLOW_MODE 0x40
 
+#define SITAR_MCLK_RATE_12288KHZ 12288000
+#define SITAR_MCLK_RATE_9600KHZ 9600000
 
-#define SITAR_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR)
-
-#define SITAR_I2S_MASTER_MODE_MASK 0x08
-
-#define SITAR_OCP_ATTEMPT 1
+#define SITAR_FAKE_INS_THRESHOLD_MS 2500
+#define SITAR_FAKE_REMOVAL_MIN_PERIOD_MS 50
 
 static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
 static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
@@ -109,8 +117,31 @@
 	SITAR_HPHR_DAC_OFF_ACK
 };
 
+/* Data used by MBHC */
+struct mbhc_internal_cal_data {
+	u16 dce_z;
+	u16 dce_mb;
+	u16 sta_z;
+	u16 sta_mb;
+	u32 t_sta_dce;
+	u32 t_dce;
+	u32 t_sta;
+	u32 micb_mv;
+	u16 v_ins_hu;
+	u16 v_ins_h;
+	u16 v_b1_hu;
+	u16 v_b1_h;
+	u16 v_b1_huc;
+	u16 v_brh;
+	u16 v_brl;
+	u16 v_no_mic;
+	u8 npoll;
+	u8 nbounce_wait;
+};
+
 struct sitar_priv {
 	struct snd_soc_codec *codec;
+	u32 mclk_freq;
 	u32 adc_count;
 	u32 cfilt1_cnt;
 	u32 cfilt2_cnt;
@@ -121,10 +152,20 @@
 	bool clock_active;
 	bool config_mode_active;
 	bool mbhc_polling_active;
-	bool fake_insert_context;
+	unsigned long mbhc_fake_ins_start;
 	int buttons_pressed;
 
-	struct sitar_mbhc_calibration *calibration;
+	enum sitar_micbias_num micbias;
+	/* void* calibration contains:
+	 *  struct sitar_mbhc_general_cfg generic;
+	 *  struct sitar_mbhc_plug_detect_cfg plug_det;
+	 *  struct sitar_mbhc_plug_type_cfg plug_type;
+	 *  struct sitar_mbhc_btn_detect_cfg btn_det;
+	 *  struct sitar_mbhc_imped_detect_cfg imped_det;
+	 * Note: various size depends on btn_det->num_btn
+	 */
+	void *calibration;
+	struct mbhc_internal_cal_data mbhc_data;
 
 	struct snd_soc_jack *headset_jack;
 	struct snd_soc_jack *button_jack;
@@ -154,13 +195,16 @@
 	struct work_struct hphlocp_work; /* reporting left hph ocp off */
 	struct work_struct hphrocp_work; /* reporting right hph ocp off */
 
-	/* pm_cnt holds number of sleep lock holders + 1
-	 * so if pm_cnt is 1 system is sleep-able. */
-	atomic_t pm_cnt;
-	wait_queue_head_t pm_wq;
-
 	u8 hphlocp_cnt; /* headphone left ocp retry */
 	u8 hphrocp_cnt; /* headphone right ocp retry */
+
+	/* Callback function to enable MCLK */
+	int (*mclk_cb) (struct snd_soc_codec*, int);
+
+	/* Work to perform MBHC Firmware Read */
+	struct delayed_work mbhc_firmware_dwork;
+	const struct firmware *mbhc_fw;
+
 	/* num of slim ports required */
 	struct sitar_codec_dai_data dai[NUM_CODEC_DAIS];
 };
@@ -419,9 +463,20 @@
 
 	SOC_SINGLE_S8_TLV("RX1 Digital Volume", SITAR_A_CDC_RX1_VOL_CTL_B2_CTL,
 		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX2 Digital Volume", SITAR_A_CDC_RX2_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
+	SOC_SINGLE_S8_TLV("RX3 Digital Volume", SITAR_A_CDC_RX3_VOL_CTL_B2_CTL,
+		-84, 40, digital_gain),
 
 	SOC_SINGLE_S8_TLV("DEC1 Volume", SITAR_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
 		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC2 Volume", SITAR_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC3 Volume", SITAR_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+	SOC_SINGLE_S8_TLV("DEC4 Volume", SITAR_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
+		digital_gain),
+
 	SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", SITAR_A_CDC_IIR1_GAIN_B1_CTL, -84,
 		40, digital_gain),
 	SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", SITAR_A_CDC_IIR1_GAIN_B2_CTL, -84,
@@ -432,6 +487,7 @@
 		40, digital_gain),
 	SOC_SINGLE_TLV("ADC1 Volume", SITAR_A_TX_1_2_EN, 5, 3, 0, analog_gain),
 	SOC_SINGLE_TLV("ADC2 Volume", SITAR_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+	SOC_SINGLE_TLV("ADC3 Volume", SITAR_A_TX_3_EN, 5, 3, 0, analog_gain),
 
 	SOC_SINGLE("MICBIAS1 CAPLESS Switch", SITAR_A_MICB_1_CTL, 4, 1, 1),
 	SOC_SINGLE("MICBIAS2 CAPLESS Switch", SITAR_A_MICB_2_CTL, 4, 1, 1),
@@ -501,7 +557,7 @@
 };
 
 static const char *rx_dac3_text[] = {
-	"ZERO", "RX1", "RX1_INV", "RX2"
+	"ZERO", "RX1", "INV_RX1", "RX2"
 };
 
 static const char *rx_dac4_text[] = {
@@ -523,6 +579,11 @@
 		"DEC3"
 };
 
+static const char *sb_tx4_mux_text[] = {
+	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+		"DEC4"
+};
+
 static const char *sb_tx5_mux_text[] = {
 	"ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
 		"DEC5"
@@ -582,6 +643,9 @@
 static const struct soc_enum sb_tx5_mux_enum =
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
 
+static const struct soc_enum sb_tx4_mux_enum =
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+
 static const struct soc_enum sb_tx3_mux_enum =
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
 
@@ -595,13 +659,13 @@
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 0, 8, dec1_mux_text);
 
 static const struct soc_enum dec2_mux_enum =
-	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 2, 8, dec2_mux_text);
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 3, 8, dec2_mux_text);
 
 static const struct soc_enum dec3_mux_enum =
-	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 4, 8, dec3_mux_text);
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B2_CTL, 0, 8, dec3_mux_text);
 
 static const struct soc_enum dec4_mux_enum =
-	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B1_CTL, 6, 8, dec4_mux_text);
+	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_TX_B2_CTL, 3, 8, dec4_mux_text);
 
 static const struct soc_enum iir1_inp1_mux_enum =
 	SOC_ENUM_SINGLE(SITAR_A_CDC_CONN_EQ1_B1_CTL, 0, 16, iir1_inp1_text);
@@ -625,20 +689,23 @@
 	SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
 
 static const struct snd_kcontrol_new rx_dac1_mux =
-	SOC_DAPM_ENUM("RX1 DAC Mux", rx_dac1_enum);
+	SOC_DAPM_ENUM("RX DAC1 Mux", rx_dac1_enum);
 
 static const struct snd_kcontrol_new rx_dac2_mux =
-	SOC_DAPM_ENUM("RX2 DAC Mux", rx_dac2_enum);
+	SOC_DAPM_ENUM("RX DAC2 Mux", rx_dac2_enum);
 
 static const struct snd_kcontrol_new rx_dac3_mux =
-	SOC_DAPM_ENUM("RX3 DAC Mux", rx_dac3_enum);
+	SOC_DAPM_ENUM("RX DAC3 Mux", rx_dac3_enum);
 
 static const struct snd_kcontrol_new rx_dac4_mux =
-	SOC_DAPM_ENUM("RX4 DAC Mux", rx_dac4_enum);
+	SOC_DAPM_ENUM("RX DAC4 Mux", rx_dac4_enum);
 
 static const struct snd_kcontrol_new sb_tx5_mux =
 	SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
 
+static const struct snd_kcontrol_new sb_tx4_mux =
+	SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
+
 static const struct snd_kcontrol_new sb_tx3_mux =
 	SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
 
@@ -726,6 +793,25 @@
 	return 0;
 }
 
+static int sitar_lineout_dac_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+
+	pr_debug("%s %s %d\n", __func__, w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+		break;
+	}
+	return 0;
+}
+
 static int sitar_codec_enable_lineout(struct snd_soc_dapm_widget *w,
 		struct snd_kcontrol *kcontrol, int event)
 {
@@ -749,7 +835,7 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x10);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		pr_err("%s: sleeping 16 ms after %s PA turn on\n",
@@ -757,7 +843,7 @@
 		usleep_range(16000, 16000);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+		snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x00);
 		break;
 	}
 	return 0;
@@ -767,7 +853,7 @@
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
+	u16 tx_dmic_ctl_reg, tx_mux_ctl_reg;
 	u8 dmic_clk_sel, dmic_clk_en;
 	unsigned int dmic;
 	int ret;
@@ -804,7 +890,7 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x01, 0x01);
 
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
 				dmic_clk_sel, dmic_clk_sel);
@@ -817,6 +903,8 @@
 	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_DMIC_CTL,
 				dmic_clk_en, 0);
+
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x01, 0x00);
 		break;
 	}
 	return 0;
@@ -843,6 +931,9 @@
 	} else {
 		sitar_codec_disable_button_presses(codec);
 	}
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x1);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x1);
 }
 
 static void sitar_codec_pause_hs_polling(struct snd_soc_codec *codec)
@@ -1089,7 +1180,7 @@
 				&& sitar->mbhc_micbias_switched)
 			sitar_codec_switch_micbias(codec, 0);
 
-		snd_soc_update_bits(codec, w->reg, 0x1E, 0x0A);
+		snd_soc_update_bits(codec, w->reg, 0x1E, 0x00);
 		sitar_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
 
 		if (strnstr(w->name, internal1_text, 30))
@@ -1099,7 +1190,7 @@
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		if (sitar->mbhc_polling_active &&
-			(sitar->calibration->bias == micb_line)) {
+		    sitar->micbias == micb_line) {
 			sitar_codec_pause_hs_polling(codec);
 			sitar_codec_start_hs_polling(codec);
 		}
@@ -1338,10 +1429,9 @@
 		struct mbhc_micbias_regs *micbias_regs)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	struct sitar_mbhc_calibration *calibration = sitar->calibration;
 	unsigned int cfilt;
 
-	switch (calibration->bias) {
+	switch (sitar->micbias) {
 	case SITAR_MICBIAS1:
 		cfilt = sitar->pdata->micbias.bias1_cfilt_sel;
 		micbias_regs->mbhc_reg = SITAR_A_MICB_1_MBHC;
@@ -1366,10 +1456,12 @@
 	case SITAR_CFILT1_SEL:
 		micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_1_VAL;
 		micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_1_CTL;
+		sitar->mbhc_data.micb_mv = sitar->pdata->micbias.cfilt1_mv;
 		break;
 	case SITAR_CFILT2_SEL:
 		micbias_regs->cfilt_val = SITAR_A_MICB_CFILT_2_VAL;
 		micbias_regs->cfilt_ctl = SITAR_A_MICB_CFILT_2_CTL;
+		sitar->mbhc_data.micb_mv = sitar->pdata->micbias.cfilt2_mv;
 		break;
 	}
 }
@@ -1448,6 +1540,13 @@
 	SND_SOC_DAPM_OUTPUT("LINEOUT1"),
 	SND_SOC_DAPM_OUTPUT("LINEOUT2"),
 
+	SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, SITAR_A_RX_LINE_1_DAC_CTL, 7, 0
+		, sitar_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, SITAR_A_RX_LINE_2_DAC_CTL, 7, 0
+		, sitar_lineout_dac_event,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_PGA_E("LINEOUT1 PA", SITAR_A_RX_LINE_CNP_EN, 0, 0, NULL,
 			0, sitar_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
 			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -1498,9 +1597,12 @@
 	SND_SOC_DAPM_SUPPLY("LDO_H", SITAR_A_LDO_H_MODE_1, 7, 0,
 		sitar_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
 	/* TX */
+
 	SND_SOC_DAPM_SUPPLY("CDC_CONN", SITAR_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
 		0),
 	SND_SOC_DAPM_INPUT("AMIC1"),
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_INPUT("AMIC3"),
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", SITAR_A_MICB_1_CTL, 7, 0,
 		sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -1508,7 +1610,6 @@
 		sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
-	SND_SOC_DAPM_INPUT("AMIC2"),
 	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", SITAR_A_MICB_2_CTL, 7, 0,
 		sitar_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -1525,13 +1626,23 @@
 	SND_SOC_DAPM_ADC_E("ADC2", NULL, SITAR_A_TX_1_2_EN, 3, 0,
 		sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_ADC_E("ADC3", NULL, SITAR_A_TX_3_EN, 7, 0,
+		sitar_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC1 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
 		&dec1_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+		&dec2_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+		&dec3_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+		&dec4_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
 
 	SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
 	SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
 	SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
+	SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, 0, 0, &sb_tx4_mux),
 
 	SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
 				0, sitar_codec_enable_slimtx,
@@ -1544,12 +1655,9 @@
 	SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
 				0, sitar_codec_enable_slimtx,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
-		&dec2_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
-		&dec3_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
-		&dec4_mux, sitar_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+	SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+				0, sitar_codec_enable_slimtx,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	/* Digital Mic Inputs */
 	SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
@@ -1558,11 +1666,9 @@
 	SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
 		sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
-
 	SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
 		sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
-
 	SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
 		sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
@@ -1581,35 +1687,40 @@
 	{"DAC1", NULL, "CP"},
 	{"DAC1", NULL, "EAR DRIVER"},
 
-	{"LINEOUT1", NULL, "CP"},
-	{"LINEOUT2", NULL, "CP"},
+	{"CP", NULL, "RX_BIAS"},
+
+	{"LINEOUT1 DAC", NULL, "RX_BIAS"},
+	{"LINEOUT2 DAC", NULL, "RX_BIAS"},
 
 	{"LINEOUT2", NULL, "LINEOUT2 PA"},
-	{"LINEOUT2 PA", "NULL", "DAC3 MUX"},
+	{"LINEOUT2 PA", NULL, "LINEOUT2 DAC"},
+	{"LINEOUT2 DAC", NULL, "DAC3 MUX"},
 
 	{"LINEOUT1", NULL, "LINEOUT1 PA"},
-	{"LINEOUT1 PA", "NULL", "DAC2 MUX"},
+	{"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
+	{"LINEOUT1 DAC", NULL, "DAC2 MUX"},
+
 
 	/* Headset (RX MIX1 and RX MIX2) */
 	{"HEADPHONE", NULL, "HPHL"},
 	{"HEADPHONE", NULL, "HPHR"},
 
 	{"HPHL", NULL, "HPHL DAC"},
-	{"HPHL DAC", NULL, "DAC4 MUX"},
+	{"HPHL DAC", "Switch", "DAC4 MUX"},
 	{"HPHR", NULL, "HPHR DAC"},
-	{"HPHL DAC", NULL, "RX3 MIX1"},
+	{"HPHR DAC", NULL, "RX3 MIX1"},
 
 	{"DAC1 MUX", "RX1", "RX1 CHAIN"},
 	{"DAC2 MUX", "RX1", "RX1 CHAIN"},
+
 	{"DAC3 MUX", "RX1", "RX1 CHAIN"},
-	{"DAC3 MUX", "RX1_INV", "RX1 CHAIN"},
+	{"DAC3 MUX", "INV_RX1", "RX1 CHAIN"},
 	{"DAC3 MUX", "RX2", "RX2 MIX1"},
+
 	{"DAC4 MUX", "ON", "RX2 MIX1"},
 
 	{"RX1 CHAIN", NULL, "RX1 MIX1"},
 
-	{"CP", NULL, "RX_BIAS"},
-
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 	{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
 	{"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
@@ -1654,46 +1765,48 @@
 
 	/* TX */
 	{"SLIM TX1", NULL, "SLIM TX1 MUX"},
-	{"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
-
-	{"SLIM TX2", NULL, "SLIM TX2 MUX"},
-	{"MIC BIAS2 Internal1", NULL, "DEC1 MUX"},
-
-	{"SLIM TX1", NULL, "SLIM TX1 MUX"},
 	{"SLIM TX2", NULL, "SLIM TX2 MUX"},
 	{"SLIM TX3", NULL, "SLIM TX3 MUX"},
+	{"SLIM TX4", NULL, "SLIM TX4 MUX"},
 
 	{"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
 	{"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
 	{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+	{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
 
 	/* Decimator Inputs */
 	{"DEC1 MUX", "DMIC1", "DMIC1"},
 	{"DEC1 MUX", "DMIC4", "DMIC4"},
 	{"DEC1 MUX", "ADC1", "ADC1"},
 	{"DEC1 MUX", "ADC2", "ADC2"},
-
+	{"DEC1 MUX", "ADC3", "ADC3"},
+	{"DEC1 MUX", NULL, "CDC_CONN"},
 	{"DEC2 MUX", "DMIC2", "DMIC2"},
 	{"DEC2 MUX", "DMIC3", "DMIC3"},
 	{"DEC2 MUX", "ADC1", "ADC1"},
 	{"DEC2 MUX", "ADC2", "ADC2"},
-
+	{"DEC2 MUX", "ADC3", "ADC3"},
+	{"DEC2 MUX", NULL, "CDC_CONN"},
 	{"DEC3 MUX", "DMIC3", "DMIC3"},
 	{"DEC3 MUX", "ADC1", "ADC1"},
 	{"DEC3 MUX", "ADC2", "ADC2"},
+	{"DEC3 MUX", "ADC3", "ADC3"},
 	{"DEC3 MUX", "DMIC2", "DMIC2"},
 	{"DEC3 MUX", "DMIC3", "DMIC4"},
-
+	{"DEC3 MUX", NULL, "CDC_CONN"},
 	{"DEC4 MUX", "DMIC4", "DMIC4"},
 	{"DEC4 MUX", "ADC1", "ADC1"},
 	{"DEC4 MUX", "ADC2", "ADC2"},
+	{"DEC4 MUX", "ADC3", "ADC3"},
 	{"DEC4 MUX", "DMIC3", "DMIC3"},
 	{"DEC4 MUX", "DMIC2", "DMIC2"},
 	{"DEC4 MUX", "DMIC1", "DMIC1"},
+	{"DEC4 MUX", NULL, "CDC_CONN"},
 
 	/* ADC Connections */
 	{"ADC1", NULL, "AMIC1"},
 	{"ADC2", NULL, "AMIC2"},
+	{"ADC3", NULL, "AMIC3"},
 
 	/* IIR */
 	{"IIR1", NULL, "IIR1 INP1 MUX"},
@@ -1768,8 +1881,9 @@
 static void sitar_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
 {
 
-	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x0C, 0x61);
+	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x0C, 0x04);
 	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CURR_CTL_2, 0x0C, 0x08);
 	usleep_range(1000, 1000);
 	snd_soc_write(codec, SITAR_A_BIAS_REF_CTL, 0x1C);
 	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x80,
@@ -1819,13 +1933,43 @@
 		usleep_range(100, 100);
 		sitar_codec_enable_audio_mode_bandgap(codec);
 	} else if (choice == SITAR_BANDGAP_OFF) {
+		snd_soc_update_bits(codec, SITAR_A_BIAS_CURR_CTL_2, 0x0C, 0x00);
 		snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
+		snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0xFF, 0x65);
+		usleep_range(1000, 1000);
 	} else {
 		pr_err("%s: Error, Invalid bandgap settings\n", __func__);
 	}
 	sitar->bandgap_type = choice;
 }
 
+static int sitar_codec_enable_config_mode(struct snd_soc_codec *codec,
+	int enable)
+{
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	if (enable) {
+		snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x10, 0);
+		snd_soc_write(codec, SITAR_A_BIAS_OSC_BG_CTL, 0x17);
+		usleep_range(5, 5);
+		snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x80,
+			0x80);
+		snd_soc_update_bits(codec, SITAR_A_RC_OSC_TEST, 0x80,
+			0x80);
+		usleep_range(10, 10);
+		snd_soc_update_bits(codec, SITAR_A_RC_OSC_TEST, 0x80, 0);
+		usleep_range(20, 20);
+		snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x08);
+	} else {
+		snd_soc_update_bits(codec, SITAR_A_BIAS_OSC_BG_CTL, 0x1,
+			0);
+		snd_soc_update_bits(codec, SITAR_A_RC_OSC_FREQ, 0x80, 0);
+		snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
+	}
+	sitar->config_mode_active = enable ? true : false;
+
+	return 0;
+}
 
 static int sitar_codec_enable_clock_block(struct snd_soc_codec *codec,
 	int config_mode)
@@ -1835,6 +1979,7 @@
 	pr_err("%s\n", __func__);
 
 	if (config_mode) {
+		sitar_codec_enable_config_mode(codec, 1);
 		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x00);
 		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
 		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN1, 0x0D);
@@ -1842,12 +1987,16 @@
 	} else
 		snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x08, 0x00);
 
+	if (!config_mode && sitar->mbhc_polling_active) {
+		snd_soc_write(codec, SITAR_A_CLK_BUFF_EN2, 0x02);
+		sitar_codec_enable_config_mode(codec, 0);
+
+	}
 
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN1, 0x05, 0x05);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x04);
 	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
 	usleep_range(50, 50);
 	sitar->clock_active = true;
 	return 0;
@@ -1856,7 +2005,7 @@
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	pr_err("%s\n", __func__);
-	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL, 0x04, 0x04);
+	snd_soc_update_bits(codec, SITAR_A_CDC_CLK_MCLK_CTL, 0x01, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
 	ndelay(160);
 	snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -1864,26 +2013,61 @@
 	sitar->clock_active = false;
 }
 
+static int sitar_codec_mclk_index(const struct sitar_priv *sitar)
+{
+	if (sitar->mclk_freq == SITAR_MCLK_RATE_12288KHZ)
+		return 0;
+	else if (sitar->mclk_freq == SITAR_MCLK_RATE_9600KHZ)
+		return 1;
+	else {
+		BUG_ON(1);
+		return -EINVAL;
+	}
+}
+
 static void sitar_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
 {
-	/* TODO store register values in calibration */
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B5_CTL, 0x20);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B6_CTL, 0xFF);
+	u8 *n_ready, *n_cic;
+	struct sitar_mbhc_btn_detect_cfg *btn_det;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B10_CTL, 0xFF);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B9_CTL, 0x20);
+	btn_det = SITAR_MBHC_CAL_BTN_DET_PTR(sitar->calibration);
 
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL, 0xF8);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL, 0xEE);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B2_CTL, 0xFC);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B1_CTL, 0xCE);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B1_CTL,
+		      sitar->mbhc_data.v_ins_hu & 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B2_CTL,
+		      (sitar->mbhc_data.v_ins_hu >> 8) & 0xFF);
 
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 3);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B2_CTL, 9);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B3_CTL, 30);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B6_CTL, 120);
-	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL, 0x78, 0x58);
-	snd_soc_write(codec, SITAR_A_CDC_MBHC_B2_CTL, 11);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B3_CTL,
+		      sitar->mbhc_data.v_b1_hu & 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B4_CTL,
+		      (sitar->mbhc_data.v_b1_hu >> 8) & 0xFF);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B5_CTL,
+		      sitar->mbhc_data.v_b1_h & 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B6_CTL,
+		      (sitar->mbhc_data.v_b1_h >> 8) & 0xFF);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B9_CTL,
+		      sitar->mbhc_data.v_brh & 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B10_CTL,
+		      (sitar->mbhc_data.v_brh >> 8) & 0xFF);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B11_CTL,
+		      sitar->mbhc_data.v_brl & 0xFF);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_VOLT_B12_CTL,
+		      (sitar->mbhc_data.v_brl >> 8) & 0xFF);
+
+	n_ready = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_N_READY);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B1_CTL,
+		      n_ready[sitar_codec_mclk_index(sitar)]);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B2_CTL,
+		      sitar->mbhc_data.npoll);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B3_CTL,
+		      sitar->mbhc_data.nbounce_wait);
+	n_cic = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_N_CIC);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B6_CTL,
+		      n_cic[sitar_codec_mclk_index(sitar)]);
 }
 
 static int sitar_startup(struct snd_pcm_substream *substream,
@@ -2064,7 +2248,7 @@
 	} else if (dai->id == AIF1_CAP) {
 		*tx_num = sitar_dai[dai->id - 1].capture.channels_max;
 		while (cnt < *tx_num) {
-			tx_slot[cnt] = tx_ch[6 + cnt];
+			tx_slot[cnt] = tx_ch[cnt];
 			cnt++;
 		}
 	}
@@ -2374,42 +2558,49 @@
 	return bias_value;
 }
 
-static short sitar_codec_measure_micbias_voltage(struct snd_soc_codec *codec,
-	int dce)
+static short sitar_codec_sta_dce(struct snd_soc_codec *codec, int dce)
 {
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	short bias_value;
 
+	/* Turn on the override */
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
 	if (dce) {
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+		usleep_range(sitar->mbhc_data.t_sta_dce,
+			     sitar->mbhc_data.t_sta_dce);
 		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x4);
-		usleep_range(60000, 60000);
+		usleep_range(sitar->mbhc_data.t_dce,
+			     sitar->mbhc_data.t_dce);
 		bias_value = sitar_codec_read_dce_result(codec);
 	} else {
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
-		usleep_range(5000, 5000);
+		usleep_range(sitar->mbhc_data.t_sta_dce,
+			     sitar->mbhc_data.t_sta_dce);
 		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x2);
-		usleep_range(50, 50);
+		usleep_range(sitar->mbhc_data.t_sta,
+			     sitar->mbhc_data.t_sta);
 		bias_value = sitar_codec_read_sta_result(codec);
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 		snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x0);
 	}
+	/* Turn off the override after measuring mic voltage */
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
 
-	pr_err("read microphone bias value %x\n", bias_value);
 	return bias_value;
 }
 
 static short sitar_codec_setup_hs_polling(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	struct sitar_mbhc_calibration *calibration = sitar->calibration;
 	short bias_value;
 	u8 cfilt_mode;
 
-	if (!calibration) {
+	if (!sitar->calibration) {
 		pr_err("Error, no sitar calibration\n");
 		return -ENODEV;
 	}
@@ -2432,23 +2623,25 @@
 	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
 		0x70, 0x00);
 
-	snd_soc_update_bits(codec,
-		sitar->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
-
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
 	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
 
+	snd_soc_update_bits(codec, SITAR_A_TX_4_MBHC_EN, 0x80, 0x80);
+	snd_soc_update_bits(codec, SITAR_A_TX_4_MBHC_EN, 0x1F, 0x1C);
+	snd_soc_update_bits(codec, SITAR_A_TX_4_MBHC_TEST_CTL, 0x40, 0x40);
+
+	snd_soc_update_bits(codec, SITAR_A_TX_4_MBHC_EN, 0x80, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
 
-	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x6);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
 
 	sitar_codec_calibrate_hs_polling(codec);
 
-	bias_value = sitar_codec_measure_micbias_voltage(codec, 0);
-	snd_soc_update_bits(codec,
-		sitar->mbhc_bias_regs.cfilt_ctl, 0x40, cfilt_mode);
+	bias_value = sitar_codec_sta_dce(codec, 0);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl, 0x40,
+			    cfilt_mode);
 	snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x13, 0x00);
 
 	return bias_value;
@@ -2458,11 +2651,14 @@
 		int insertion)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	struct sitar_mbhc_calibration *calibration = sitar->calibration;
 	int central_bias_enabled = 0;
+	const struct sitar_mbhc_general_cfg *generic =
+	    SITAR_MBHC_CAL_GENERAL_PTR(sitar->calibration);
+	const struct sitar_mbhc_plug_detect_cfg *plug_det =
+	    SITAR_MBHC_CAL_PLUG_DET_PTR(sitar->calibration);
 	u8 wg_time;
 
-	if (!calibration) {
+	if (!sitar->calibration) {
 		pr_err("Error, no sitar calibration\n");
 		return -EINVAL;
 	}
@@ -2483,7 +2679,7 @@
 		/* Enable HPH Schmitt Trigger */
 		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x11, 0x11);
 		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x0C,
-			calibration->hph_current << 2);
+			plug_det->hph_current << 2);
 
 		/* Turn off HPH PAs and DAC's during insertion detection to
 		* avoid false insertion interrupts
@@ -2506,10 +2702,10 @@
 
 		/* enable the mic line schmitt trigger */
 		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg, 0x60,
-			calibration->mic_current << 5);
+			plug_det->mic_current << 5);
 		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
 			0x80, 0x80);
-		usleep_range(calibration->mic_pid, calibration->mic_pid);
+		usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
 		snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg,
 			0x10, 0x10);
 
@@ -2519,10 +2715,12 @@
 
 	if (snd_soc_read(codec, SITAR_A_CDC_MBHC_B1_CTL) & 0x4) {
 		if (!(sitar->clock_active)) {
+			sitar_codec_enable_config_mode(codec, 1);
 			snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
 				0x06, 0);
-			usleep_range(calibration->shutdown_plug_removal,
-				calibration->shutdown_plug_removal);
+			usleep_range(generic->t_shutdown_plug_rem,
+				generic->t_shutdown_plug_rem);
+			sitar_codec_enable_config_mode(codec, 0);
 		} else
 			snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL,
 				0x06, 0);
@@ -2533,8 +2731,8 @@
 	/* If central bandgap disabled */
 	if (!(snd_soc_read(codec, SITAR_A_PIN_CTL_OE1) & 1)) {
 		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE1, 0x3, 0x3);
-		usleep_range(calibration->bg_fast_settle,
-			calibration->bg_fast_settle);
+		usleep_range(generic->t_bg_fast_settle,
+			generic->t_bg_fast_settle);
 		central_bias_enabled = 1;
 	}
 
@@ -2542,7 +2740,7 @@
 	if (snd_soc_read(codec, SITAR_A_PIN_CTL_OE0) & 0x80) {
 		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x10, 0);
 		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0x80);
-		usleep_range(calibration->tldoh, calibration->tldoh);
+		usleep_range(generic->t_ldoh, generic->t_ldoh);
 		snd_soc_update_bits(codec, SITAR_A_PIN_CTL_OE0, 0x80, 0);
 
 		if (central_bias_enabled)
@@ -2554,23 +2752,82 @@
 	return 0;
 }
 
+static u16 sitar_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
+				 s16 vin_mv)
+{
+	short diff, zero;
+	struct sitar_priv *sitar;
+	u32 mb_mv, in;
+
+	sitar = snd_soc_codec_get_drvdata(codec);
+	mb_mv = sitar->mbhc_data.micb_mv;
+
+	if (mb_mv == 0) {
+		pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
+		return -EINVAL;
+	}
+
+	if (dce) {
+		diff = sitar->mbhc_data.dce_mb - sitar->mbhc_data.dce_z;
+		zero = sitar->mbhc_data.dce_z;
+	} else {
+		diff = sitar->mbhc_data.sta_mb - sitar->mbhc_data.sta_z;
+		zero = sitar->mbhc_data.sta_z;
+	}
+	in = (u32) diff * vin_mv;
+
+	return (u16) (in / mb_mv) + zero;
+}
+
+static s32 sitar_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
+				 u16 bias_value)
+{
+	struct sitar_priv *sitar;
+	s32 mv;
+
+	sitar = snd_soc_codec_get_drvdata(codec);
+
+	if (dce) {
+		mv = ((s32)bias_value - (s32)sitar->mbhc_data.dce_z) *
+		     (s32)sitar->mbhc_data.micb_mv /
+		     (s32)(sitar->mbhc_data.dce_mb - sitar->mbhc_data.dce_z);
+	} else {
+		mv = ((s32)bias_value - (s32)sitar->mbhc_data.sta_z) *
+		     (s32)sitar->mbhc_data.micb_mv /
+		     (s32)(sitar->mbhc_data.sta_mb - sitar->mbhc_data.sta_z);
+	}
+
+	return mv;
+}
+
 static void btn0_lpress_fn(struct work_struct *work)
 {
 	struct delayed_work *delayed_work;
 	struct sitar_priv *sitar;
+	short bias_value;
+	int dce_mv, sta_mv;
+	struct sitar *core;
 
-	pr_err("%s:\n", __func__);
+	pr_debug("%s:\n", __func__);
 
 	delayed_work = to_delayed_work(work);
 	sitar = container_of(delayed_work, struct sitar_priv, btn0_dwork);
+	core = dev_get_drvdata(sitar->codec->dev->parent);
 
 	if (sitar) {
 		if (sitar->button_jack) {
-			pr_err("%s: Reporting long button press event\n",
-					__func__);
+			bias_value = sitar_codec_read_sta_result(sitar->codec);
+			sta_mv = sitar_codec_sta_dce_v(sitar->codec, 0,
+						bias_value);
+			bias_value = sitar_codec_read_dce_result(sitar->codec);
+			dce_mv = sitar_codec_sta_dce_v(sitar->codec, 1,
+						bias_value);
+			pr_debug("%s: Reporting long button press event"
+				 " STA: %d, DCE: %d\n", __func__,
+				 sta_mv, dce_mv);
 			sitar_snd_soc_jack_report(sitar, sitar->button_jack,
-						 SND_JACK_BTN_0,
-						 SND_JACK_BTN_0);
+						  SND_JACK_BTN_0,
+						  SND_JACK_BTN_0);
 		}
 	} else {
 		pr_err("%s: Bad sitar private data\n", __func__);
@@ -2578,31 +2835,361 @@
 
 }
 
-int sitar_hs_detect(struct snd_soc_codec *codec,
-	struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
-	struct sitar_mbhc_calibration *calibration)
+void sitar_mbhc_cal(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar;
-	int rc;
+	struct sitar_mbhc_btn_detect_cfg *btn_det;
+	u8 cfilt_mode, bg_mode;
+	u8 ncic, nmeas, navg;
+	u32 mclk_rate;
+	u32 dce_wait, sta_wait;
+	u8 *n_cic;
+
+	sitar = snd_soc_codec_get_drvdata(codec);
+
+	/* First compute the DCE / STA wait times
+	 * depending on tunable parameters.
+	 * The value is computed in microseconds
+	 */
+	btn_det = SITAR_MBHC_CAL_BTN_DET_PTR(sitar->calibration);
+	n_cic = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_N_CIC);
+	ncic = n_cic[sitar_codec_mclk_index(sitar)];
+	nmeas = SITAR_MBHC_CAL_BTN_DET_PTR(sitar->calibration)->n_meas;
+	navg = SITAR_MBHC_CAL_GENERAL_PTR(sitar->calibration)->mbhc_navg;
+	mclk_rate = sitar->mclk_freq;
+	dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (mclk_rate / 1000);
+	sta_wait = (1000 * 128 * (navg + 1)) / (mclk_rate / 1000);
+
+	sitar->mbhc_data.t_dce = dce_wait;
+	sitar->mbhc_data.t_sta = sta_wait;
+
+	/* LDOH and CFILT are already configured during pdata handling.
+	 * Only need to make sure CFILT and bandgap are in Fast mode.
+	 * Need to restore defaults once calculation is done.
+	 */
+	cfilt_mode = snd_soc_read(codec, sitar->mbhc_bias_regs.cfilt_ctl);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
+	bg_mode = snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x02,
+				      0x02);
+
+	/* Micbias, CFILT, LDOH, MBHC MUX mode settings
+	 * to perform ADC calibration
+	 */
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.ctl_reg, 0x60,
+			    sitar->micbias << 5);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+	snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x60, 0x60);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
+
+	/* DCE measurement for 0 volts */
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x04);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x81);
+	usleep_range(100, 100);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x04);
+	usleep_range(sitar->mbhc_data.t_dce, sitar->mbhc_data.t_dce);
+	sitar->mbhc_data.dce_z = sitar_codec_read_dce_result(codec);
+
+	/* DCE measurment for MB voltage */
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x82);
+	usleep_range(100, 100);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x04);
+	usleep_range(sitar->mbhc_data.t_dce, sitar->mbhc_data.t_dce);
+	sitar->mbhc_data.dce_mb = sitar_codec_read_dce_result(codec);
+
+	/* Sta measuremnt for 0 volts */
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x0A);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x02);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x02);
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x81);
+	usleep_range(100, 100);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x02);
+	usleep_range(sitar->mbhc_data.t_sta, sitar->mbhc_data.t_sta);
+	sitar->mbhc_data.sta_z = sitar_codec_read_sta_result(codec);
+
+	/* STA Measurement for MB Voltage */
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x82);
+	usleep_range(100, 100);
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_EN_CTL, 0x02);
+	usleep_range(sitar->mbhc_data.t_sta, sitar->mbhc_data.t_sta);
+	sitar->mbhc_data.sta_mb = sitar_codec_read_sta_result(codec);
+
+	/* Restore default settings. */
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl, 0x40,
+			    cfilt_mode);
+	snd_soc_update_bits(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
+
+	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x84);
+	usleep_range(100, 100);
+}
+
+void *sitar_mbhc_cal_btn_det_mp(const struct sitar_mbhc_btn_detect_cfg* btn_det,
+				const enum sitar_mbhc_btn_det_mem mem)
+{
+	void *ret = &btn_det->_v_btn_low;
+
+	switch (mem) {
+	case SITAR_BTN_DET_GAIN:
+		ret += sizeof(btn_det->_n_cic);
+	case SITAR_BTN_DET_N_CIC:
+		ret += sizeof(btn_det->_n_ready);
+	case SITAR_BTN_DET_N_READY:
+		ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
+	case SITAR_BTN_DET_V_BTN_HIGH:
+		ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
+	case SITAR_BTN_DET_V_BTN_LOW:
+		/* do nothing */
+		break;
+	default:
+		ret = NULL;
+	}
+
+	return ret;
+}
+
+static void sitar_mbhc_calc_thres(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar;
+	s16 btn_mv = 0, btn_delta_mv;
+	struct sitar_mbhc_btn_detect_cfg *btn_det;
+	struct sitar_mbhc_plug_type_cfg *plug_type;
+	u16 *btn_high;
+	u8 *n_ready;
+	int i;
+
+	sitar = snd_soc_codec_get_drvdata(codec);
+	btn_det = SITAR_MBHC_CAL_BTN_DET_PTR(sitar->calibration);
+	plug_type = SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar->calibration);
+
+	n_ready = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_N_READY);
+	if (sitar->mclk_freq == SITAR_MCLK_RATE_12288KHZ) {
+		sitar->mbhc_data.npoll = 9;
+		sitar->mbhc_data.nbounce_wait = 30;
+	} else if (sitar->mclk_freq == SITAR_MCLK_RATE_9600KHZ) {
+		sitar->mbhc_data.npoll = 7;
+		sitar->mbhc_data.nbounce_wait = 23;
+	}
+
+	sitar->mbhc_data.t_sta_dce = ((1000 * 256) / (sitar->mclk_freq / 1000) *
+				      n_ready[sitar_codec_mclk_index(sitar)]) +
+				     10;
+	sitar->mbhc_data.v_ins_hu =
+	    sitar_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
+	sitar->mbhc_data.v_ins_h =
+	    sitar_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
+
+	btn_high = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_V_BTN_HIGH);
+	for (i = 0; i < btn_det->num_btn; i++)
+		btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
+
+	sitar->mbhc_data.v_b1_h = sitar_codec_v_sta_dce(codec, DCE, btn_mv);
+	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
+
+	sitar->mbhc_data.v_b1_hu =
+	    sitar_codec_v_sta_dce(codec, STA, btn_delta_mv);
+
+	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
+
+	sitar->mbhc_data.v_b1_huc =
+	    sitar_codec_v_sta_dce(codec, DCE, btn_delta_mv);
+
+	sitar->mbhc_data.v_brh = sitar->mbhc_data.v_b1_h;
+	sitar->mbhc_data.v_brl = 0xFA55;
+
+	sitar->mbhc_data.v_no_mic =
+	    sitar_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
+}
+
+void sitar_mbhc_init(struct snd_soc_codec *codec)
+{
+	struct sitar_priv *sitar;
+	struct sitar_mbhc_general_cfg *generic;
+	struct sitar_mbhc_btn_detect_cfg *btn_det;
+	int n;
+	u8 *n_cic, *gain;
+
+	sitar = snd_soc_codec_get_drvdata(codec);
+	generic = SITAR_MBHC_CAL_GENERAL_PTR(sitar->calibration);
+	btn_det = SITAR_MBHC_CAL_BTN_DET_PTR(sitar->calibration);
+
+	for (n = 0; n < 8; n++) {
+		if (n != 7) {
+			snd_soc_update_bits(codec,
+					    SITAR_A_CDC_MBHC_FIR_B1_CFG,
+					    0x07, n);
+			snd_soc_write(codec, SITAR_A_CDC_MBHC_FIR_B2_CFG,
+				      btn_det->c[n]);
+		}
+	}
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B2_CTL, 0x07,
+			    btn_det->nc);
+
+	n_cic = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_N_CIC);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
+			    n_cic[sitar_codec_mclk_index(sitar)]);
+
+	gain = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_GAIN);
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B2_CTL, 0x78,
+			    gain[sitar_codec_mclk_index(sitar)] << 3);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
+			    generic->mbhc_nsa << 4);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
+			    btn_det->n_meas);
+
+	snd_soc_write(codec, SITAR_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x78,
+			    btn_det->mbhc_nsc << 3);
+
+	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
+}
+
+static bool sitar_mbhc_fw_validate(const struct firmware *fw)
+{
+	u32 cfg_offset;
+	struct sitar_mbhc_imped_detect_cfg *imped_cfg;
+	struct sitar_mbhc_btn_detect_cfg *btn_cfg;
+
+	if (fw->size < SITAR_MBHC_CAL_MIN_SIZE)
+		return false;
+
+	/* previous check guarantees that there is enough fw data up
+	 * to num_btn
+	 */
+	btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(fw->data);
+	cfg_offset = (u32) ((void *) btn_cfg - (void *) fw->data);
+	if (fw->size < (cfg_offset + SITAR_MBHC_CAL_BTN_SZ(btn_cfg)))
+		return false;
+
+	/* previous check guarantees that there is enough fw data up
+	 * to start of impedance detection configuration
+	 */
+	imped_cfg = SITAR_MBHC_CAL_IMPED_DET_PTR(fw->data);
+	cfg_offset = (u32) ((void *) imped_cfg - (void *) fw->data);
+
+	if (fw->size < (cfg_offset + SITAR_MBHC_CAL_IMPED_MIN_SZ))
+		return false;
+
+	if (fw->size < (cfg_offset + SITAR_MBHC_CAL_IMPED_SZ(imped_cfg)))
+		return false;
+
+	return true;
+}
+static void mbhc_fw_read(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct sitar_priv *sitar;
+	struct snd_soc_codec *codec;
+	const struct firmware *fw;
+	int ret = -1, retry = 0, rc;
+
+	dwork = to_delayed_work(work);
+	sitar = container_of(dwork, struct sitar_priv,
+				mbhc_firmware_dwork);
+	codec = sitar->codec;
+
+	while (retry < MBHC_FW_READ_ATTEMPTS) {
+		retry++;
+		pr_info("%s:Attempt %d to request MBHC firmware\n",
+			__func__, retry);
+		ret = request_firmware(&fw, "wcd9310/wcd9310_mbhc.bin",
+					codec->dev);
+
+		if (ret != 0) {
+			usleep_range(MBHC_FW_READ_TIMEOUT,
+					MBHC_FW_READ_TIMEOUT);
+		} else {
+			pr_info("%s: MBHC Firmware read succesful\n", __func__);
+			break;
+		}
+	}
+
+	if (ret != 0) {
+		pr_err("%s: Cannot load MBHC firmware use default cal\n",
+			__func__);
+	} else if (sitar_mbhc_fw_validate(fw) == false) {
+		pr_err("%s: Invalid MBHC cal data size use default cal\n",
+			 __func__);
+		release_firmware(fw);
+	} else {
+		sitar->calibration = (void *)fw->data;
+		sitar->mbhc_fw = fw;
+	}
+
+	sitar->mclk_cb(codec, 1);
+	sitar_mbhc_init(codec);
+	sitar_mbhc_cal(codec);
+	sitar_mbhc_calc_thres(codec);
+	sitar->mclk_cb(codec, 0);
+	sitar_codec_calibrate_hs_polling(codec);
+	rc = sitar_codec_enable_hs_detect(codec, 1);
+
+	if (IS_ERR_VALUE(rc))
+		pr_err("%s: Failed to setup MBHC detection\n", __func__);
+
+}
+
+int sitar_hs_detect(struct snd_soc_codec *codec,
+		    struct snd_soc_jack *headset_jack,
+		    struct snd_soc_jack *button_jack,
+		    void *calibration, enum sitar_micbias_num micbias,
+		    int (*mclk_cb_fn) (struct snd_soc_codec*, int),
+		    int read_fw_bin, u32 mclk_rate)
+{
+	struct sitar_priv *sitar;
+	int rc = 0;
 
 	if (!codec || !calibration) {
 		pr_err("Error: no codec or calibration\n");
 		return -EINVAL;
 	}
+
+	if (mclk_rate != SITAR_MCLK_RATE_12288KHZ) {
+		if (mclk_rate == SITAR_MCLK_RATE_9600KHZ)
+			pr_err("Error: clock rate %dHz is not yet supported\n",
+				mclk_rate);
+		else
+			pr_err("Error: unsupported clock rate %d\n", mclk_rate);
+		return -EINVAL;
+	}
+
 	sitar = snd_soc_codec_get_drvdata(codec);
 	sitar->headset_jack = headset_jack;
 	sitar->button_jack = button_jack;
+	sitar->micbias = micbias;
 	sitar->calibration = calibration;
+	sitar->mclk_cb = mclk_cb_fn;
+	sitar->mclk_freq = mclk_rate;
 	sitar_get_mbhc_micbias_regs(codec, &sitar->mbhc_bias_regs);
 
 	/* Put CFILT in fast mode by default */
 	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.cfilt_ctl,
 		0x40, SITAR_CFILT_FAST_MODE);
-
+	INIT_DELAYED_WORK(&sitar->mbhc_firmware_dwork, mbhc_fw_read);
 	INIT_DELAYED_WORK(&sitar->btn0_dwork, btn0_lpress_fn);
 	INIT_WORK(&sitar->hphlocp_work, hphlocp_off_report);
 	INIT_WORK(&sitar->hphrocp_work, hphrocp_off_report);
-	rc =  sitar_codec_enable_hs_detect(codec, 1);
+
+	if (!read_fw_bin) {
+		sitar->mclk_cb(codec, 1);
+		sitar_mbhc_init(codec);
+		sitar_mbhc_cal(codec);
+		sitar_mbhc_calc_thres(codec);
+		sitar->mclk_cb(codec, 0);
+		sitar_codec_calibrate_hs_polling(codec);
+		rc =  sitar_codec_enable_hs_detect(codec, 1);
+	} else {
+		schedule_delayed_work(&sitar->mbhc_firmware_dwork,
+				usecs_to_jiffies(MBHC_FW_READ_TIMEOUT));
+	}
 
 	if (!IS_ERR_VALUE(rc)) {
 		snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -2617,36 +3204,139 @@
 }
 EXPORT_SYMBOL_GPL(sitar_hs_detect);
 
+static int sitar_determine_button(const struct sitar_priv *priv,
+				  const s32 bias_mv)
+{
+	s16 *v_btn_low, *v_btn_high;
+	struct sitar_mbhc_btn_detect_cfg *btn_det;
+	int i, btn = -1;
+
+	btn_det = SITAR_MBHC_CAL_BTN_DET_PTR(priv->calibration);
+	v_btn_low = sitar_mbhc_cal_btn_det_mp(btn_det, SITAR_BTN_DET_V_BTN_LOW);
+	v_btn_high = sitar_mbhc_cal_btn_det_mp(btn_det,
+				SITAR_BTN_DET_V_BTN_HIGH);
+	for (i = 0; i < btn_det->num_btn; i++) {
+		if ((v_btn_low[i] <= bias_mv) && (v_btn_high[i] >= bias_mv)) {
+			btn = i;
+			break;
+		}
+	}
+
+	if (btn == -1)
+		pr_debug("%s: couldn't find button number for mic mv %d\n",
+			 __func__, bias_mv);
+
+	return btn;
+}
+
+static int sitar_get_button_mask(const int btn)
+{
+	int mask = 0;
+	switch (btn) {
+	case 0:
+		mask = SND_JACK_BTN_0;
+		break;
+	case 1:
+		mask = SND_JACK_BTN_1;
+		break;
+	case 2:
+		mask = SND_JACK_BTN_2;
+		break;
+	case 3:
+		mask = SND_JACK_BTN_3;
+		break;
+	case 4:
+		mask = SND_JACK_BTN_4;
+		break;
+	case 5:
+		mask = SND_JACK_BTN_5;
+		break;
+	case 6:
+		mask = SND_JACK_BTN_6;
+		break;
+	case 7:
+		mask = SND_JACK_BTN_7;
+		break;
+	}
+	return mask;
+}
+
 static irqreturn_t sitar_dce_handler(int irq, void *data)
 {
+	int i, mask;
+	short bias_value_dce;
+	s32 bias_mv_dce;
+	int btn = -1, meas = 0;
 	struct sitar_priv *priv = data;
+	const struct sitar_mbhc_btn_detect_cfg *d =
+	    SITAR_MBHC_CAL_BTN_DET_PTR(priv->calibration);
+	short btnmeas[d->n_btn_meas + 1];
 	struct snd_soc_codec *codec = priv->codec;
-	short bias_value;
 	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
 
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
 
-	bias_value = sitar_codec_read_dce_result(codec);
-	pr_err("%s: button press interrupt, bias value(DCE Read)=%d\n",
-			__func__, bias_value);
+	bias_value_dce = sitar_codec_read_dce_result(codec);
+	bias_mv_dce = sitar_codec_sta_dce_v(codec, 1, bias_value_dce);
 
-	bias_value = sitar_codec_read_sta_result(codec);
-	pr_err("%s: button press interrupt, bias value(STA Read)=%d\n",
-			__func__, bias_value);
-	/*
-	* TODO: If button pressed is not button 0,
-	* report the button press event immediately.
-	*/
-	priv->buttons_pressed |= SND_JACK_BTN_0;
+	/* determine pressed button */
+	btnmeas[meas++] = sitar_determine_button(priv, bias_mv_dce);
+	pr_debug("%s: meas %d - DCE %d,%d, button %d\n", __func__,
+		 meas - 1, bias_value_dce, bias_mv_dce, btnmeas[meas - 1]);
+	if (d->n_btn_meas == 0)
+		btn = btnmeas[0];
+	for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
+		bias_value_dce = sitar_codec_sta_dce(codec, 1);
+		bias_mv_dce = sitar_codec_sta_dce_v(codec, 1, bias_value_dce);
+		btnmeas[meas] = sitar_determine_button(priv, bias_mv_dce);
+		pr_debug("%s: meas %d - DCE %d,%d, button %d\n",
+			 __func__, meas, bias_value_dce, bias_mv_dce,
+			 btnmeas[meas]);
+		/* if large enough measurements are collected,
+		 * start to check if last all n_btn_con measurements were
+		 * in same button low/high range */
+		if (meas + 1 >= d->n_btn_con) {
+			for (i = 0; i < d->n_btn_con; i++)
+				if ((btnmeas[meas] < 0) ||
+				    (btnmeas[meas] != btnmeas[meas - i]))
+					break;
+			if (i == d->n_btn_con) {
+				/* button pressed */
+				btn = btnmeas[meas];
+				break;
+			}
+		}
+		/* if left measurements are less than n_btn_con,
+		 * it's impossible to find button number */
+		if ((d->n_btn_meas - meas) < d->n_btn_con)
+			break;
+	}
 
-	msleep(100);
+	if (btn >= 0) {
+		mask = sitar_get_button_mask(btn);
+		priv->buttons_pressed |= mask;
 
-	wcd9xxx_lock_sleep(core);
-	if (schedule_delayed_work(&priv->btn0_dwork,
-				 msecs_to_jiffies(400)) == 0) {
-		WARN(1, "Button pressed twice without release event\n");
-		wcd9xxx_unlock_sleep(core);
+		msleep(100);
+
+		/* XXX: assuming button 0 has the lowest micbias voltage */
+		if (btn == 0) {
+			wcd9xxx_lock_sleep(core);
+			if (schedule_delayed_work(&priv->btn0_dwork,
+						  msecs_to_jiffies(400)) == 0) {
+				WARN(1, "Button pressed twice without release"
+				     "event\n");
+				wcd9xxx_unlock_sleep(core);
+			}
+		} else {
+			pr_debug("%s: Reporting short button %d(0x%x) press\n",
+				  __func__, btn, mask);
+			sitar_snd_soc_jack_report(priv, priv->button_jack, mask,
+						  mask);
+		}
+	} else {
+		pr_debug("%s: bogus button press, too short press?\n",
+			 __func__);
 	}
 
 	return IRQ_HANDLED;
@@ -2654,62 +3344,65 @@
 
 static irqreturn_t sitar_release_handler(int irq, void *data)
 {
+	int ret;
+	short mb_v;
 	struct sitar_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	int ret, mic_voltage;
 	struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
 
-	pr_err("%s\n", __func__);
+	pr_debug("%s: enter\n", __func__);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
 
-	mic_voltage = sitar_codec_read_dce_result(codec);
-	pr_err("%s: Microphone Voltage on release(DCE Read) = %d\n",
-		__func__, mic_voltage);
-
 	if (priv->buttons_pressed & SND_JACK_BTN_0) {
 		ret = cancel_delayed_work(&priv->btn0_dwork);
 
 		if (ret == 0) {
-
-			pr_err("%s: Reporting long button release event\n",
-					__func__);
-			if (priv->button_jack) {
+			pr_debug("%s: Reporting long button 0 release event\n",
+				 __func__);
+			if (priv->button_jack)
 				sitar_snd_soc_jack_report(priv,
-							 priv->button_jack, 0,
-							 SND_JACK_BTN_0);
-			}
-
+							  priv->button_jack, 0,
+							  SND_JACK_BTN_0);
 		} else {
 			/* if scheduled btn0_dwork is canceled from here,
-			* we have to unlock from here instead btn0_work */
+			 * we have to unlock from here instead btn0_work */
 			wcd9xxx_unlock_sleep(core);
-			mic_voltage =
-				sitar_codec_measure_micbias_voltage(codec, 0);
-			pr_err("%s: Mic Voltage on release(new STA) = %d\n",
-						__func__, mic_voltage);
+			mb_v = sitar_codec_sta_dce(codec, 0);
+			pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
+				 __func__, mb_v,
+				 sitar_codec_sta_dce_v(codec, 0, mb_v));
 
-			if (mic_voltage < -2000 || mic_voltage > -670) {
-				pr_err("%s: Fake buttton press interrupt\n",
-						__func__);
-			} else {
-
-				if (priv->button_jack) {
-					pr_err("%s:reporting short button press and release\n",
-							__func__);
-
-					sitar_snd_soc_jack_report(priv,
-							     priv->button_jack,
-						SND_JACK_BTN_0, SND_JACK_BTN_0);
-					sitar_snd_soc_jack_report(priv,
-							    priv->button_jack,
-							    0, SND_JACK_BTN_0);
-				}
+			if (mb_v < (short)priv->mbhc_data.v_b1_hu ||
+			    mb_v > (short)priv->mbhc_data.v_ins_hu)
+				pr_debug("%s: Fake buttton press interrupt\n",
+					 __func__);
+			else if (priv->button_jack) {
+				pr_debug("%s: Reporting short button 0 "
+					 "press and release\n", __func__);
+				sitar_snd_soc_jack_report(priv,
+							  priv->button_jack,
+							  SND_JACK_BTN_0,
+							  SND_JACK_BTN_0);
+				sitar_snd_soc_jack_report(priv,
+							  priv->button_jack, 0,
+							  SND_JACK_BTN_0);
 			}
 		}
 
 		priv->buttons_pressed &= ~SND_JACK_BTN_0;
 	}
 
+	if (priv->buttons_pressed) {
+		pr_debug("%s:reporting button release mask 0x%x\n", __func__,
+			 priv->buttons_pressed);
+		sitar_snd_soc_jack_report(priv, priv->button_jack, 0,
+					  priv->buttons_pressed);
+		/* hardware doesn't detect another button press until
+		 * already pressed button is released.
+		 * therefore buttons_pressed has only one button's mask. */
+		priv->buttons_pressed &= ~SITAR_JACK_BUTTON_MASK;
+	}
+
 	sitar_codec_start_hs_polling(codec);
 	return IRQ_HANDLED;
 }
@@ -2717,17 +3410,23 @@
 static void sitar_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
 {
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
-	struct sitar_mbhc_calibration *calibration = sitar->calibration;
+	const struct sitar_mbhc_general_cfg *generic =
+	    SITAR_MBHC_CAL_GENERAL_PTR(sitar->calibration);
+
+	if (!sitar->mclk_enabled && !sitar->mbhc_polling_active)
+		sitar_codec_enable_config_mode(codec, 1);
 
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
 
-	snd_soc_update_bits(codec,
-		sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
-	usleep_range(calibration->shutdown_plug_removal,
-		calibration->shutdown_plug_removal);
+	snd_soc_update_bits(codec, sitar->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+
+	usleep_range(generic->t_shutdown_plug_rem,
+		     generic->t_shutdown_plug_rem);
 
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
+	if (!sitar->mclk_enabled && !sitar->mbhc_polling_active)
+		sitar_codec_enable_config_mode(codec, 0);
 
 	snd_soc_write(codec, SITAR_A_MBHC_SCALING_MUX_1, 0x00);
 }
@@ -2740,8 +3439,8 @@
 
 	if (!sitar->mclk_enabled) {
 		snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0x00);
-		sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_AUDIO_MODE);
-		sitar_codec_enable_clock_block(codec, 0);
+		sitar_codec_disable_clock_block(codec);
+		sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_OFF);
 	}
 
 	sitar->mbhc_polling_active = false;
@@ -2759,19 +3458,19 @@
 		if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
 			pr_info("%s: retry\n", __func__);
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
-					   0x00);
+					    0x00);
 			snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
-					   0x10);
+					    0x10);
 		} else {
 			wcd9xxx_disable_irq(codec->control_data,
-					 SITAR_IRQ_HPH_PA_OCPL_FAULT);
+					  SITAR_IRQ_HPH_PA_OCPL_FAULT);
 			sitar->hphlocp_cnt = 0;
 			sitar->hph_status |= SND_JACK_OC_HPHL;
 			if (sitar->headset_jack)
 				sitar_snd_soc_jack_report(sitar,
-							 sitar->headset_jack,
-							 sitar->hph_status,
-							 SITAR_JACK_MASK);
+							  sitar->headset_jack,
+							  sitar->hph_status,
+							  SITAR_JACK_MASK);
 		}
 	} else {
 		pr_err("%s: Bad sitar private data\n", __func__);
@@ -2846,45 +3545,48 @@
 {
 	struct sitar_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
+	const struct sitar_mbhc_plug_detect_cfg *plug_det =
+	    SITAR_MBHC_CAL_PLUG_DET_PTR(priv->calibration);
 	int ldo_h_on, micb_cfilt_on;
-	short mic_voltage;
-	short threshold_no_mic = 0xF7F6;
-	short threshold_fake_insert = 0xFD30;
+	short mb_v;
 	u8 is_removal;
+	int mic_mv;
 
-	pr_err("%s\n", __func__);
+	pr_debug("%s: enter\n", __func__);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION);
 
 	is_removal = snd_soc_read(codec, SITAR_A_CDC_MBHC_INT_CTL) & 0x02;
 	snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
 
 	/* Turn off both HPH and MIC line schmitt triggers */
-	snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
-			0x90, 0x00);
+	snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
 	snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x13, 0x00);
 
-	if (priv->fake_insert_context) {
-		pr_err("%s: fake context interrupt, reset insertion\n",
-			__func__);
-		priv->fake_insert_context = false;
+	if (priv->mbhc_fake_ins_start &&
+	    time_after(jiffies, priv->mbhc_fake_ins_start +
+			msecs_to_jiffies(SITAR_FAKE_INS_THRESHOLD_MS))) {
+		pr_debug("%s: fake context interrupt, reset insertion\n",
+			 __func__);
+		priv->mbhc_fake_ins_start = 0;
 		sitar_codec_shutdown_hs_polling(codec);
 		sitar_codec_enable_hs_detect(codec, 1);
 		return IRQ_HANDLED;
 	}
 
-
 	ldo_h_on = snd_soc_read(codec, SITAR_A_LDO_H_MODE_1) & 0x80;
-	micb_cfilt_on = snd_soc_read(codec,
-					priv->mbhc_bias_regs.cfilt_ctl) & 0x80;
+	micb_cfilt_on = snd_soc_read(codec, priv->mbhc_bias_regs.cfilt_ctl)
+			    & 0x80;
 
 	if (!ldo_h_on)
 		snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x80);
 	if (!micb_cfilt_on)
 		snd_soc_update_bits(codec, priv->mbhc_bias_regs.cfilt_ctl,
-							0x80, 0x80);
-
-	usleep_range(priv->calibration->setup_plug_removal_delay,
-		priv->calibration->setup_plug_removal_delay);
+				    0x80, 0x80);
+	if (plug_det->t_ins_complete > 20)
+		msleep(plug_det->t_ins_complete);
+	else
+		usleep_range(plug_det->t_ins_complete * 1000,
+			     plug_det->t_ins_complete * 1000);
 
 	if (!ldo_h_on)
 		snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1, 0x80, 0x0);
@@ -2926,56 +3628,78 @@
 		return IRQ_HANDLED;
 	}
 
-	mic_voltage = sitar_codec_setup_hs_polling(codec);
+	mb_v = sitar_codec_setup_hs_polling(codec);
+	mic_mv = sitar_codec_sta_dce_v(codec, 0, mb_v);
 
-	if (mic_voltage > threshold_fake_insert) {
-		pr_err("%s: Fake insertion interrupt, mic_voltage = %x\n",
-			__func__, mic_voltage);
-
-		/* Disable HPH trigger and enable MIC line trigger */
-		snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12, 0x00);
-
-		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x60,
-			priv->calibration->mic_current << 5);
-		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
-			0x80, 0x80);
-		usleep_range(priv->calibration->mic_pid,
-			priv->calibration->mic_pid);
-		snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg,
-			0x10, 0x10);
-
+	if (mb_v > (short) priv->mbhc_data.v_ins_hu) {
+		pr_debug("%s: Fake insertion interrupt since %dmsec ago, "
+			 "STA : %d,%d\n", __func__,
+			 (priv->mbhc_fake_ins_start ?
+			     jiffies_to_msecs(jiffies -
+					      priv->mbhc_fake_ins_start) :
+			     0),
+			 mb_v, mic_mv);
+		if (time_after(jiffies,
+			priv->mbhc_fake_ins_start +
+			msecs_to_jiffies(SITAR_FAKE_INS_THRESHOLD_MS))) {
+			/* Disable HPH trigger and enable MIC line trigger */
+			snd_soc_update_bits(codec, SITAR_A_MBHC_HPH, 0x12,
+					    0x00);
+			snd_soc_update_bits(codec,
+					    priv->mbhc_bias_regs.mbhc_reg, 0x60,
+					    plug_det->mic_current << 5);
+			snd_soc_update_bits(codec,
+					    priv->mbhc_bias_regs.mbhc_reg,
+					    0x80, 0x80);
+			usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
+			snd_soc_update_bits(codec,
+					    priv->mbhc_bias_regs.mbhc_reg,
+					    0x10, 0x10);
+		} else {
+			if (priv->mbhc_fake_ins_start == 0)
+				priv->mbhc_fake_ins_start = jiffies;
+			/* Setup normal insert detection
+			 * Enable HPH Schmitt Trigger
+			 */
+			snd_soc_update_bits(codec, SITAR_A_MBHC_HPH,
+					    0x13 | 0x0C,
+					    0x13 | plug_det->hph_current << 2);
+		}
 		/* Setup for insertion detection */
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x2, 0);
-		priv->fake_insert_context = true;
 		wcd9xxx_enable_irq(codec->control_data,
-				SITAR_IRQ_MBHC_INSERTION);
+					SITAR_IRQ_MBHC_INSERTION);
 		snd_soc_update_bits(codec, SITAR_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
 
-	} else if (mic_voltage < threshold_no_mic) {
-		pr_err("%s: Headphone Detected, mic_voltage = %x\n",
-			__func__, mic_voltage);
+	} else if (mb_v < (short) priv->mbhc_data.v_no_mic) {
+		pr_debug("%s: Headphone Detected, mb_v: %d,%d\n",
+			 __func__, mb_v, mic_mv);
+		priv->mbhc_fake_ins_start = 0;
 		priv->hph_status |= SND_JACK_HEADPHONE;
 		if (priv->headset_jack) {
-			pr_err("%s: Reporting insertion %d\n", __func__,
-				SND_JACK_HEADPHONE);
+			pr_debug("%s: Reporting insertion %d\n", __func__,
+				 SND_JACK_HEADPHONE);
 			sitar_snd_soc_jack_report(priv, priv->headset_jack,
-						 priv->hph_status,
-						 SITAR_JACK_MASK);
+						  priv->hph_status,
+						  SITAR_JACK_MASK);
 		}
 		sitar_codec_shutdown_hs_polling(codec);
 		sitar_codec_enable_hs_detect(codec, 0);
 		sitar_sync_hph_state(priv);
 	} else {
-		pr_err("%s: Headset detected, mic_voltage = %x\n",
-			__func__, mic_voltage);
+		pr_debug("%s: Headset detected, mb_v: %d,%d\n",
+			__func__, mb_v, mic_mv);
+		priv->mbhc_fake_ins_start = 0;
 		priv->hph_status |= SND_JACK_HEADSET;
 		if (priv->headset_jack) {
-			pr_err("%s: Reporting insertion %d\n", __func__,
-				SND_JACK_HEADSET);
+			pr_debug("%s: Reporting insertion %d\n", __func__,
+				 SND_JACK_HEADSET);
 			sitar_snd_soc_jack_report(priv, priv->headset_jack,
-						 priv->hph_status,
-						 SITAR_JACK_MASK);
+						  priv->hph_status,
+						  SITAR_JACK_MASK);
 		}
+		/* avoid false button press detect */
+		msleep(50);
 		sitar_codec_start_hs_polling(codec);
 		sitar_sync_hph_state(priv);
 	}
@@ -2985,29 +3709,42 @@
 
 static irqreturn_t sitar_hs_remove_irq(int irq, void *data)
 {
+	short bias_value;
 	struct sitar_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
-	short bias_value;
+	const struct sitar_mbhc_general_cfg *generic =
+	    SITAR_MBHC_CAL_GENERAL_PTR(priv->calibration);
+	int fake_removal = 0;
+	int min_us = SITAR_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
 
+	pr_debug("%s: enter, removal interrupt\n", __func__);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_REMOVAL);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_POTENTIAL);
 	wcd9xxx_disable_irq(codec->control_data, SITAR_IRQ_MBHC_RELEASE);
 
-	usleep_range(priv->calibration->shutdown_plug_removal,
-		priv->calibration->shutdown_plug_removal);
+	usleep_range(generic->t_shutdown_plug_rem,
+		     generic->t_shutdown_plug_rem);
 
-	bias_value = sitar_codec_measure_micbias_voltage(codec, 1);
-	pr_err("removal interrupt, bias value is %d\n", bias_value);
+	do {
+		bias_value = sitar_codec_sta_dce(codec, 1);
+		pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
+			 sitar_codec_sta_dce_v(codec, 1, bias_value), min_us);
+		if (bias_value < (short)priv->mbhc_data.v_ins_h) {
+			fake_removal = 1;
+			break;
+		}
+		min_us -= priv->mbhc_data.t_dce;
+	} while (min_us > 0);
 
-	if (bias_value < -90) {
-		pr_err("False alarm, headset not actually removed\n");
+	if (fake_removal) {
+		pr_debug("False alarm, headset not actually removed\n");
 		sitar_codec_start_hs_polling(codec);
 	} else {
 		/*
-		* If this removal is not false, first check the micbias
-		* switch status and switch it to LDOH if it is already
-		* switched to VDDIO.
-		*/
+		 * If this removal is not false, first check the micbias
+		 * switch status and switch it to LDOH if it is already
+		 * switched to VDDIO.
+		 */
 		if (priv->mbhc_micbias_switched)
 			sitar_codec_switch_micbias(codec, 0);
 		priv->hph_status &= ~SND_JACK_HEADSET;
@@ -3129,6 +3866,14 @@
 				0x03, val_txfe);
 		}
 	}
+	if (flag & 0x40) {
+		value = (leg_mode & 0x40) ? 0x10 : 0x00;
+		value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
+		value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
+		snd_soc_update_bits(codec, SITAR_A_TX_4_MBHC_EN,
+			0x13, value);
+	}
+
 
 	if (pdata->ocp.use_pdata) {
 		/* not defined in CODEC specification */
@@ -3203,11 +3948,12 @@
 	{SITAR_A_CDC_CONN_CLSG_CTL, 0x3C, 0x14},
 
 	/* Use 16 bit sample size for TX1 to TX6 */
-	{SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x28},
+	{SITAR_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
 	{SITAR_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
 	{SITAR_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
 	{SITAR_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
 	{SITAR_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+	{SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0x1, 0x1},
 
 	/* Use 16 bit sample size for RX */
 	{SITAR_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
@@ -3215,12 +3961,12 @@
 
 	/*enable HPF filter for TX paths */
 	{SITAR_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+	{SITAR_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
 };
 
 static void sitar_codec_init_reg(struct snd_soc_codec *codec)
 {
 	u32 i;
-
 	for (i = 0; i < ARRAY_SIZE(sitar_codec_reg_init_val); i++)
 		snd_soc_update_bits(codec, sitar_codec_reg_init_val[i].reg,
 			sitar_codec_reg_init_val[i].mask,
@@ -3252,6 +3998,12 @@
 	sitar->cfilt_k_value = 0;
 	sitar->mbhc_micbias_switched = false;
 
+	/* Make sure mbhc intenal calibration data is zeroed out */
+	memset(&sitar->mbhc_data, 0,
+		sizeof(struct mbhc_internal_cal_data));
+	sitar->mbhc_data.t_sta_dce = DEFAULT_DCE_STA_WAIT;
+	sitar->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
+	sitar->mbhc_data.t_sta = DEFAULT_STA_WAIT;
 	snd_soc_codec_set_drvdata(codec, sitar);
 
 	sitar->mclk_enabled = false;
@@ -3259,13 +4011,9 @@
 	sitar->clock_active = false;
 	sitar->config_mode_active = false;
 	sitar->mbhc_polling_active = false;
-	sitar->fake_insert_context = false;
 	sitar->no_mic_headset_override = false;
 	sitar->codec = codec;
 	sitar->pdata = dev_get_platdata(codec->dev->parent);
-	atomic_set(&sitar->pm_cnt, 1);
-	init_waitqueue_head(&sitar->pm_wq);
-
 	sitar_update_reg_defaults(codec);
 	sitar_codec_init_reg(codec);
 
@@ -3414,6 +4162,8 @@
 	wcd9xxx_free_irq(codec->control_data, SITAR_IRQ_MBHC_INSERTION, sitar);
 	sitar_codec_disable_clock_block(codec);
 	sitar_codec_enable_bandgap(codec, SITAR_BANDGAP_OFF);
+	if (sitar->mbhc_fw)
+		release_firmware(sitar->mbhc_fw);
 	for (i = 0; i < ARRAY_SIZE(sitar_dai); i++)
 		kfree(sitar->dai[i].ch_num);
 	kfree(sitar);
diff --git a/sound/soc/codecs/wcd9304.h b/sound/soc/codecs/wcd9304.h
index 07a1ca0..cfe839b 100644
--- a/sound/soc/codecs/wcd9304.h
+++ b/sound/soc/codecs/wcd9304.h
@@ -13,24 +13,36 @@
 #include <sound/soc.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
 
-#define SITAR_VERSION_1_0	0x00
-
-#define SITAR_NUM_REGISTERS 0x3E0
+#define SITAR_NUM_REGISTERS 0x400
 #define SITAR_MAX_REGISTER (SITAR_NUM_REGISTERS-1)
 #define SITAR_CACHE_SIZE SITAR_NUM_REGISTERS
+#define SITAR_1_X_ONLY_REGISTERS 3
+#define SITAR_2_HIGHER_ONLY_REGISTERS 3
 
 #define SITAR_REG_VAL(reg, val)		{reg, 0, val}
 
-/* Local to the core only */
-#define SITAR_SLIM_MAX_RX_PORTS 5
-#define SITAR_SLIM_MAX_TX_PORTS 5
+#define DEFAULT_DCE_STA_WAIT 55
+#define DEFAULT_DCE_WAIT 60000
+#define DEFAULT_STA_WAIT 5000
+
+#define STA 0
+#define DCE 1
+
+#define SITAR_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
+				SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
+				SND_JACK_BTN_4 | SND_JACK_BTN_5 | \
+				SND_JACK_BTN_6 | SND_JACK_BTN_7)
 
 extern const u8 sitar_reg_readable[SITAR_CACHE_SIZE];
+extern const u32 sitar_1_reg_readable[SITAR_1_X_ONLY_REGISTERS];
+extern const u32 sitar_2_reg_readable[SITAR_2_HIGHER_ONLY_REGISTERS];
 extern const u8 sitar_reg_defaults[SITAR_CACHE_SIZE];
 
 enum sitar_micbias_num {
 	SITAR_MICBIAS1,
 	SITAR_MICBIAS2,
+	SITAR_MICBIAS3,
+	SITAR_MICBIAS4,
 };
 
 enum sitar_pid_current {
@@ -40,26 +52,116 @@
 	SITAR_PID_MIC_20_UA,
 };
 
-struct sitar_mbhc_calibration {
-	enum sitar_micbias_num bias;
-	int tldoh;
-	int bg_fast_settle;
-	enum sitar_pid_current mic_current;
-	int mic_pid;
-	enum sitar_pid_current hph_current;
-	int setup_plug_removal_delay;
-	int shutdown_plug_removal;
-};
-
 struct sitar_reg_mask_val {
 	u16	reg;
 	u8	mask;
 	u8	val;
 };
 
+enum sitar_mbhc_clk_freq {
+	SITAR_MCLK_12P2MHZ = 0,
+	SITAR_MCLK_9P6MHZ,
+	SITAR_NUM_CLK_FREQS,
+};
+
+enum sitar_mbhc_analog_pwr_cfg {
+	SITAR_ANALOG_PWR_COLLAPSED = 0,
+	SITAR_ANALOG_PWR_ON,
+	SITAR_NUM_ANALOG_PWR_CONFIGS,
+};
+
+enum sitar_mbhc_btn_det_mem {
+	SITAR_BTN_DET_V_BTN_LOW,
+	SITAR_BTN_DET_V_BTN_HIGH,
+	SITAR_BTN_DET_N_READY,
+	SITAR_BTN_DET_N_CIC,
+	SITAR_BTN_DET_GAIN
+};
+
+struct sitar_mbhc_general_cfg {
+	u8 t_ldoh;
+	u8 t_bg_fast_settle;
+	u8 t_shutdown_plug_rem;
+	u8 mbhc_nsa;
+	u8 mbhc_navg;
+	u8 v_micbias_l;
+	u8 v_micbias;
+	u8 mbhc_reserved;
+	u16 settle_wait;
+	u16 t_micbias_rampup;
+	u16 t_micbias_rampdown;
+	u16 t_supply_bringup;
+} __packed;
+
+struct sitar_mbhc_plug_detect_cfg {
+	u32 mic_current;
+	u32 hph_current;
+	u16 t_mic_pid;
+	u16 t_ins_complete;
+	u16 t_ins_retry;
+	u16 v_removal_delta;
+	u8 micbias_slow_ramp;
+	u8 reserved0;
+	u8 reserved1;
+	u8 reserved2;
+} __packed;
+
+struct sitar_mbhc_plug_type_cfg {
+	u8 av_detect;
+	u8 mono_detect;
+	u8 num_ins_tries;
+	u8 reserved0;
+	s16 v_no_mic;
+	s16 v_av_min;
+	s16 v_av_max;
+	s16 v_hs_min;
+	s16 v_hs_max;
+	u16 reserved1;
+} __packed;
+
+
+struct sitar_mbhc_btn_detect_cfg {
+	s8 c[8];
+	u8 nc;
+	u8 n_meas;
+	u8 mbhc_nsc;
+	u8 n_btn_meas;
+	u8 n_btn_con;
+	u8 num_btn;
+	u8 reserved0;
+	u8 reserved1;
+	u16 t_poll;
+	u16 t_bounce_wait;
+	u16 t_rel_timeout;
+	s16 v_btn_press_delta_sta;
+	s16 v_btn_press_delta_cic;
+	u16 t_btn0_timeout;
+	s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
+	s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
+	u8 _n_ready[SITAR_NUM_CLK_FREQS];
+	u8 _n_cic[SITAR_NUM_CLK_FREQS];
+	u8 _gain[SITAR_NUM_CLK_FREQS];
+} __packed;
+
+struct sitar_mbhc_imped_detect_cfg {
+	u8 _hs_imped_detect;
+	u8 _n_rload;
+	u8 _hph_keep_on;
+	u8 _repeat_rload_calc;
+	u16 _t_dac_ramp_time;
+	u16 _rhph_high;
+	u16 _rhph_low;
+	u16 _rload[0]; /* rload[n_rload] */
+	u16 _alpha[0]; /* alpha[n_rload] */
+	u16 _beta[3];
+} __packed;
+
 extern int sitar_hs_detect(struct snd_soc_codec *codec,
-	struct snd_soc_jack *headset_jack, struct snd_soc_jack *button_jack,
-	struct sitar_mbhc_calibration *calibration);
+			   struct snd_soc_jack *headset_jack,
+			   struct snd_soc_jack *button_jack,
+			   void *calibration, enum sitar_micbias_num micbis,
+			   int (*mclk_cb_fn) (struct snd_soc_codec*, int),
+			   int read_fw_bin, u32 mclk_rate);
 
 #ifndef anc_header_dec
 struct anc_header {
@@ -70,3 +172,62 @@
 #endif
 
 extern int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable);
+
+extern void *sitar_mbhc_cal_btn_det_mp(const struct sitar_mbhc_btn_detect_cfg
+				       *btn_det,
+				       const enum sitar_mbhc_btn_det_mem mem);
+
+#define SITAR_MBHC_CAL_SIZE(buttons, rload) ( \
+	sizeof(enum sitar_micbias_num) + \
+	sizeof(struct sitar_mbhc_general_cfg) + \
+	sizeof(struct sitar_mbhc_plug_detect_cfg) + \
+	    ((sizeof(s16) + sizeof(s16)) * buttons) + \
+	sizeof(struct sitar_mbhc_plug_type_cfg) + \
+	sizeof(struct sitar_mbhc_btn_detect_cfg) + \
+	sizeof(struct sitar_mbhc_imped_detect_cfg) + \
+	    ((sizeof(u16) + sizeof(u16)) * rload) \
+	)
+
+#define SITAR_MBHC_CAL_GENERAL_PTR(cali) ( \
+	    (struct sitar_mbhc_general_cfg *) cali)
+#define SITAR_MBHC_CAL_PLUG_DET_PTR(cali) ( \
+	    (struct sitar_mbhc_plug_detect_cfg *) \
+	    &(SITAR_MBHC_CAL_GENERAL_PTR(cali)[1]))
+#define SITAR_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
+	    (struct sitar_mbhc_plug_type_cfg *) \
+	    &(SITAR_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
+#define SITAR_MBHC_CAL_BTN_DET_PTR(cali) ( \
+	    (struct sitar_mbhc_btn_detect_cfg *) \
+	    &(SITAR_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
+#define SITAR_MBHC_CAL_IMPED_DET_PTR(cali) ( \
+	    (struct sitar_mbhc_imped_detect_cfg *) \
+	    (((void *)&SITAR_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
+	     (SITAR_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
+	      (sizeof(SITAR_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
+	       sizeof(SITAR_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
+	)
+
+/* minimum size of calibration data assuming there is only one button and
+ * one rload.
+ */
+#define SITAR_MBHC_CAL_MIN_SIZE ( \
+	sizeof(struct sitar_mbhc_general_cfg) + \
+	sizeof(struct sitar_mbhc_plug_detect_cfg) + \
+	sizeof(struct sitar_mbhc_plug_type_cfg) + \
+	sizeof(struct sitar_mbhc_btn_detect_cfg) + \
+	sizeof(struct sitar_mbhc_imped_detect_cfg) + \
+	(sizeof(u16) * 2))
+
+#define SITAR_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
+	    sizeof(struct sitar_mbhc_btn_detect_cfg) + \
+	    (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
+				 sizeof(cfg_ptr->_v_btn_high[0]))))
+
+#define SITAR_MBHC_CAL_IMPED_MIN_SZ ( \
+	    sizeof(struct sitar_mbhc_imped_detect_cfg) + \
+	    sizeof(u16) * 2)
+
+#define SITAR_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
+	    sizeof(struct sitar_mbhc_imped_detect_cfg) + \
+	    (cfg_ptr->_n_rload * (sizeof(cfg_ptr->_rload[0]) + \
+				 sizeof(cfg_ptr->_alpha[0]))))
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 830b98f..a78380b 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1331,41 +1331,132 @@
 static const struct snd_kcontrol_new sb_tx1_mux =
 	SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
 
+static int wcd9310_put_dec_enum(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+	struct snd_soc_dapm_widget *w = wlist->widgets[0];
+	struct snd_soc_codec *codec = w->codec;
+	struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+	unsigned int dec_mux, decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	u16 tx_mux_ctl_reg;
+	u8 adc_dmic_sel = 0x0;
+	int ret = 0;
+
+	if (ucontrol->value.enumerated.item[0] > e->max - 1)
+		return -EINVAL;
+
+	dec_mux = ucontrol->value.enumerated.item[0];
+
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	dev_dbg(w->dapm->dev, "%s(): widget = %s  dec_name = %s decimator = %u"
+		" dec_mux = %u\n", __func__, w->name, dec_name, decimator,
+		dec_mux);
+
+
+	switch (decimator) {
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (dec_mux == 1)
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+		if ((dec_mux == 1) || (dec_mux == 2))
+			adc_dmic_sel = 0x1;
+		else
+			adc_dmic_sel = 0x0;
+		break;
+	default:
+		pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+	ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+	kfree(widget_name);
+	return ret;
+}
+
+#define WCD9310_DEC_ENUM(xname, xenum) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.info = snd_soc_info_enum_double, \
+	.get = snd_soc_dapm_get_enum_double, \
+	.put = wcd9310_put_dec_enum, \
+	.private_value = (unsigned long)&xenum }
+
 static const struct snd_kcontrol_new dec1_mux =
-	SOC_DAPM_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+	WCD9310_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
 
 static const struct snd_kcontrol_new dec2_mux =
-	SOC_DAPM_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+	WCD9310_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
 
 static const struct snd_kcontrol_new dec3_mux =
-	SOC_DAPM_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+	WCD9310_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
 
 static const struct snd_kcontrol_new dec4_mux =
-	SOC_DAPM_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+	WCD9310_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
 
 static const struct snd_kcontrol_new dec5_mux =
-	SOC_DAPM_ENUM("DEC5 MUX Mux", dec5_mux_enum);
+	WCD9310_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
 
 static const struct snd_kcontrol_new dec6_mux =
-	SOC_DAPM_ENUM("DEC6 MUX Mux", dec6_mux_enum);
+	WCD9310_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
 
 static const struct snd_kcontrol_new dec7_mux =
-	SOC_DAPM_ENUM("DEC7 MUX Mux", dec7_mux_enum);
+	WCD9310_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
 
-static const struct snd_kcontrol_new anc1_mux =
-	SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
 static const struct snd_kcontrol_new dec8_mux =
-	SOC_DAPM_ENUM("DEC8 MUX Mux", dec8_mux_enum);
+	WCD9310_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
 
 static const struct snd_kcontrol_new dec9_mux =
-	SOC_DAPM_ENUM("DEC9 MUX Mux", dec9_mux_enum);
+	WCD9310_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
 
 static const struct snd_kcontrol_new dec10_mux =
-	SOC_DAPM_ENUM("DEC10 MUX Mux", dec10_mux_enum);
+	WCD9310_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
 
 static const struct snd_kcontrol_new iir1_inp1_mux =
 	SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
 
+static const struct snd_kcontrol_new anc1_mux =
+	SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
+
 static const struct snd_kcontrol_new anc2_mux =
 	SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
 
@@ -1845,7 +1936,7 @@
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u16 tx_mux_ctl_reg, tx_dmic_ctl_reg;
+	u16 tx_dmic_ctl_reg;
 	u8 dmic_clk_sel, dmic_clk_en;
 	unsigned int dmic;
 	int ret;
@@ -1880,14 +1971,12 @@
 		return -EINVAL;
 	}
 
-	tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
 	tx_dmic_ctl_reg = TABLA_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
 
 	pr_debug("%s %d\n", __func__, event);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, 0x1);
 
 		snd_soc_update_bits(codec, TABLA_A_CDC_CLK_DMIC_CTL,
 				dmic_clk_sel, dmic_clk_sel);
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index a6ec1a7..b3cffd1 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -62,7 +62,7 @@
 snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
 obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
 
-snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o
+snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o mpq8064.o
 obj-$(CONFIG_SND_SOC_MSM8960) += snd-soc-msm8960.o
 
 # Generic MSM drivers
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 9d61a7c..26e4263 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1439,7 +1439,7 @@
 {
 	int ret;
 
-	if (!cpu_is_apq8064()) {
+	if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV;
 	}
@@ -1478,7 +1478,7 @@
 
 static void __exit msm_audio_exit(void)
 {
-	if (!cpu_is_apq8064()) {
+	if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
new file mode 100644
index 0000000..961f833
--- /dev/null
+++ b/sound/soc/msm/mpq8064.c
@@ -0,0 +1,1284 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/soc-dsp.h>
+#include <sound/pcm.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+#include <asm/mach-types.h>
+#include <mach/socinfo.h>
+#include "msm-pcm-routing.h"
+#include "../codecs/wcd9310.h"
+
+/* 8064 machine driver */
+
+#define PM8921_GPIO_BASE		NR_GPIO_IRQS
+#define PM8921_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio - 1 + PM8921_GPIO_BASE)
+
+#define MPQ8064_SPK_ON 1
+#define MPQ8064_SPK_OFF 0
+
+#define MSM_SLIM_0_RX_MAX_CHANNELS		2
+#define MSM_SLIM_0_TX_MAX_CHANNELS		4
+
+#define BOTTOM_SPK_AMP_POS	0x1
+#define BOTTOM_SPK_AMP_NEG	0x2
+#define TOP_SPK_AMP_POS		0x4
+#define TOP_SPK_AMP_NEG		0x8
+
+#define TABLA_EXT_CLK_RATE 12288000
+
+#define TABLA_MBHC_DEF_BUTTONS 8
+#define TABLA_MBHC_DEF_RLOADS 5
+
+#define GPIO_SEC_I2S_RX_SCK  47
+#define GPIO_SEC_I2S_RX_WS   48
+#define GPIO_SEC_I2S_RX_DOUT 49
+#define GPIO_SEC_I2S_RX_MCLK 50
+#define I2S_MCLK_RATE 1536000
+
+static struct clk *sec_i2s_rx_osr_clk;
+static struct clk *sec_i2s_rx_bit_clk;
+
+struct request_gpio {
+	unsigned gpio_no;
+	char *gpio_name;
+};
+
+static struct request_gpio sec_i2s_rx_gpio[] = {
+	{
+		.gpio_no = GPIO_SEC_I2S_RX_MCLK,
+		.gpio_name = "SEC_I2S_RX_MCLK",
+	},
+	{
+		.gpio_no = GPIO_SEC_I2S_RX_SCK,
+		.gpio_name = "SEC_I2S_RX_SCK",
+	},
+	{
+		.gpio_no = GPIO_SEC_I2S_RX_WS,
+		.gpio_name = "SEC_I2S_RX_WS",
+	},
+	{
+		.gpio_no = GPIO_SEC_I2S_RX_DOUT,
+		.gpio_name = "SEC_I2S_RX_DOUT",
+	},
+};
+
+static u32 top_spk_pamp_gpio  = PM8921_GPIO_PM_TO_SYS(18);
+static u32 bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(19);
+static int msm_spk_control;
+static int msm_ext_bottom_spk_pamp;
+static int msm_ext_top_spk_pamp;
+static int msm_slim_0_rx_ch = 1;
+static int msm_slim_0_tx_ch = 1;
+
+static struct clk *codec_clk;
+static int clk_users;
+
+static int msm_headset_gpios_configured;
+
+static struct snd_soc_jack hs_jack;
+static struct snd_soc_jack button_jack;
+
+static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
+				    bool dapm);
+
+static struct tabla_mbhc_config mbhc_cfg = {
+	.headset_jack = &hs_jack,
+	.button_jack = &button_jack,
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.micbias = TABLA_MICBIAS2,
+	.mclk_cb_fn = msm_enable_codec_ext_clk,
+	.mclk_rate = TABLA_EXT_CLK_RATE,
+	.gpio = 0, /* MBHC GPIO is not configured */
+	.gpio_irq = 0,
+	.gpio_level_insert = 1,
+};
+
+static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
+{
+	int ret = 0;
+
+	struct pm_gpio param = {
+		.direction      = PM_GPIO_DIR_OUT,
+		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+		.output_value   = 1,
+		.pull      = PM_GPIO_PULL_NO,
+		.vin_sel	= PM_GPIO_VIN_S4,
+		.out_strength   = PM_GPIO_STRENGTH_MED,
+		.
+			function       = PM_GPIO_FUNC_NORMAL,
+	};
+
+	if (spk_amp_gpio == bottom_spk_pamp_gpio) {
+
+		ret = gpio_request(bottom_spk_pamp_gpio, "BOTTOM_SPK_AMP");
+		if (ret) {
+			pr_err("%s: Error requesting BOTTOM SPK AMP GPIO %u\n",
+				__func__, bottom_spk_pamp_gpio);
+			return;
+		}
+		ret = pm8xxx_gpio_config(bottom_spk_pamp_gpio, &param);
+		if (ret)
+			pr_err("%s: Failed to configure Bottom Spk Ampl"
+				" gpio %u\n", __func__, bottom_spk_pamp_gpio);
+		else {
+			pr_debug("%s: enable Bottom spkr amp gpio\n", __func__);
+			gpio_direction_output(bottom_spk_pamp_gpio, 1);
+		}
+
+	} else if (spk_amp_gpio == top_spk_pamp_gpio) {
+
+		ret = gpio_request(top_spk_pamp_gpio, "TOP_SPK_AMP");
+		if (ret) {
+			pr_err("%s: Error requesting GPIO %d\n", __func__,
+				top_spk_pamp_gpio);
+			return;
+		}
+		ret = pm8xxx_gpio_config(top_spk_pamp_gpio, &param);
+		if (ret)
+			pr_err("%s: Failed to configure Top Spk Ampl"
+				" gpio %u\n", __func__, top_spk_pamp_gpio);
+		else {
+			pr_debug("%s: enable Top spkr amp gpio\n", __func__);
+			gpio_direction_output(top_spk_pamp_gpio, 1);
+		}
+	} else {
+		pr_err("%s: ERROR : Invalid External Speaker Ampl GPIO."
+			" gpio = %u\n", __func__, spk_amp_gpio);
+		return;
+	}
+}
+
+static void msm_ext_spk_power_amp_on(u32 spk)
+{
+	if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
+
+		if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
+			(msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
+
+			pr_debug("%s() External Bottom Speaker Ampl already "
+				"turned on. spk = 0x%08x\n", __func__, spk);
+			return;
+		}
+
+		msm_ext_bottom_spk_pamp |= spk;
+
+		if ((msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_POS) &&
+			(msm_ext_bottom_spk_pamp & BOTTOM_SPK_AMP_NEG)) {
+
+			msm_enable_ext_spk_amp_gpio(bottom_spk_pamp_gpio);
+			pr_debug("%s: slepping 4 ms after turning on external "
+				" Bottom Speaker Ampl\n", __func__);
+			usleep_range(4000, 4000);
+		}
+
+	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+
+		if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+
+			pr_debug("%s() External Top Speaker Ampl already"
+				"turned on. spk = 0x%08x\n", __func__, spk);
+			return;
+		}
+
+		msm_ext_top_spk_pamp |= spk;
+
+		if ((msm_ext_top_spk_pamp & TOP_SPK_AMP_POS) &&
+			(msm_ext_top_spk_pamp & TOP_SPK_AMP_NEG)) {
+
+			msm_enable_ext_spk_amp_gpio(top_spk_pamp_gpio);
+			pr_debug("%s: sleeping 4 ms after turning on "
+				" external Top Speaker Ampl\n", __func__);
+			usleep_range(4000, 4000);
+		}
+	} else  {
+
+		pr_err("%s: ERROR : Invalid External Speaker Ampl. spk = 0x%08x\n",
+			__func__, spk);
+		return;
+	}
+}
+
+static void msm_ext_spk_power_amp_off(u32 spk)
+{
+	if (spk & (BOTTOM_SPK_AMP_POS | BOTTOM_SPK_AMP_NEG)) {
+
+		if (!msm_ext_bottom_spk_pamp)
+			return;
+
+		gpio_direction_output(bottom_spk_pamp_gpio, 0);
+		gpio_free(bottom_spk_pamp_gpio);
+		msm_ext_bottom_spk_pamp = 0;
+
+		pr_debug("%s: sleeping 4 ms after turning off external Bottom"
+			" Speaker Ampl\n", __func__);
+
+		usleep_range(4000, 4000);
+
+	} else if (spk & (TOP_SPK_AMP_POS | TOP_SPK_AMP_NEG)) {
+
+		if (!msm_ext_top_spk_pamp)
+			return;
+
+		gpio_direction_output(top_spk_pamp_gpio, 0);
+		gpio_free(top_spk_pamp_gpio);
+		msm_ext_top_spk_pamp = 0;
+
+		pr_debug("%s: sleeping 4 ms after turning off external Top"
+			" Spkaker Ampl\n", __func__);
+
+		usleep_range(4000, 4000);
+	} else  {
+
+		pr_err("%s: ERROR : Invalid Ext Spk Ampl. spk = 0x%08x\n",
+			__func__, spk);
+		return;
+	}
+}
+
+static void msm_ext_control(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+	pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
+	if (msm_spk_control == MPQ8064_SPK_ON) {
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
+	} else {
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Pos");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Bottom Neg");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Pos");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Top Neg");
+	}
+
+	snd_soc_dapm_sync(dapm);
+}
+
+static int msm_get_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_spk_control = %d", __func__, msm_spk_control);
+	ucontrol->value.integer.value[0] = msm_spk_control;
+	return 0;
+}
+static int msm_set_spk(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	pr_debug("%s()\n", __func__);
+	if (msm_spk_control == ucontrol->value.integer.value[0])
+		return 0;
+
+	msm_spk_control = ucontrol->value.integer.value[0];
+	msm_ext_control(codec);
+	return 1;
+}
+static int msm_spkramp_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *k, int event)
+{
+	pr_debug("%s() %x\n", __func__, SND_SOC_DAPM_EVENT_ON(event));
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
+			msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_POS);
+		else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
+			msm_ext_spk_power_amp_on(BOTTOM_SPK_AMP_NEG);
+		else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
+			msm_ext_spk_power_amp_on(TOP_SPK_AMP_POS);
+		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
+			msm_ext_spk_power_amp_on(TOP_SPK_AMP_NEG);
+		else {
+			pr_err("%s() Invalid Speaker Widget = %s\n",
+					__func__, w->name);
+			return -EINVAL;
+		}
+
+	} else {
+		if (!strncmp(w->name, "Ext Spk Bottom Pos", 18))
+			msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_POS);
+		else if (!strncmp(w->name, "Ext Spk Bottom Neg", 18))
+			msm_ext_spk_power_amp_off(BOTTOM_SPK_AMP_NEG);
+		else if (!strncmp(w->name, "Ext Spk Top Pos", 15))
+			msm_ext_spk_power_amp_off(TOP_SPK_AMP_POS);
+		else if  (!strncmp(w->name, "Ext Spk Top Neg", 15))
+			msm_ext_spk_power_amp_off(TOP_SPK_AMP_NEG);
+		else {
+			pr_err("%s() Invalid Speaker Widget = %s\n",
+					__func__, w->name);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
+				    bool dapm)
+{
+	pr_debug("%s: enable = %d\n", __func__, enable);
+	if (enable) {
+		clk_users++;
+		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+		if (clk_users != 1)
+			return 0;
+
+		if (codec_clk) {
+			clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
+			clk_enable(codec_clk);
+			tabla_mclk_enable(codec, 1, dapm);
+		} else {
+			pr_err("%s: Error setting Tabla MCLK\n", __func__);
+			clk_users--;
+			return -EINVAL;
+		}
+	} else {
+		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+		if (clk_users == 0)
+			return 0;
+		clk_users--;
+		if (!clk_users) {
+			pr_debug("%s: disabling MCLK. clk_users = %d\n",
+					 __func__, clk_users);
+			clk_disable(codec_clk);
+			tabla_mclk_enable(codec, 0, dapm);
+		}
+	}
+	return 0;
+}
+
+static int msm_mclk_event(struct snd_soc_dapm_widget *w,
+		struct snd_kcontrol *kcontrol, int event)
+{
+	pr_debug("%s: event = %d\n", __func__, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+
+		clk_users++;
+		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+
+		if (clk_users != 1)
+			return 0;
+
+		if (codec_clk) {
+			clk_set_rate(codec_clk, 12288000);
+			clk_enable(codec_clk);
+			tabla_mclk_enable(w->codec, 1, true);
+
+		} else {
+			pr_err("%s: Error setting Tabla MCLK\n", __func__);
+			clk_users--;
+			return -EINVAL;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+
+		pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+
+		if (clk_users == 0)
+			return 0;
+
+		clk_users--;
+
+		if (!clk_users) {
+			pr_debug("%s: disabling MCLK. clk_users = %d\n",
+					__func__, clk_users);
+
+			clk_disable(codec_clk);
+			tabla_mclk_enable(w->codec, 0, true);
+		}
+		break;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
+
+	SND_SOC_DAPM_SUPPLY("MCLK",  SND_SOC_NOPM, 0, 0,
+	msm_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SPK("Ext Spk Bottom Pos", msm_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Bottom Neg", msm_spkramp_event),
+
+	SND_SOC_DAPM_SPK("Ext Spk Top Pos", msm_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Top Neg", msm_spkramp_event),
+
+	SND_SOC_DAPM_MIC("Handset Mic", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route common_audio_map[] = {
+
+	{"RX_BIAS", NULL, "MCLK"},
+	{"LDO_H", NULL, "MCLK"},
+
+	/* Speaker path */
+	{"Ext Spk Bottom Pos", NULL, "LINEOUT1"},
+	{"Ext Spk Bottom Neg", NULL, "LINEOUT3"},
+
+	{"Ext Spk Top Pos", NULL, "LINEOUT2"},
+	{"Ext Spk Top Neg", NULL, "LINEOUT4"},
+
+	/* Microphone path */
+	{"AMIC1", NULL, "MIC BIAS1 Internal1"},
+	{"MIC BIAS1 Internal1", NULL, "Handset Mic"},
+
+	{"AMIC2", NULL, "MIC BIAS2 External"},
+	{"MIC BIAS2 External", NULL, "Headset Mic"},
+
+	/**
+	 * AMIC3 and AMIC4 inputs are connected to ANC microphones
+	 * These mics are biased differently on CDP and FLUID
+	 * routing entries below are based on bias arrangement
+	 * on FLUID.
+	 */
+	{"AMIC3", NULL, "MIC BIAS3 Internal1"},
+	{"MIC BIAS3 Internal1", NULL, "ANCRight Headset Mic"},
+
+	{"AMIC4", NULL, "MIC BIAS1 Internal2"},
+	{"MIC BIAS1 Internal2", NULL, "ANCLeft Headset Mic"},
+
+	{"HEADPHONE", NULL, "LDO_H"},
+};
+
+static const char *spk_function[] = {"Off", "On"};
+static const char *slim0_rx_ch_text[] = {"One", "Two"};
+static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
+
+static const struct soc_enum msm_enum[] = {
+	SOC_ENUM_SINGLE_EXT(2, spk_function),
+	SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
+	SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
+};
+
+static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_slim_0_rx_ch  = %d\n", __func__,
+			msm_slim_0_rx_ch);
+	ucontrol->value.integer.value[0] = msm_slim_0_rx_ch - 1;
+	return 0;
+}
+
+static int msm_slim_0_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_slim_0_rx_ch = %d\n", __func__,
+			msm_slim_0_rx_ch);
+	return 1;
+}
+
+static int msm_slim_0_tx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_slim_0_tx_ch  = %d\n", __func__,
+			msm_slim_0_tx_ch);
+	ucontrol->value.integer.value[0] = msm_slim_0_tx_ch - 1;
+	return 0;
+}
+
+static int msm_slim_0_tx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_slim_0_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_slim_0_tx_ch = %d\n", __func__,
+			msm_slim_0_tx_ch);
+	return 1;
+}
+
+static const struct snd_kcontrol_new tabla_msm_controls[] = {
+	SOC_ENUM_EXT("Speaker Function", msm_enum[0], msm_get_spk,
+		msm_set_spk),
+	SOC_ENUM_EXT("SLIM_0_RX Channels", msm_enum[1],
+		msm_slim_0_rx_ch_get, msm_slim_0_rx_ch_put),
+	SOC_ENUM_EXT("SLIM_0_TX Channels", msm_enum[2],
+		msm_slim_0_tx_ch_get, msm_slim_0_tx_ch_put),
+};
+
+static void *def_tabla_mbhc_cal(void)
+{
+	void *tabla_cal;
+	struct tabla_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_low, *btn_high;
+	u8 *n_ready, *n_cic, *gain;
+
+	tabla_cal = kzalloc(TABLA_MBHC_CAL_SIZE(TABLA_MBHC_DEF_BUTTONS,
+						TABLA_MBHC_DEF_RLOADS),
+			    GFP_KERNEL);
+	if (!tabla_cal) {
+		pr_err("%s: out of memory\n", __func__);
+		return NULL;
+	}
+
+#define S(X, Y) ((TABLA_MBHC_CAL_GENERAL_PTR(tabla_cal)->X) = (Y))
+	S(t_ldoh, 100);
+	S(t_bg_fast_settle, 100);
+	S(t_shutdown_plug_rem, 255);
+	S(mbhc_nsa, 4);
+	S(mbhc_navg, 4);
+#undef S
+#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_DET_PTR(tabla_cal)->X) = (Y))
+	S(mic_current, TABLA_PID_MIC_5_UA);
+	S(hph_current, TABLA_PID_MIC_5_UA);
+	S(t_mic_pid, 100);
+	S(t_ins_complete, 250);
+	S(t_ins_retry, 200);
+#undef S
+#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
+	S(v_no_mic, 30);
+	S(v_hs_max, 1550);
+#undef S
+#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
+	S(c[0], 62);
+	S(c[1], 124);
+	S(nc, 1);
+	S(n_meas, 3);
+	S(mbhc_nsc, 11);
+	S(n_btn_meas, 1);
+	S(n_btn_con, 2);
+	S(num_btn, TABLA_MBHC_DEF_BUTTONS);
+	S(v_btn_press_delta_sta, 100);
+	S(v_btn_press_delta_cic, 50);
+#undef S
+	btn_cfg = TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal);
+	btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
+	btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
+	btn_low[0] = -50;
+	btn_high[0] = 10;
+	btn_low[1] = 11;
+	btn_high[1] = 38;
+	btn_low[2] = 39;
+	btn_high[2] = 64;
+	btn_low[3] = 65;
+	btn_high[3] = 91;
+	btn_low[4] = 92;
+	btn_high[4] = 115;
+	btn_low[5] = 116;
+	btn_high[5] = 141;
+	btn_low[6] = 142;
+	btn_high[6] = 163;
+	btn_low[7] = 164;
+	btn_high[7] = 250;
+	n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
+	n_ready[0] = 48;
+	n_ready[1] = 38;
+	n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
+	n_cic[0] = 60;
+	n_cic[1] = 47;
+	gain = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_GAIN);
+	gain[0] = 11;
+	gain[1] = 9;
+
+	return tabla_cal;
+}
+
+static int msm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+	unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+
+	pr_debug("%s: ch=%d\n", __func__,
+					msm_slim_0_rx_ch);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				msm_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai, 0, 0,
+				msm_slim_0_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+	} else {
+		ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, tx_ch, &rx_ch_cnt , rx_ch);
+		if (ret < 0) {
+			pr_err("%s: failed to get codec chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+				msm_slim_0_tx_ch, tx_ch, 0 , 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map\n", __func__);
+			goto end;
+		}
+		ret = snd_soc_dai_set_channel_map(codec_dai,
+				msm_slim_0_tx_ch, tx_ch, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set codec channel map\n",
+								__func__);
+			goto end;
+		}
+
+
+	}
+end:
+	return ret;
+}
+
+static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int err;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+
+	pr_debug("%s(), dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+	/*if (machine_is_msm_liquid()) {
+		top_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(19));
+		bottom_spk_pamp_gpio = (PM8921_GPIO_PM_TO_SYS(18));
+	}*/
+
+	rtd->pmdown_time = 0;
+
+	err = snd_soc_add_controls(codec, tabla_msm_controls,
+				ARRAY_SIZE(tabla_msm_controls));
+	if (err < 0)
+		return err;
+
+	snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
+				ARRAY_SIZE(msm_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, common_audio_map,
+		ARRAY_SIZE(common_audio_map));
+
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Bottom Neg");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Top Neg");
+
+	snd_soc_dapm_sync(dapm);
+
+	err = snd_soc_jack_new(codec, "Headset Jack",
+		(SND_JACK_HEADSET | SND_JACK_OC_HPHL | SND_JACK_OC_HPHR),
+		&hs_jack);
+	if (err) {
+		pr_err("failed to create new jack\n");
+		return err;
+	}
+
+	err = snd_soc_jack_new(codec, "Button Jack",
+			       TABLA_JACK_BUTTON_MASK, &button_jack);
+	if (err) {
+		pr_err("failed to create new jack\n");
+		return err;
+	}
+
+	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
+
+	err = tabla_hs_detect(codec, &mbhc_cfg);
+
+	return err;
+}
+
+static struct snd_soc_dsp_link lpa_fe_media = {
+	.playback = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link fe_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link slimbus0_hl_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static struct snd_soc_dsp_link int_fm_hl_media = {
+	.playback = true,
+	.capture = true,
+	.trigger = {
+		SND_SOC_DSP_TRIGGER_POST,
+		SND_SOC_DSP_TRIGGER_POST
+	},
+};
+
+static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_slim_0_rx_ch;
+
+	return 0;
+}
+
+static int msm_slim_0_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_slim_0_tx_ch;
+
+	return 0;
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm_hdmi_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+			channels->min, channels->max);
+
+	rate->min = rate->max = 48000;
+
+	return 0;
+}
+
+static int msm_startup(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return 0;
+}
+
+static void msm_shutdown(struct snd_pcm_substream *substream)
+{
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static struct snd_soc_ops msm_be_ops = {
+	.startup = msm_startup,
+	.hw_params = msm_hw_params,
+	.shutdown = msm_shutdown,
+};
+
+static int mpq8064_sec_i2s_rx_free_gpios(void)
+{
+	int	i;
+	for (i = 0; i < ARRAY_SIZE(sec_i2s_rx_gpio); i++)
+		gpio_free(sec_i2s_rx_gpio[i].gpio_no);
+	return 0;
+}
+
+static int mpq8064_sec_i2s_rx_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+
+	int rate = params_rate(params);
+	int bit_clk_set = 0;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			bit_clk_set = I2S_MCLK_RATE/(rate * 2 * 16);
+			clk_set_rate(sec_i2s_rx_bit_clk, bit_clk_set);
+			break;
+		case SNDRV_PCM_FORMAT_S24_LE:
+			bit_clk_set = I2S_MCLK_RATE/(rate * 2 * 24);
+			clk_set_rate(sec_i2s_rx_bit_clk, bit_clk_set);
+			break;
+		default:
+			pr_err("wrong format\n");
+			break;
+		}
+	}
+	return 0;
+}
+
+static void mpq8064_sec_i2s_rx_shutdown(struct snd_pcm_substream *substream)
+{
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (sec_i2s_rx_bit_clk) {
+			clk_disable(sec_i2s_rx_bit_clk);
+			clk_put(sec_i2s_rx_bit_clk);
+			sec_i2s_rx_bit_clk = NULL;
+		}
+		if (sec_i2s_rx_osr_clk) {
+			clk_disable(sec_i2s_rx_osr_clk);
+			clk_put(sec_i2s_rx_osr_clk);
+			sec_i2s_rx_osr_clk = NULL;
+		}
+		mpq8064_sec_i2s_rx_free_gpios();
+	}
+	pr_info("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+}
+
+static int configure_sec_i2s_rx_gpio(void)
+{
+	int rtn;
+	int i;
+	int j;
+	for (i = 0; i < ARRAY_SIZE(sec_i2s_rx_gpio); i++) {
+		rtn = gpio_request(sec_i2s_rx_gpio[i].gpio_no,
+				sec_i2s_rx_gpio[i].gpio_name);
+		pr_debug("%s: gpio = %d, gpio name = %s, rtn = %d\n",
+				__func__,
+				sec_i2s_rx_gpio[i].gpio_no,
+				sec_i2s_rx_gpio[i].gpio_name,
+					rtn);
+		if (rtn) {
+			pr_err("%s: Failed to request gpio %d\n",
+				__func__,
+			sec_i2s_rx_gpio[i].gpio_no);
+			for (j = i; j >= 0; j--)
+				gpio_free(sec_i2s_rx_gpio[j].gpio_no);
+
+			goto err;
+		}
+	}
+err:
+	return rtn;
+}
+
+static int mpq8064_sec_i2s_rx_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		configure_sec_i2s_rx_gpio();
+		sec_i2s_rx_osr_clk = clk_get(cpu_dai->dev, "osr_clk");
+		if (IS_ERR(sec_i2s_rx_osr_clk)) {
+			pr_err("Failed to get sec_i2s_rx_osr_clk\n");
+			return PTR_ERR(sec_i2s_rx_osr_clk);
+		}
+		clk_set_rate(sec_i2s_rx_osr_clk, I2S_MCLK_RATE);
+		clk_enable(sec_i2s_rx_osr_clk);
+		sec_i2s_rx_bit_clk = clk_get(cpu_dai->dev, "bit_clk");
+		if (IS_ERR(sec_i2s_rx_bit_clk)) {
+			pr_err("Failed to get sec i2s osr_clk\n");
+			clk_disable(sec_i2s_rx_osr_clk);
+			clk_put(sec_i2s_rx_osr_clk);
+			return PTR_ERR(sec_i2s_rx_bit_clk);
+		}
+		clk_set_rate(sec_i2s_rx_bit_clk, 1);
+		ret = clk_enable(sec_i2s_rx_bit_clk);
+		if (ret != 0) {
+			pr_err("Unable to enable sec i2s rx_bit_clk\n");
+			clk_put(sec_i2s_rx_bit_clk);
+			clk_disable(sec_i2s_rx_osr_clk);
+			clk_put(sec_i2s_rx_osr_clk);
+			return ret;
+		}
+		ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
+		if (ret < 0)
+			pr_err("set format for codec dai failed\n");
+	}
+	pr_debug("%s: ret = %d\n", __func__, ret);
+	pr_info("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	return ret;
+}
+
+static struct snd_soc_ops mpq8064_sec_i2s_rx_be_ops = {
+	.startup = mpq8064_sec_i2s_rx_startup,
+	.shutdown = mpq8064_sec_i2s_rx_shutdown,
+	.hw_params = mpq8064_sec_i2s_rx_hw_params,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_dai[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSM8960 Media1",
+		.stream_name = "MultiMedia1",
+		.cpu_dai_name	= "MultiMedia1",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+	},
+	{
+		.name = "MSM8960 Media2",
+		.stream_name = "MultiMedia2",
+		.cpu_dai_name	= "MultiMedia2",
+		.platform_name  = "msm-pcm-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+	},
+	{
+		.name = "Circuit-Switch Voice",
+		.stream_name = "CS-Voice",
+		.cpu_dai_name   = "CS-VOICE",
+		.platform_name  = "msm-pcm-voice",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_CS_VOICE,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.cpu_dai_name	= "VoIP",
+		.platform_name  = "msm-voip-dsp",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.be_id = MSM_FRONTEND_DAI_VOIP,
+	},
+	{
+		.name = "MSM8960 LPA",
+		.stream_name = "LPA",
+		.cpu_dai_name	= "MultiMedia3",
+		.platform_name  = "msm-pcm-lpa",
+		.dynamic = 1,
+		.dsp_link = &lpa_fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+	},
+	/* Hostless PMC purpose */
+	{
+		.name = "SLIMBUS_0 Hostless",
+		.stream_name = "SLIMBUS_0 Hostless",
+		.cpu_dai_name	= "SLIMBUS0_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &slimbus0_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
+	{
+		.name = "INT_FM Hostless",
+		.stream_name = "INT_FM Hostless",
+		.cpu_dai_name	= "INT_FM_HOSTLESS",
+		.platform_name  = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &int_fm_hl_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
+	{
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.cpu_dai_name = "msm-dai-q6.241",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.cpu_dai_name = "msm-dai-q6.240",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.platform_name  = "msm-pcm-afe",
+		.ignore_suspend = 1,
+	},
+	{
+		.name = "MSM8960 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name   = "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.dsp_link = &lpa_fe_media,
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	{
+		.name = "Voice Stub",
+		.stream_name = "Voice Stub",
+		.cpu_dai_name = "VOICE_STUB",
+		.platform_name = "msm-pcm-hostless",
+		.dynamic = 1,
+		.dsp_link = &fe_media,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* .be_id = do not care */
+	},
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_SLIMBUS_0_RX,
+		.stream_name = "Slimbus Playback",
+		.cpu_dai_name = "msm-dai-q6.16384",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_rx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+		.init = &msm_audrx_init,
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_0_TX,
+		.stream_name = "Slimbus Capture",
+		.cpu_dai_name = "msm-dai-q6.16385",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_tx1",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
+	{
+		.name = LPASS_BE_SEC_I2S_RX,
+		.stream_name = "Secondary I2S Playback",
+		.cpu_dai_name = "msm-dai-q6.4",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "cs8427-spdif.5-0014",
+		.codec_dai_name = "spdif_rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SEC_I2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &mpq8064_sec_i2s_rx_be_ops,
+	},
+	{
+		.name = LPASS_BE_INT_FM_RX,
+		.stream_name = "Internal FM Playback",
+		.cpu_dai_name = "msm-dai-q6.12292",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+	},
+	{
+		.name = LPASS_BE_INT_FM_TX,
+		.stream_name = "Internal FM Capture",
+		.cpu_dai_name = "msm-dai-q6.12293",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_INT_FM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+	},
+	/* HDMI BACK END DAI Link */
+	{
+		.name = LPASS_BE_HDMI,
+		.stream_name = "HDMI Playback",
+		.cpu_dai_name = "msm-dai-q6-hdmi.8",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.no_codec = 1,
+		.be_id = MSM_BACKEND_DAI_HDMI_RX,
+		.be_hw_params_fixup = msm_hdmi_be_hw_params_fixup,
+	},
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.cpu_dai_name = "msm-dai-q6.224",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_codec = 1,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.cpu_dai_name = "msm-dai-q6.225",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_codec = 1,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+	},
+};
+
+
+static struct snd_soc_card snd_soc_card_msm = {
+	.name		= "mpq8064-tabla-snd-card",
+	.dai_link	= msm_dai,
+	.num_links	= ARRAY_SIZE(msm_dai),
+};
+
+static struct platform_device *msm_snd_device;
+
+static int msm_configure_headset_mic_gpios(void)
+{
+	int ret;
+	struct pm_gpio param = {
+		.direction      = PM_GPIO_DIR_OUT,
+		.output_buffer  = PM_GPIO_OUT_BUF_CMOS,
+		.output_value   = 1,
+		.pull	   = PM_GPIO_PULL_NO,
+		.vin_sel	= PM_GPIO_VIN_S4,
+		.out_strength   = PM_GPIO_STRENGTH_MED,
+		.function       = PM_GPIO_FUNC_NORMAL,
+	};
+
+	ret = gpio_request(PM8921_GPIO_PM_TO_SYS(23), "AV_SWITCH");
+	if (ret) {
+		pr_err("%s: Failed to request gpio %d\n", __func__,
+			PM8921_GPIO_PM_TO_SYS(23));
+		return ret;
+	}
+
+	ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(23), &param);
+	if (ret)
+		pr_err("%s: Failed to configure gpio %d\n", __func__,
+			PM8921_GPIO_PM_TO_SYS(23));
+	else
+		gpio_direction_output(PM8921_GPIO_PM_TO_SYS(23), 0);
+
+	ret = gpio_request(PM8921_GPIO_PM_TO_SYS(35), "US_EURO_SWITCH");
+	if (ret) {
+		pr_err("%s: Failed to request gpio %d\n", __func__,
+			PM8921_GPIO_PM_TO_SYS(35));
+		gpio_free(PM8921_GPIO_PM_TO_SYS(23));
+		return ret;
+	}
+	ret = pm8xxx_gpio_config(PM8921_GPIO_PM_TO_SYS(35), &param);
+	if (ret)
+		pr_err("%s: Failed to configure gpio %d\n", __func__,
+			PM8921_GPIO_PM_TO_SYS(35));
+	else
+		gpio_direction_output(PM8921_GPIO_PM_TO_SYS(35), 0);
+
+	return 0;
+}
+static void msm_free_headset_mic_gpios(void)
+{
+	if (msm_headset_gpios_configured) {
+		gpio_free(PM8921_GPIO_PM_TO_SYS(23));
+		gpio_free(PM8921_GPIO_PM_TO_SYS(35));
+	}
+}
+
+static int __init msm_audio_init(void)
+{
+	int ret;
+
+	if (socinfo_get_id() != 130) {
+		pr_err("%s: Not the right machine type\n", __func__);
+		return -ENODEV;
+	}
+
+	mbhc_cfg.calibration = def_tabla_mbhc_cal();
+	if (!mbhc_cfg.calibration) {
+		pr_err("Calibration data allocation failed\n");
+		return -ENOMEM;
+	}
+
+	msm_snd_device = platform_device_alloc("soc-audio", 0);
+	if (!msm_snd_device) {
+		pr_err("Platform device allocation failed\n");
+		kfree(mbhc_cfg.calibration);
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(msm_snd_device, &snd_soc_card_msm);
+	ret = platform_device_add(msm_snd_device);
+	if (ret) {
+		platform_device_put(msm_snd_device);
+		kfree(mbhc_cfg.calibration);
+		return ret;
+	}
+
+	if (msm_configure_headset_mic_gpios()) {
+		pr_err("%s Fail to configure headset mic gpios\n", __func__);
+		msm_headset_gpios_configured = 0;
+	} else
+		msm_headset_gpios_configured = 1;
+
+	return ret;
+
+}
+module_init(msm_audio_init);
+
+static void __exit msm_audio_exit(void)
+{
+	if (socinfo_get_id() != 130) {
+		pr_err("%s: Not the right machine type\n", __func__);
+		return ;
+	}
+	msm_free_headset_mic_gpios();
+	platform_device_unregister(msm_snd_device);
+	kfree(mbhc_cfg.calibration);
+}
+module_exit(msm_audio_exit);
+
+MODULE_DESCRIPTION("ALSA SoC mpq8064");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 11ac330..b3fb7c1 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -25,6 +25,7 @@
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/control.h>
+#include <sound/q6asm.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <linux/android_pmem.h>
@@ -188,7 +189,7 @@
 	struct asm_aac_cfg aac_cfg;
 	int ret;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("compressed stream prepare\n");
 	prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
 	prtd->pcm_irq_pos = 0;
@@ -220,6 +221,10 @@
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed\n", __func__);
 		break;
+	case SND_AUDIOCODEC_AC3_PASS_THROUGH:
+		pr_debug("compressd playback, no need to send"
+			" the decoder params\n");
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -234,6 +239,7 @@
 {
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
 
@@ -241,6 +247,12 @@
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		prtd->pcm_irq_pos = 0;
+		if (compr->info.codec_param.codec.id ==
+				SND_AUDIOCODEC_AC3_PASS_THROUGH) {
+			msm_pcm_routing_reg_psthr_stream(
+				soc_prtd->dai_link->be_id,
+				prtd->session_id, substream->stream);
+		}
 	case SNDRV_PCM_TRIGGER_RESUME:
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		pr_debug("%s: Trigger start\n", __func__);
@@ -277,13 +289,13 @@
 	compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
 	compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
 	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
+	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3_PASS_THROUGH;
 	/* Add new codecs here */
 }
 
 static int msm_compr_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct compr_audio *compr;
 	struct msm_audio *prtd;
 	int ret = 0;
@@ -323,8 +335,6 @@
 	pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
 
 	prtd->session_id = prtd->audio_client->session;
-	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
-			prtd->session_id, substream->stream);
 
 	prtd->cmd_ack = 1;
 
@@ -464,6 +474,7 @@
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct compr_audio *compr = runtime->private_data;
 	struct msm_audio *prtd = &compr->prtd;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
@@ -476,10 +487,26 @@
 	else
 		return -EINVAL;
 
-	ret = q6asm_open_write(prtd->audio_client, compr->codec);
-	if (ret < 0) {
-		pr_err("%s: Session out open failed\n", __func__);
-		return -ENOMEM;
+	switch (compr->info.codec_param.codec.id) {
+	case SND_AUDIOCODEC_AC3_PASS_THROUGH:
+		ret = q6asm_open_write_compressed(prtd->audio_client,
+					compr->codec);
+		if (ret < 0) {
+			pr_err("%s: compressed Session out open failed\n",
+					__func__);
+			return -ENOMEM;
+		}
+		break;
+	default:
+		ret = q6asm_open_write(prtd->audio_client, compr->codec);
+		if (ret < 0) {
+			pr_err("%s: Session out open failed\n", __func__);
+			return -ENOMEM;
+		}
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
+
+		break;
 	}
 	ret = q6asm_set_io_mode(prtd->audio_client, ASYNC_IO_MODE);
 	if (ret < 0) {
@@ -577,6 +604,10 @@
 			pr_debug("SND_AUDIOCODEC_AAC\n");
 			compr->codec = FORMAT_MPEG4_AAC;
 			break;
+		case SND_AUDIOCODEC_AC3_PASS_THROUGH:
+			pr_debug("SND_AUDIOCODEC_AC3_PASS_THROUGH\n");
+			compr->codec = FORMAT_AC3;
+			break;
 		default:
 			pr_debug("FORMAT_LINEAR_PCM\n");
 			compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index f735748..4bb9282 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -48,27 +48,24 @@
 
 static int fm_switch_enable;
 
-#define INT_FM_RX_VOL_MAX_STEPS 100
-#define INT_FM_RX_VOL_GAIN 2000
-
-static int msm_route_fm_vol_control;
-static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
-			INT_FM_RX_VOL_MAX_STEPS, 0);
-
-#define INT_RX_VOL_MAX_STEPS 100
+#define INT_RX_VOL_MAX_STEPS 0x2000
 #define INT_RX_VOL_GAIN 0x2000
 
+static int msm_route_fm_vol_control;
+static const DECLARE_TLV_DB_LINEAR(fm_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
+
 static int msm_route_lpa_vol_control;
-static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
-			INT_RX_VOL_MAX_STEPS, 0);
+static const DECLARE_TLV_DB_LINEAR(lpa_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
 
 static int msm_route_multimedia2_vol_control;
-static const DECLARE_TLV_DB_SCALE(multimedia2_rx_vol_gain, 0,
-			INT_RX_VOL_MAX_STEPS, 0);
+static const DECLARE_TLV_DB_LINEAR(multimedia2_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
 
 static int msm_route_compressed_vol_control;
-static const DECLARE_TLV_DB_SCALE(compressed_rx_vol_gain, 0,
-			INT_RX_VOL_MAX_STEPS, 0);
+static const DECLARE_TLV_DB_LINEAR(compressed_rx_vol_gain, 0,
+			INT_RX_VOL_MAX_STEPS);
 
 
 
@@ -173,6 +170,46 @@
 			payload.num_copps, payload.copp_ids, 0);
 }
 
+void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
+					int stream_type)
+{
+	int i, session_type, path_type, port_type;
+	u32 mode = 0;
+
+	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
+		/* bad ID assigned in machine driver */
+		pr_err("%s: bad MM ID\n", __func__);
+		return;
+	}
+
+	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
+		session_type = SESSION_TYPE_RX;
+		path_type = ADM_PATH_PLAYBACK;
+		port_type = MSM_AFE_PORT_TYPE_RX;
+	} else {
+		session_type = SESSION_TYPE_TX;
+		path_type = ADM_PATH_LIVE_REC;
+		port_type = MSM_AFE_PORT_TYPE_TX;
+	}
+
+	mutex_lock(&routing_lock);
+
+	fe_dai_map[fedai_id][session_type] = dspst_id;
+	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
+		if ((afe_get_port_type(msm_bedais[i].port_id) ==
+			port_type) && msm_bedais[i].active &&
+			(test_bit(fedai_id,
+			&msm_bedais[i].fe_sessions))) {
+
+			mode = afe_get_port_type(msm_bedais[i].port_id);
+			adm_connect_afe_port(mode, dspst_id,
+				msm_bedais[i].port_id);
+			break;
+		}
+	}
+	mutex_unlock(&routing_lock);
+}
+
 void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
 {
 	int i, session_type, path_type, port_type;
@@ -1148,7 +1185,7 @@
 
 static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
 	SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
-	INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
+	INT_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
 	msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
 };
 
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index eae2128..eb6db4b 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -90,6 +90,9 @@
  */
 void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id,
 	int stream_type);
+void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id,
+		int stream_type);
+
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type);
 
 int lpa_set_volume(unsigned volume);
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 2301472..aec1bb2 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -691,7 +691,7 @@
 	int ret = 0;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
-	uint32_t media_type = 0;
+	int32_t media_type = 0;
 	uint32_t rate_type = 0;
 
 	mutex_lock(&prtd->lock);
@@ -988,7 +988,7 @@
 static int voip_get_media_type(uint32_t mode,
 				unsigned int samp_rate)
 {
-	uint32_t media_type;
+	int32_t media_type;
 
 	pr_debug("%s: mode=%d, samp_rate=%d\n", __func__,
 		mode, samp_rate);
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index f814a21..a6a3266 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -84,11 +84,12 @@
 	spin_lock_irq(&the_locks.mixer_lock);
 	change = (msm_vol_ctl.volume != volume);
 	if (change) {
-		msm_vol_ctl.update = 1;
 		msm_vol_ctl.volume = volume;
+		msm_audio_volume_update(PCMPLAYBACK_DECODERID,
+				msm_vol_ctl.volume, msm_vol_ctl.pan);
 	}
 	spin_unlock_irq(&the_locks.mixer_lock);
-	return change;
+	return 0;
 }
 
 static int snd_msm_device_info(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/msm/msm7k-pcm.c b/sound/soc/msm/msm7k-pcm.c
index 6ef924f..1f23a92 100644
--- a/sound/soc/msm/msm7k-pcm.c
+++ b/sound/soc/msm/msm7k-pcm.c
@@ -414,11 +414,12 @@
 		return ret;
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		msm_vol_ctl.update = 1; /* Update Volume, with Cached value */
 		runtime->hw = msm_pcm_playback_hardware;
 		prtd->dir = SNDRV_PCM_STREAM_PLAYBACK;
 		prtd->playback_substream = substream;
 		prtd->eos_ack = 0;
+		ret = msm_audio_volume_update(PCMPLAYBACK_DECODERID,
+			msm_vol_ctl.volume, msm_vol_ctl.pan);
 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		runtime->hw = msm_pcm_capture_hardware;
 		prtd->dir = SNDRV_PCM_STREAM_CAPTURE;
@@ -468,12 +469,6 @@
 		alsa_audio_configure(prtd);
 		mutex_unlock(&the_locks.lock);
 	}
-	if ((prtd->running) && (msm_vol_ctl.update)) {
-		rc = msm_audio_volume_update(PCMPLAYBACK_DECODERID,
-				msm_vol_ctl.volume, msm_vol_ctl.pan);
-		msm_vol_ctl.update = 0;
-	}
-
 	return  rc;
 }
 
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index a081253..e254cce 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -13,10 +13,9 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
+#include <linux/mfd/pm8xxx/misc.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
-#include <linux/mfd/pm8xxx/pm8921.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/soc.h>
@@ -31,28 +30,12 @@
 
 /* 8930 machine driver */
 
-#define PM8921_GPIO_BASE		NR_GPIO_IRQS
-#define PM8921_GPIO_PM_TO_SYS(pm_gpio)  (pm_gpio - 1 + PM8921_GPIO_BASE)
-
 #define MSM8930_SPK_ON 1
 #define MSM8930_SPK_OFF 0
 
-#define msm8930_SLIM_0_RX_MAX_CHANNELS		2
-#define msm8930_SLIM_0_TX_MAX_CHANNELS		4
-
 #define BTSCO_RATE_8KHZ 8000
 #define BTSCO_RATE_16KHZ 16000
 
-#define BOTTOM_SPK_AMP_POS	0x1
-#define BOTTOM_SPK_AMP_NEG	0x2
-#define TOP_SPK_AMP_POS		0x4
-#define TOP_SPK_AMP_NEG		0x8
-
-#define GPIO_AUX_PCM_DOUT 63
-#define GPIO_AUX_PCM_DIN 64
-#define GPIO_AUX_PCM_SYNC 65
-#define GPIO_AUX_PCM_CLK 66
-
 #define SITAR_EXT_CLK_RATE 12288000
 
 #define SITAR_MBHC_DEF_BUTTONS 3
@@ -72,17 +55,7 @@
 
 static struct snd_soc_jack hs_jack;
 static struct snd_soc_jack button_jack;
-
-struct sitar_mbhc_calibration sitar_calib = {
-	.bias = SITAR_MICBIAS2,
-	.tldoh = 100,
-	.bg_fast_settle = 100,
-	.mic_current = SITAR_PID_MIC_5_UA,
-	.mic_pid = 100,
-	.hph_current = SITAR_PID_MIC_5_UA,
-	.setup_plug_removal_delay = 1000000,
-	.shutdown_plug_removal = 100000,
-};
+static void *sitar_mbhc_cal;
 
 static void msm8930_ext_control(struct snd_soc_codec *codec)
 {
@@ -91,10 +64,10 @@
 	pr_debug("%s: msm8930_spk_control = %d", __func__, msm8930_spk_control);
 	if (msm8930_spk_control == MSM8930_SPK_ON) {
 		snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
-		snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+		snd_soc_dapm_enable_pin(dapm, "Ext Spk left Neg");
 	} else {
 		snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Pos");
-		snd_soc_dapm_disable_pin(dapm, "Ext Spk Right Pos");
+		snd_soc_dapm_disable_pin(dapm, "Ext Spk Left Neg");
 	}
 
 	snd_soc_dapm_sync(dapm);
@@ -128,6 +101,7 @@
 	/* TODO: add external speaker power amps support */
 	return 0;
 }
+
 int msm8930_enable_codec_ext_clk(
 		struct snd_soc_codec *codec, int enable)
 {
@@ -140,10 +114,10 @@
 
 		if (codec_clk) {
 			clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
-			clk_enable(codec_clk);
+			clk_prepare_enable(codec_clk);
 			sitar_mclk_enable(codec, 1);
 		} else {
-			pr_err("%s: Error setting Tabla MCLK\n", __func__);
+			pr_err("%s: Error setting Sitar MCLK\n", __func__);
 			clk_users--;
 			return -EINVAL;
 		}
@@ -155,7 +129,7 @@
 		if (!clk_users) {
 			pr_debug("%s: disabling MCLK. clk_users = %d\n",
 					 __func__, clk_users);
-			clk_disable(codec_clk);
+			clk_disable_unprepare(codec_clk);
 			sitar_mclk_enable(codec, 0);
 		}
 	}
@@ -182,9 +156,8 @@
 	msm8930_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_SPK("Ext Spk Left Pos", msm8930_spkramp_event),
-	SND_SOC_DAPM_SPK("Ext Spk Right Pos", msm8930_spkramp_event),
+	SND_SOC_DAPM_SPK("Ext Spk Left Neg", NULL),
 
-	SND_SOC_DAPM_MIC("Handset Mic", NULL),
 	SND_SOC_DAPM_MIC("Headset Mic", NULL),
 	SND_SOC_DAPM_MIC("Digital Mic1", NULL),
 	SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
@@ -207,15 +180,18 @@
 
 	/* Speaker path */
 	{"Ext Spk Left Pos", NULL, "LINEOUT1"},
-	{"Ext Spk Right Pos", NULL, "LINEOUT2"},
+	{"Ext Spk Left Neg", NULL, "LINEOUT2"},
 
-
+	/* Headset Mic */
 	{"AMIC2", NULL, "MIC BIAS2 Internal1"},
 	{"MIC BIAS2 Internal1", NULL, "Headset Mic"},
 
 	/* Microphone path */
-	{"AMIC1", NULL, "MIC BIAS1 Internal1"},
-	{"MIC BIAS1 Internal1", NULL, "Handset Mic"},
+	{"AMIC1", NULL, "MIC BIAS2 Internal1"},
+	{"MIC BIAS2 Internal1", NULL, "ANCLeft Headset Mic"},
+
+	{"AMIC3", NULL, "MIC BIAS2 Internal1"},
+	{"MIC BIAS2 Internal1", NULL, "ANCRight Headset Mic"},
 
 	{"HEADPHONE", NULL, "LDO_H"},
 
@@ -227,7 +203,7 @@
 	/**
 	 * Digital Mic1. Front Bottom left Digital Mic on Fluid and MTP.
 	 * Digital Mic GM5 on CDP mainboard.
-	 * Conncted to DMIC2 Input on Tabla codec.
+	 * Conncted to DMIC2 Input on Sitar codec.
 	 */
 	{"DMIC1", NULL, "MIC BIAS1 External"},
 	{"MIC BIAS1 External", NULL, "Digital Mic1"},
@@ -235,25 +211,25 @@
 	/**
 	 * Digital Mic2. Front Bottom right Digital Mic on Fluid and MTP.
 	 * Digital Mic GM6 on CDP mainboard.
-	 * Conncted to DMIC1 Input on Tabla codec.
+	 * Conncted to DMIC1 Input on Sitar codec.
 	 */
 	{"DMIC2", NULL, "MIC BIAS1 External"},
 	{"MIC BIAS1 External", NULL, "Digital Mic2"},
 	/**
 	 * Digital Mic3. Back Bottom Digital Mic on Fluid.
 	 * Digital Mic GM1 on CDP mainboard.
-	 * Conncted to DMIC4 Input on Tabla codec.
+	 * Conncted to DMIC4 Input on Sitar codec.
 	 */
-	{"DMIC3", NULL, "MIC BIAS2 External"},
-	{"MIC BIAS2 External", NULL, "Digital Mic3"},
+	{"DMIC3", NULL, "MIC BIAS1 External"},
+	{"MIC BIAS1 External", NULL, "Digital Mic3"},
 
 	/**
 	 * Digital Mic4. Back top Digital Mic on Fluid.
 	 * Digital Mic GM2 on CDP mainboard.
-	 * Conncted to DMIC3 Input on Tabla codec.
+	 * Conncted to DMIC3 Input on Sitar codec.
 	 */
-	{"DMIC4", NULL, "MIC BIAS2 External"},
-	{"MIC BIAS2 External", NULL, "Digital Mic4"},
+	{"DMIC4", NULL, "MIC BIAS1 External"},
+	{"MIC BIAS1 External", NULL, "Digital Mic4"},
 
 
 };
@@ -277,7 +253,7 @@
 	struct snd_ctl_elem_value *ucontrol)
 {
 	pr_debug("%s: msm8930_slim_0_rx_ch  = %d\n", __func__,
-		 msm8930_slim_0_rx_ch);
+		msm8930_slim_0_rx_ch);
 	ucontrol->value.integer.value[0] = msm8930_slim_0_rx_ch - 1;
 	return 0;
 }
@@ -288,7 +264,7 @@
 	msm8930_slim_0_rx_ch = ucontrol->value.integer.value[0] + 1;
 
 	pr_debug("%s: msm8930_slim_0_rx_ch = %d\n", __func__,
-		 msm8930_slim_0_rx_ch);
+		msm8930_slim_0_rx_ch);
 	return 1;
 }
 
@@ -364,6 +340,83 @@
 	return 0;
 }
 
+static void *def_sitar_mbhc_cal(void)
+{
+	void *sitar_cal;
+	struct sitar_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_low, *btn_high;
+	u8 *n_ready, *n_cic, *gain;
+
+	sitar_cal = kzalloc(SITAR_MBHC_CAL_SIZE(SITAR_MBHC_DEF_BUTTONS,
+				SITAR_MBHC_DEF_RLOADS),
+				GFP_KERNEL);
+	if (!sitar_cal) {
+		pr_err("%s: out of memory\n", __func__);
+		return NULL;
+	}
+
+#define S(X, Y) ((SITAR_MBHC_CAL_GENERAL_PTR(sitar_cal)->X) = (Y))
+	S(t_ldoh, 100);
+	S(t_bg_fast_settle, 100);
+	S(t_shutdown_plug_rem, 255);
+	S(mbhc_nsa, 4);
+	S(mbhc_navg, 4);
+#undef S
+#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_DET_PTR(sitar_cal)->X) = (Y))
+	S(mic_current, SITAR_PID_MIC_5_UA);
+	S(hph_current, SITAR_PID_MIC_5_UA);
+	S(t_mic_pid, 100);
+	S(t_ins_complete, 250);
+	S(t_ins_retry, 200);
+#undef S
+#define S(X, Y) ((SITAR_MBHC_CAL_PLUG_TYPE_PTR(sitar_cal)->X) = (Y))
+	S(v_no_mic, 30);
+	S(v_hs_max, 1550);
+#undef S
+#define S(X, Y) ((SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal)->X) = (Y))
+	S(c[0], 62);
+	S(c[1], 124);
+	S(nc, 1);
+	S(n_meas, 3);
+	S(mbhc_nsc, 11);
+	S(n_btn_meas, 1);
+	S(n_btn_con, 2);
+	S(num_btn, SITAR_MBHC_DEF_BUTTONS);
+	S(v_btn_press_delta_sta, 100);
+	S(v_btn_press_delta_cic, 50);
+#undef S
+	btn_cfg = SITAR_MBHC_CAL_BTN_DET_PTR(sitar_cal);
+	btn_low = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_LOW);
+	btn_high = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_V_BTN_HIGH);
+	btn_low[0] = -50;
+	btn_high[0] = 10;
+	btn_low[1] = 11;
+	btn_high[1] = 38;
+	btn_low[2] = 39;
+	btn_high[2] = 64;
+	btn_low[3] = 65;
+	btn_high[3] = 91;
+	btn_low[4] = 92;
+	btn_high[4] = 115;
+	btn_low[5] = 116;
+	btn_high[5] = 141;
+	btn_low[6] = 142;
+	btn_high[6] = 163;
+	btn_low[7] = 164;
+	btn_high[7] = 250;
+	n_ready = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_READY);
+	n_ready[0] = 48;
+	n_ready[1] = 38;
+	n_cic = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_N_CIC);
+	n_cic[0] = 60;
+	n_cic[1] = 47;
+	gain = sitar_mbhc_cal_btn_det_mp(btn_cfg, SITAR_BTN_DET_GAIN);
+	gain[0] = 11;
+	gain[1] = 9;
+
+	return sitar_cal;
+}
+
 static int msm8930_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
@@ -447,7 +500,7 @@
 		ARRAY_SIZE(common_audio_map));
 
 	snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Pos");
-	snd_soc_dapm_enable_pin(dapm, "Ext Spk Right Pos");
+	snd_soc_dapm_enable_pin(dapm, "Ext Spk Left Neg");
 
 	snd_soc_dapm_sync(dapm);
 
@@ -466,7 +519,10 @@
 		return err;
 	}
 	codec_clk = clk_get(cpu_dai->dev, "osr_clk");
-	sitar_hs_detect(codec, &hs_jack, &button_jack, &sitar_calib);
+
+	sitar_hs_detect(codec, &hs_jack, &button_jack, sitar_mbhc_cal,
+			SITAR_MICBIAS2, msm8930_enable_codec_ext_clk, 0,
+			SITAR_EXT_CLK_RATE);
 	return 0;
 }
 
@@ -596,76 +652,7 @@
 
 	return 0;
 }
-static int msm8930_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
-					struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_RATE);
 
-	struct snd_interval *channels = hw_param_interval(params,
-					SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	/* PCM only supports mono output with 8khz sample rate */
-	rate->min = rate->max = 8000;
-	channels->min = channels->max = 1;
-
-	return 0;
-}
-static int msm8930_aux_pcm_get_gpios(void)
-{
-	int ret = 0;
-
-	pr_debug("%s\n", __func__);
-
-	ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
-	if (ret < 0) {
-		pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
-				__func__, GPIO_AUX_PCM_DOUT);
-		goto fail_dout;
-	}
-
-	ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
-	if (ret < 0) {
-		pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
-				__func__, GPIO_AUX_PCM_DIN);
-		goto fail_din;
-	}
-
-	ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
-	if (ret < 0) {
-		pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
-				__func__, GPIO_AUX_PCM_SYNC);
-		goto fail_sync;
-	}
-	ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
-	if (ret < 0) {
-		pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
-				__func__, GPIO_AUX_PCM_CLK);
-		goto fail_clk;
-	}
-
-	return 0;
-
-fail_clk:
-	gpio_free(GPIO_AUX_PCM_SYNC);
-fail_sync:
-	gpio_free(GPIO_AUX_PCM_DIN);
-fail_din:
-	gpio_free(GPIO_AUX_PCM_DOUT);
-fail_dout:
-
-	return ret;
-}
-
-static int msm8930_aux_pcm_free_gpios(void)
-{
-	gpio_free(GPIO_AUX_PCM_DIN);
-	gpio_free(GPIO_AUX_PCM_DOUT);
-	gpio_free(GPIO_AUX_PCM_SYNC);
-	gpio_free(GPIO_AUX_PCM_CLK);
-
-	return 0;
-}
 static int msm8930_startup(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -673,26 +660,6 @@
 	return 0;
 }
 
-static int msm8930_auxpcm_startup(struct snd_pcm_substream *substream)
-{
-	int ret = 0;
-
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	ret = msm8930_aux_pcm_get_gpios();
-	if (ret < 0) {
-		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static void msm8930_auxpcm_shutdown(struct snd_pcm_substream *substream)
-{
-
-	pr_debug("%s(): substream = %s\n", __func__, substream->name);
-	msm8930_aux_pcm_free_gpios();
-}
-
 static void msm8930_shutdown(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -705,11 +672,6 @@
 	.shutdown = msm8930_shutdown,
 };
 
-static struct snd_soc_ops msm8930_auxpcm_be_ops = {
-	.startup = msm8930_auxpcm_startup,
-	.shutdown = msm8930_auxpcm_shutdown,
-};
-
 /* Digital audio interface glue - connects codec <---> CPU */
 static struct snd_soc_dai_link msm8930_dai[] = {
 	/* FrontEnd DAI Links */
@@ -940,30 +902,6 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
 	},
-	/* AUX PCM Backend DAI Links */
-	{
-		.name = LPASS_BE_AUXPCM_RX,
-		.stream_name = "AUX PCM Playback",
-		.cpu_dai_name = "msm-dai-q6.2",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-rx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
-		.be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
-		.ops = &msm8930_auxpcm_be_ops,
-	},
-	{
-		.name = LPASS_BE_AUXPCM_TX,
-		.stream_name = "AUX PCM Capture",
-		.cpu_dai_name = "msm-dai-q6.3",
-		.platform_name = "msm-pcm-routing",
-		.codec_name = "msm-stub-codec.1",
-		.codec_dai_name = "msm-stub-tx",
-		.no_pcm = 1,
-		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
-		.be_hw_params_fixup = msm8930_auxpcm_be_params_fixup,
-	},
 	/* Incall Music BACK END DAI Link */
 	{
 		.name = LPASS_BE_VOICE_PLAYBACK_TX,
@@ -1043,10 +981,16 @@
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
 	}
+	sitar_mbhc_cal = def_sitar_mbhc_cal();
+	if (!sitar_mbhc_cal) {
+		pr_err("Calibration data allocation failed\n");
+		return -ENOMEM;
+	}
 
 	msm8930_snd_device = platform_device_alloc("soc-audio", 0);
 	if (!msm8930_snd_device) {
 		pr_err("Platform device allocation failed\n");
+		kfree(sitar_mbhc_cal);
 		return -ENOMEM;
 	}
 
@@ -1054,6 +998,7 @@
 	ret = platform_device_add(msm8930_snd_device);
 	if (ret) {
 		platform_device_put(msm8930_snd_device);
+		kfree(sitar_mbhc_cal);
 		return ret;
 	}
 
@@ -1076,6 +1021,7 @@
 	}
 	msm8930_free_headset_mic_gpios();
 	platform_device_unregister(msm8930_snd_device);
+	kfree(sitar_mbhc_cal);
 }
 module_exit(msm8930_audio_exit);
 
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index f928c00..bc5c007 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -82,7 +82,7 @@
 			return 0;
 		}
 		if (data->opcode == APR_BASIC_RSP_RESULT) {
-			pr_debug("APR_BASIC_RSP_RESULT\n");
+			pr_debug("APR_BASIC_RSP_RESULT id %x\n", payload[0]);
 			switch (payload[0]) {
 			case ADM_CMD_SET_PARAMS:
 				if (rtac_make_adm_callback(payload,
@@ -94,7 +94,7 @@
 			case ADM_CMD_MEMORY_MAP_REGIONS:
 			case ADM_CMD_MEMORY_UNMAP_REGIONS:
 			case ADM_CMD_MATRIX_MAP_ROUTINGS:
-				pr_debug("ADM_CMD_MATRIX_MAP_ROUTINGS\n");
+			case ADM_CMD_CONNECT_AFE_PORT:
 				atomic_set(&this_adm.copp_stat[index], 1);
 				wake_up(&this_adm.wait);
 				break;
@@ -143,14 +143,14 @@
 	s32				result = 0;
 	struct adm_set_params_command	adm_params;
 	int index = afe_get_port_index(port_id);
-	if (index < 0 || index >= AFE_MAX_PORTS) {
-		pr_err("%s: invalid port idx %d portid %d\n",
-				__func__, index, port_id);
-		return 0;
-	}
 
 	pr_debug("%s: Port id %d, index %d\n", __func__, port_id, index);
 
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %d\n",
+				__func__, index, port_id);
+		goto done;
+	}
 	if (!aud_cal || aud_cal->cal_size == 0) {
 		pr_debug("%s: No ADM cal to send for port_id = %d!\n",
 			__func__, port_id);
@@ -270,6 +270,76 @@
 			__func__, port_id, acdb_path);
 }
 
+int adm_connect_afe_port(int mode, int session_id, int port_id)
+{
+	struct adm_cmd_connect_afe_port	cmd;
+	int ret = 0;
+	int index;
+
+	pr_debug("%s: port %d session id:%d mode:%d\n", __func__,
+				port_id, session_id, mode);
+
+	port_id = afe_convert_virtual_to_portid(port_id);
+
+	if (afe_validate_port(port_id) < 0) {
+		pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+		return -ENODEV;
+	}
+	if (this_adm.apr == NULL) {
+		this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+						0xFFFFFFFF, &this_adm);
+		if (this_adm.apr == NULL) {
+			pr_err("%s: Unable to register ADM\n", __func__);
+			ret = -ENODEV;
+			return ret;
+		}
+		rtac_set_adm_handle(this_adm.apr);
+	}
+	index = afe_get_port_index(port_id);
+	pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+	cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	cmd.hdr.pkt_size = sizeof(cmd);
+	cmd.hdr.src_svc = APR_SVC_ADM;
+	cmd.hdr.src_domain = APR_DOMAIN_APPS;
+	cmd.hdr.src_port = port_id;
+	cmd.hdr.dest_svc = APR_SVC_ADM;
+	cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
+	cmd.hdr.dest_port = port_id;
+	cmd.hdr.token = port_id;
+	cmd.hdr.opcode = ADM_CMD_CONNECT_AFE_PORT;
+
+	cmd.mode = mode;
+	cmd.session_id = session_id;
+	cmd.afe_port_id = port_id;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	ret = apr_send_pkt(this_adm.apr, (uint32_t *)&cmd);
+	if (ret < 0) {
+		pr_err("%s:ADM enable for port %d failed\n",
+					__func__, port_id);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	/* Wait for the callback with copp id */
+	ret = wait_event_timeout(this_adm.wait,
+		atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s ADM connect AFE failed for port %d\n", __func__,
+							port_id);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	atomic_inc(&this_adm.copp_cnt[index]);
+	return 0;
+
+fail_cmd:
+
+	return ret;
+}
+
 int adm_open(int port_id, int path, int rate, int channel_mode, int topology)
 {
 	struct adm_copp_open_command	open;
@@ -505,15 +575,16 @@
 	int ret = 0, i = 0;
 	/* Assumes port_ids have already been validated during adm_open */
 	int index = afe_get_port_index(copp_id);
-	if (index < 0 || index >= AFE_MAX_PORTS) {
-		pr_err("%s: invalid port idx %d token %d\n",
-					__func__, index, copp_id);
-		return 0;
-	}
 
 	pr_debug("%s: session 0x%x path:%d num_copps:%d port_id[0]:%d\n",
 		 __func__, session_id, path, num_copps, port_id[0]);
 
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d token %d\n",
+					__func__, index, copp_id);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
 	route.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
 	route.hdr.pkt_size = sizeof(route);
@@ -538,7 +609,7 @@
 		pr_debug("%s: port_id[%d]: %d, index: %d\n", __func__, i,
 			 port_id[i], tmp);
 
-		if (tmp >= 0 && tmp < AFE_MAX_PORTS)
+		if ((tmp >= 0) && (tmp < AFE_MAX_PORTS))
 			route.session[0].copp_id[i] =
 					atomic_read(&this_adm.copp_id[tmp]);
 	}
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index fe31b27..c7ebd2c 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -865,6 +865,7 @@
 		case ASM_STREAM_CMD_OPEN_READWRITE:
 		case ASM_DATA_CMD_MEDIA_FORMAT_UPDATE:
 		case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+		case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
 			if (atomic_read(&ac->cmd_state)) {
 				atomic_set(&ac->cmd_state, 0);
 				wake_up(&ac->cmd_wait);
@@ -1269,6 +1270,72 @@
 	return -EINVAL;
 }
 
+int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format)
+{
+	int rc = 0x00;
+	struct asm_stream_cmd_open_write_compressed open;
+
+	if ((ac == NULL) || (ac->apr == NULL)) {
+		pr_err("%s: APR handle NULL\n", __func__);
+		return -EINVAL;
+	}
+	pr_debug("%s: session[%d] wr_format[0x%x]", __func__, ac->session,
+		format);
+
+	q6asm_add_hdr(ac, &open.hdr, sizeof(open), TRUE);
+
+	open.hdr.opcode = ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED;
+
+	switch (format) {
+	case FORMAT_AC3:
+		open.format = AC3_DECODER;
+		break;
+	case FORMAT_EAC3:
+		open.format = EAC3_DECODER;
+		break;
+	case FORMAT_MP3:
+		open.format = MP3;
+		break;
+	case FORMAT_DTS:
+		open.format = DTS;
+		break;
+	case FORMAT_AAC:
+		open.format = MPEG4_AAC;
+		break;
+	case FORMAT_ATRAC:
+		open.format = ATRAC;
+		break;
+	case FORMAT_WMA_V10PRO:
+		open.format = WMA_V10PRO;
+		break;
+	case FORMAT_MAT:
+		open.format = MAT;
+		break;
+	default:
+		pr_err("%s: Invalid format[%d]\n", __func__, format);
+		goto fail_cmd;
+	}
+	/*Below flag indicates the DSP that Compressed audio input
+	stream is not IEC 61937 or IEC 60958 packetizied*/
+	open.flags = 0x00000000;
+	rc = apr_send_pkt(ac->apr, (uint32_t *) &open);
+	if (rc < 0) {
+		pr_err("%s: open failed op[0x%x]rc[%d]\n", \
+					__func__, open.hdr.opcode, rc);
+		goto fail_cmd;
+	}
+	rc = wait_event_timeout(ac->cmd_wait,
+			(atomic_read(&ac->cmd_state) == 0), 5*HZ);
+	if (!rc) {
+		pr_err("%s: timeout. waited for OPEN_WRITE rc[%d]\n", __func__,
+			rc);
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return -EINVAL;
+}
+
 int q6asm_open_write(struct audio_client *ac, uint32_t format)
 {
 	int rc = 0x00;