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/&/\\&/g" \
+ -e "s/</\\</g" \
+ -e "s/>/\\>/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 <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 <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 <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 <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 <marcus@convergence.de>
- * Ralph Metzler <ralph@convergence.de>
- * Holger Waechtler <holger@convergence.de>
- * Andre Draszik <ad@convergence.de>
- * 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 <linux/types.h>
-
-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 <link linkend='v4l2-buf-type'>v4l2_buf_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-colorspace'>v4l2_colorspace</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-ctrl-type'>v4l2_ctrl_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-exposure-auto-type'>v4l2_exposure_auto_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-field'>v4l2_field</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-memory'>v4l2_memory</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-emphasis'>v4l2_mpeg_audio_emphasis</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-encoding'>v4l2_mpeg_audio_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-l1-bitrate'>v4l2_mpeg_audio_l1_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-l2-bitrate'>v4l2_mpeg_audio_l2_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-l3-bitrate'>v4l2_mpeg_audio_l3_bitrate</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-mode'>v4l2_mpeg_audio_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-mode-extension'>v4l2_mpeg_audio_mode_extension</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-audio-sampling-freq'>v4l2_mpeg_audio_sampling_freq</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='chroma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='luma-spatial-filter-type'>v4l2_mpeg_cx2341x_video_luma_spatial_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-cx2341x-video-median-filter-type'>v4l2_mpeg_cx2341x_video_median_filter_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-cx2341x-video-spatial-filter-mode'>v4l2_mpeg_cx2341x_video_spatial_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-cx2341x-video-temporal-filter-mode'>v4l2_mpeg_cx2341x_video_temporal_filter_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-stream-type'>v4l2_mpeg_stream_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-stream-vbi-fmt'>v4l2_mpeg_stream_vbi_fmt</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-video-aspect'>v4l2_mpeg_video_aspect</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-video-bitrate-mode'>v4l2_mpeg_video_bitrate_mode</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-priority'>v4l2_priority</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-tuner-type'>v4l2_tuner_type</link></primaryie></indexentry>
-<indexentry><primaryie>enum <link linkend='v4l2-preemphasis'>v4l2_preemphasis</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-audio'>v4l2_audio</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-audioout'>v4l2_audioout</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-bt-timings'>v4l2_bt_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-buffer'>v4l2_buffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-capability'>v4l2_capability</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-captureparm'>v4l2_captureparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-clip'>v4l2_clip</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-control'>v4l2_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-crop'>v4l2_crop</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-cropcap'>v4l2_cropcap</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dbg-chip-ident'>v4l2_dbg_chip_ident</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dbg-match'>v4l2_dbg_match</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dbg-register'>v4l2_dbg_register</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dv-enum-preset'>v4l2_dv_enum_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dv-preset'>v4l2_dv_preset</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-dv-timings'>v4l2_dv_timings</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-enc-idx'>v4l2_enc_idx</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-ext-control'>v4l2_ext_control</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-ext-controls'>v4l2_ext_controls</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-format'>v4l2_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-fract'>v4l2_fract</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-framebuffer'>v4l2_framebuffer</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frequency'>v4l2_frequency</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frmival-stepwise'>v4l2_frmival_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frmivalenum'>v4l2_frmivalenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frmsize-discrete'>v4l2_frmsize_discrete</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frmsize-stepwise'>v4l2_frmsize_stepwise</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-frmsizeenum'>v4l2_frmsizeenum</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-input'>v4l2_input</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-modulator'>v4l2_modulator</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-output'>v4l2_output</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-outputparm'>v4l2_outputparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-pix-format'>v4l2_pix_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-queryctrl'>v4l2_queryctrl</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-querymenu'>v4l2_querymenu</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-rect'>v4l2_rect</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-requestbuffers'>v4l2_requestbuffers</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-standard'>v4l2_standard</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-streamparm'>v4l2_streamparm</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-timecode'>v4l2_timecode</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-tuner'>v4l2_tuner</link></primaryie></indexentry>
-<indexentry><primaryie>struct <link linkend='v4l2-vbi-format'>v4l2_vbi_format</link></primaryie></indexentry>
-<indexentry><primaryie>struct <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 <bill@thedirks.org>
- * Justin Schoeman
- * Hans Verkuil <hverkuil@xs4all.nl>
- * et al.
- */
-#ifndef __LINUX_VIDEODEV2_H
-#define __LINUX_VIDEODEV2_H
-
-#ifdef __KERNEL__
-#include <linux/time.h> /* need struct timeval */
-#else
-#include <sys/time.h>
-#endif
-#include <linux/compiler.h>
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/*
- * 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) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 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<<3) /* Define Huffman Tables */
-#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */
-#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */
-#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */
-#define V4L2_JPEG_MARKER_APP (1<<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->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) & 0x0fff0000UL)
-#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 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 << 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 << 0)
-#define V4L2_VBI_INTERLACED (1 << 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 <media/v4l2-chip-ident.h> */
- __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(¶ms, 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, ¶ms);
+ 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, ¶m);
+ 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, ¶m);
+ 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), ¶m);
+ 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), ¶m);
+ 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;