Merge "ASoC: wcd9xxx: Add AANC codec registers for DSP"
diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
index 23d78b5..0ba6ea2 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -11,7 +11,7 @@
Date: September 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
- The /sys/class/devfreq/.../governor shows the name of the
+ The /sys/class/devfreq/.../governor show or set the name of the
governor used by the corresponding devfreq object.
What: /sys/class/devfreq/.../cur_freq
@@ -19,15 +19,16 @@
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
The /sys/class/devfreq/.../cur_freq shows the current
- frequency of the corresponding devfreq object.
+ frequency of the corresponding devfreq object. Same as
+ target_freq when get_cur_freq() is not implemented by
+ devfreq driver.
-What: /sys/class/devfreq/.../central_polling
-Date: September 2011
-Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+What: /sys/class/devfreq/.../target_freq
+Date: September 2012
+Contact: Rajagopal Venkat <rajagopal.venkat@linaro.org>
Description:
- The /sys/class/devfreq/.../central_polling shows whether
- the devfreq ojbect is using devfreq-provided central
- polling mechanism or not.
+ The /sys/class/devfreq/.../target_freq shows the next governor
+ predicted target frequency of the corresponding devfreq object.
What: /sys/class/devfreq/.../polling_interval
Date: September 2011
@@ -43,6 +44,17 @@
(/sys/class/devfreq/.../central_polling is 0), this value
may be useless.
+What: /sys/class/devfreq/.../trans_stat
+Date: October 2012
+Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
+Descrtiption:
+ This ABI shows the statistics of devfreq behavior on a
+ specific device. It shows the time spent in each state and
+ the number of transitions between states.
+ In order to activate this ABI, the devfreq target device
+ driver should provide the list of available frequencies
+ with its profile.
+
What: /sys/class/devfreq/.../userspace/set_freq
Date: September 2011
Contact: MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -50,3 +62,19 @@
The /sys/class/devfreq/.../userspace/set_freq shows and
sets the requested frequency for the devfreq object if
userspace governor is in effect.
+
+What: /sys/class/devfreq/.../available_frequencies
+Date: October 2012
+Contact: Nishanth Menon <nm@ti.com>
+Description:
+ The /sys/class/devfreq/.../available_frequencies shows
+ the available frequencies of the corresponding devfreq object.
+ This is a snapshot of available frequencies and not limited
+ by the min/max frequency restrictions.
+
+What: /sys/class/devfreq/.../available_governors
+Date: October 2012
+Contact: Nishanth Menon <nm@ti.com>
+Description:
+ The /sys/class/devfreq/.../available_governors shows
+ currently available governors in the system.
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
new file mode 100644
index 0000000..3a29004
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -0,0 +1,69 @@
+Qualcomm CPR (Core Power Reduction) Regulator
+
+CPR regulator device is for Qualcomm RBCPR (RapidBridge CPR) on
+ application processor core. It takes voltage corner level
+ as input and converts it to actual voltage based on the
+ suggestions from factory production process. When CPR is
+ enabled for application processer core, it will suggest
+ scaling the voltage up or down for best performance and
+ power of the core. The scaling based on factory production
+ process is called PVS (Process Voltage Scaling) with efuse
+ bits to indicate what bin (and voltage range) a chip is in.
+
+Required properties:
+- compatible: Must be "qcom,cpr-regulator"
+- reg: Register addresses for RBCPR and efuse
+- reg-names: Register names. Must be "rbcpr" and "efuse_phys"
+- regulator-name: A string used to describe the regulator
+- regulator-min-microvolt: Minimum corner value as min constraint, which
+ should be 1 for SVS corner
+- regulator-max-microvolt: Maximum corner value as max constraint, which
+ should be 4 for SUPER_TURBO or 3 for TURBO
+- qcom,num-efuse-bits: The number of bits used in efuse memory to
+ represent total number of PVS bins. It should
+ not exceed a maximum of 5 for total number of
+ 32 bins.
+- qcom,efuse-bit-pos: A list of integers whose length must equal
+ to qcom,num-efuse-bits and each integer indicates
+ bit position in efuse memory from LSB to MSB
+- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
+ the power of qcom,num-efuse-bits. The location or
+ 0-based index of an element in the list corresponds
+ to the bin number. The value of each integer
+ corresponds to the PVS process speed of the APC
+ silicon for a chip with one of these cases:
+ 1 = APC_PVS_SLOW
+ 2 = APC_PVS_NOM
+ 3 = APC_PVS_FAST
+ 0 or other values = No PVS
+- qcom,pvs-corner-ceiling-slow: Ceiling voltages of all corners for APC_PVS_SLOW
+- qcom,pvs-corner-ceiling-nom: Ceiling voltages of all corners for APC_PVS_NOM
+- qcom,pvs-corner-ceiling-fast: Ceiling voltages of all corners for APC_PVS_FAST
+ The ceiling voltages for each of above three
+ properties may look like this:
+ 0 (SVS voltage): 1050000 uV
+ 1 (NORMAL voltage): 1150000 uV
+ 2 (TURBO voltage): 1275000 uV
+ 3 (SUPER_TURBO voltage): 1275000 uV
+- vdd-apc-supply: Regulator to supply VDD APC power
+
+Example:
+ apc_vreg_corner: regulator@f9018000 {
+ status = "okay";
+ compatible = "qcom,cpr-regulator";
+ reg = <0xf9018000 0x1000>,
+ <0xfc4b80b0 8>;
+ reg-names = "rbcpr", "efuse_phys";
+ regulator-name = "apc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <4>;
+ qcom,num-efuse-bits = <5>;
+ qcom,efuse-bit-pos = <6 7 8 9 10>;
+ qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ vdd-apc-supply = <&pm8226_s2>;
+ };
+
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
index 5c6b804..2d83614 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
@@ -6,12 +6,19 @@
type of heap ION must reserve memory using the msm specific memory reservation
bindings (see Documentation/devicetree/bindings/arm/msm/memory-reserve.txt).
-Required properties
+Required properties for Ion
- compatible: "qcom,msm-ion"
+
+
+All child nodes of a qcom,msm-ion node are interpreted as Ion heap
+configurations.
+
+Required properties for Ion heaps
+
- reg: The ID of the ION heap.
-Optional properties
+Optional properties for Ion heaps
- compatible: "qcom,msm-ion-reserve" This is required if memory is to be reserved
as specified by qcom,memory-reservation-size below.
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
index d930799..3d70a9b 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
@@ -62,6 +62,28 @@
1. This value shift is necessary to work around
limitations in the regulator framework which
treat 0 uV as an error.
+- qcom,use-voltage-floor-corner: Flag that signifies if regulator_set_voltage
+ calls should modify the floor corner parameter
+ instead of the voltage parameter. When used,
+ voltages specified inside of the regulator
+ framework represent corners that have been
+ incremented by 1. The properties
+ qcom,use-voltage-corner and
+ qcom,use-voltage-floor-corner are mutually
+ exclusive. Only one may be specified for a
+ given regulator.
+- qcom,always-send-voltage: Flag which indicates that updates to the voltage
+ or voltage corner set point should always be
+ sent immediately to the RPM. If this flag is
+ not specified, then voltage set point updates
+ are only sent if the given regulator has also
+ been enabled by a Linux consumer.
+- qcom,always-send-current: Flag which indicates that updates to the load
+ current should always be sent immediately to the
+ RPM. If this flag is not specified, then load
+ current updates are only sent if the given
+ regulator has also been enabled by a Linux
+ consumer.
The following properties specify initial values for parameters to be sent to the
RPM in regulator requests.
- qcom,init-enable: 0 = regulator disabled
@@ -94,25 +116,9 @@
BIT(2) = follow HW2_EN signal
BIT(3) = follow HW3_EN signal
BIT(4) = follow PMIC awake state
-- qcom,init-frequency: Switching frequency in MHz for SMPS regulators.
- Supported values are:
- 0 = Don't care about frequency used
- 1 = 19.20
- 2 = 9.60
- 3 = 6.40
- 4 = 4.80
- 5 = 3.84
- 6 = 3.20
- 7 = 2.74
- 8 = 2.40
- 9 = 2.13
- 10 = 1.92
- 11 = 1.75
- 12 = 1.60
- 13 = 1.48
- 14 = 1.37
- 15 = 1.28
- 16 = 1.20
+- qcom,init-frequency: Switching frequency divisor for SMPS regulators.
+ Supported values are n = 0 to 31 where
+ freq = 19.2 MHz / (n + 1).
- qcom,init-head-room: Voltage head room in mV required for the
regulator. This head room value should be used
in situations where the device connected to the
@@ -165,6 +171,10 @@
0 = Allow RPM to utilize LDO bypass mode
if possible
1 = Disallow LDO bypass mode
+- qcom,init-voltage-floor-corner: Minimum performance corner to use if any
+ processor in the system is awake. This property
+ supports the same values as
+ qcom,init-voltage-corner.
All properties specified within the core regulator framework can also be used in
second level nodes. These bindings can be found in:
diff --git a/Documentation/devicetree/bindings/arm/msm/smp2p.txt b/Documentation/devicetree/bindings/arm/msm/smp2p.txt
index 7a5f506..a7af9e7 100644
--- a/Documentation/devicetree/bindings/arm/msm/smp2p.txt
+++ b/Documentation/devicetree/bindings/arm/msm/smp2p.txt
@@ -2,9 +2,7 @@
Required properties:
-compatible : should be "qcom,smp2p"
--reg : the location and offset of the irq register base memory
--reg-names : "irq-reg-base", "irq-reg-offset" - string to identify the irq
- register region and offset values
+-reg : the location of the irq register base memory
-qcom,remote-pid : the SMP2P remote processor ID (see smp2p_private_api.h)
-qcom,irq-bitmask : the sending irq bitmask
-interrupts : the receiving interrupt line
@@ -13,8 +11,7 @@
qcom,smp2p-modem {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <1>;
qcom,irq-bitmask = <0x4000>;
interrupts = <0 27 1>;
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
new file mode 100644
index 0000000..c012eec
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spm-regulator.txt
@@ -0,0 +1,32 @@
+Qualcomm SPM Regulators
+
+spm-regulator is a regulator device which supports PMIC processor supply
+regulators via the SPM module.
+
+Required properties:
+- compatible: Must be "qcom,spm-regulator"
+- reg: Specifies the SPMI address and size for this regulator device
+- regulator-name: A string used as a descriptive name for the regulator
+
+Required structure:
+- A qcom,spm-regulator node must be a child of an SPMI node that has specified
+ the spmi-slave-container property
+
+All properties specified within the core regulator framework can also be used.
+These bindings can be found in regulator.txt.
+
+Example:
+ qcom,spmi@fc4c0000 {
+
+ qcom,pm8226@1 {
+ spmi-slave-container;
+
+ spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
+ regulator-name = "8226_s2";
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1275000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/bluetooth/bluesleep.txt b/Documentation/devicetree/bindings/bluetooth/bluesleep.txt
new file mode 100644
index 0000000..a5c5a16
--- /dev/null
+++ b/Documentation/devicetree/bindings/bluetooth/bluesleep.txt
@@ -0,0 +1,41 @@
+* Bluetooth Sleep Protocol driver
+Bluetooth controller communicates with the Bluetooth Host using HCI Transport layer.
+HCI Transport layer can be based on UART or USB serial communication protocol.
+
+Apart from the transport layer, Bluetooth Controller also supports Low Power Mode
+using various mechanisms. One of such mechanism is Out-of-Band Sleep. Also known
+as 2-wire sleep mechanism.
+
+Out-of-Band Sleep:
+It requires two GPIOs to communicate the sleep protocol between Host and Controller.
+One of them is called as Host Wake GPIO where as other is known as a External wake
+GPIO.
+Host Wake GPIO is used for awake the Host from the Sleep Mode. It is controlled by the
+Controller. It should be wakeup interruptible source on the Host.
+External Wake GPIO is used for awake the Controller from the Sleep Mode. It is controlled
+by the Host.
+
+Required Properties:
+
+ - compatible: Should be "qca,ar3002_bluesleep"
+ - host-wake-gpio: Specify GPIO for Host wake signal (Controller -> Host).
+ - ext-wake-gpio: Specify GPIO for Controller wake signal(Host -> Controller).
+ - interrupt-parent: Should be phandle for the interrupt controller
+ that services interrupts for this device.
+ - interrupts: Should contain host wake interrupt from controller.
+ - interrupt-names: indicates interrupts passed to driver
+ (via interrupts property) by name. "host_wake" is mandatory.
+
+Optional Properties:
+ None
+
+Example:
+
+ bt_sleep {
+ compatible = "qca,ar3002_bluesleep";
+ host-wake-gpio = <&msmgpio 12 0>;
+ ext-wake-gpio = <&msmgpio 13 0>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <12 0>;
+ interrupt-names = "host_wake";
+ };
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index c830bc4..25219cd 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -24,16 +24,12 @@
- reg-names : names corresponding to each reg property value. The reg-names that
need to be used with corresponding compatible string for a coresight device
are:
- - for coresight tmc-etr device:
+ - for coresight tmc-etr or tmc-etf device:
compatible : should be "arm,coresight-tmc"
reg-names : should be:
- "tmc-etr-base" - physical base address of tmc-etr registers
- "tmc-etr-bam-base" - physical base address of tmc-etr bam
- registers
- - for coresight tmc-etf device:
- compatible : should be "arm,coresight-tmc"
- reg-names : should be:
- "tmc-etf-base" - physical base address of tmc-etf registers
+ "tmc-base" - physical base address of tmc configuration
+ registers
+ "bam-base" - physical base address of tmc-etr bam registers
- for coresight tpiu device:
compatible : should be "arm,coresight-tpiu"
reg-names : should be:
@@ -41,24 +37,22 @@
- for coresight replicator device
compatible : should be "qcom,coresight-replicator"
reg-names : should be:
- "replicator-base" - physical base address of replicator registers
+ "replicator-base" - physical base address of replicator
+ registers
- for coresight funnel devices
compatible : should be "arm,coresight-funnel"
reg-names : should be:
- "funnel-<val>-base" - physical base address of funnel registers
- where <val> can be "merg", "in0", "in1", "kpss", "a7ss" or
- "mmss"
+ "funnel-base" - physical base address of funnel registers
- for coresight stm trace device
compatible : should be "arm,coresight-stm"
reg-names : should be:
- "stm-base" - physical base address of stm registers
+ "stm-base" - physical base address of stm configuration
+ registers
"stm-data-base" - physical base address of stm data registers
- for coresight etm trace devices
compatible : should be "arm,coresight-etm"
reg-names : should be:
- "etm<num>-base" - physical base address of etm registers in
- general where <num> is the number of etm components or cores
- present for more than one cpu core
+ "etm-base" - physical base address of etm registers
- for coresight csr device:
compatible : should be "qcom,coresight-csr"
reg-names : should be:
@@ -66,12 +60,7 @@
- for coresight cti devices:
compatible : should be "arm,coresight-cti"
reg-names : should be:
- "cti<num>-base" - physical base address of cti registers in general
- where <num> is the cti component number for more than one
- cti components
- "cti-cpu<num>-base" - physical base address of cti cpu registers
- where <num> is the component number for more than one cpu core
- "cti-l2" - physical base address of L2 cti registers
+ "cti<num>-base" - physical base address of cti registers
- coresight-id : unique integer identifier for the component
- coresight-name : unique descriptive name of the component
- coresight-nr-inports : number of input ports on the component
@@ -99,6 +88,23 @@
- qcom,reset-flush-race : indicates if a race exists between flushing and ddr
being put into self-refresh during watchdog reset
- qcom,write-64bit : only 64bit data writes supported by stm
+- vdd-supply: phandle to the regulator device tree node. Used for tpiu component
+- qcom,vdd-voltage-level : specifies voltage level for vdd supply. Should be
+ specified in pairs (min, max) with units being uV
+- qcom,vdd-current-level : specifies current load levels for vdd supply. Should
+ be specified in paris (lpm, hpm) with units being uA
+- qcom,seta-gpios : specifies gpios included in set A that are routed to the
+ mictor connector. Used for tpiu component
+- qcom,seta-gpios-func : active function select for set A gpios
+- qcom,seta-gpios-drv : active drive strength for set A gpios
+- qcom,seta-gpios-pull : active pull configuration for set A gpios
+- qcom,seta-gpios-dir : active direction for set A gpios
+- qcom,setb-gpios : specifies gpios included in set B that are routed to the
+ mictor connector. Used for tpiu component
+- qcom,setb-gpios-func : active function select for set B gpios
+- qcom,setb-gpios-drv : active drive strength for set B gpios
+- qcom,setb-gpios-pull : active pull configuration for set B gpios
+- qcom,setb-gpios-dir : active direction for set B gpios
Examples:
@@ -107,7 +113,7 @@
compatible = "arm,coresight-tmc";
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
- reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+ reg-names = "tmc-base", "bam-base";
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
@@ -123,13 +129,18 @@
coresight-id = <1>;
coresight-name = "coresight-tpiu";
coresight-nr-inports = <1>;
+
+ vdd-supply = <&pm8941_l21>;
+
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <9000 800000>;
};
2. Links
funnel_merg: funnel@fc31b000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31b000 0x1000>;
- reg-names = "funnel-merg-base";
+ reg-names = "funnel-base";
coresight-id = <4>;
coresight-name = "coresight-funnel-merg";
@@ -142,7 +153,7 @@
funnel_in0: funnel@fc319000 {
compatible = "arm,coresight-funnel";
reg = <0xfc319000 0x1000>;
- reg-names = "funnel-in0-base";
+ reg-names = "funnel-base";
coresight-id = <5>;
coresight-name = "coresight-funnel-in0";
@@ -170,7 +181,7 @@
etm0: etm@fc33c000 {
compatible = "arm,coresight-etm";
reg = <0xfc33c000 0x1000>;
- reg-names = "etm0-base";
+ reg-names = "etm-base";
coresight-id = <10>;
coresight-name = "coresight-etm0";
@@ -186,7 +197,7 @@
cti0: cti@fc308000 {
compatible = "arm,coresight-cti";
reg = <0xfc308000 0x1000>;
- reg-names = "cti0-base";
+ reg-names = "cti-base";
coresight-id = <15>;
coresight-name = "coresight-cti0";
@@ -196,7 +207,7 @@
cti1: cti@fc309000 {
compatible = "arm,coresight-cti";
reg = <0xfc309000 0x1000>;
- reg-names = "cti1-base";
+ reg-names = "cti-base";
coresight-id = <16>;
coresight-name = "coresight-cti1";
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
index bf97e80..b9a71f6 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -13,6 +13,11 @@
- qcom,msm_bus,num_paths: The paths for source and destination ports
- qcom,msm_bus,vectors: Vectors for bus topology.
+Optional properties:
+ - qcom,ce-hw-shared : optional, indicates if the hardware is shared between EE.
+
+
+
Example:
qcom,qcedev@fd440000 {
@@ -23,6 +28,7 @@
interrupts = <0 235 0>;
qcom,bam-pipe-pair = <0>;
qcom,ce-hw-instance = <1>;
+ qcom,ce-hw-shared;
qcom,msm-bus,name = "qcedev-noc";
qcom,msm-bus,num-cases = <2>;
qcom,msm-bus,active-only = <0>;
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index c99262b..59f9879 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -13,6 +13,10 @@
- qcom,msm_bus,num_paths: The paths for source and destination ports
- qcom,msm_bus,vectors: Vectors for bus topology.
+Optional properties:
+ - qcom,ce-hw-shared : optional, indicates if the hardware is shared between EE.
+
+
Example:
qcom,qcrypto@fd444000 {
@@ -23,6 +27,7 @@
interrupts = <0 235 0>;
qcom,bam-pipe-pair = <1>;
qcom,ce-hw-instance = <1>;
+ qcom,ce-hw-shared;
qcom,msm-bus,name = "qcrypto-noc";
qcom,msm-bus,num-cases = <2>;
qcom,msm-bus,active-only = <0>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 17b878c..497471a 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -10,6 +10,8 @@
- reg-names : names to refer to register sets related to this device
- interrupts : Interrupt associated with MDSS.
- vdd-supply : Phandle for vdd regulator device node.
+- qcom,max-clk-rate: Specify maximum MDP core clock rate in hz that this
+ device supports.
- qcom,mdss-pipe-vig-off: Array of offset for MDP source surface pipes of
type VIG, the offsets are calculated from
register "mdp_phys" defined in reg property.
@@ -97,6 +99,9 @@
settings used to setup MDSS QoS for best performance.
The key used should be offset from "mdp_phys" register
defined in reg property.
+- qcom,mdss-rot-block-size: The size of a memory block (in pixels) to be used
+ by the rotator. If this property is not specified,
+ then a default value of 128 pixels would be used.
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -115,7 +120,7 @@
reg-names = "mdp_phys", "vbif_phys";
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
-
+ qcom,max-clk-rate = <320000000>;
qcom,vbif-settings = <0x0004 0x00000001>,
<0x00D8 0x00000707>;
qcom,mdp-settings = <0x02E0 0x000000AA>,
@@ -129,6 +134,7 @@
qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
qcom,mdss-pipe-dma-fetch-id = <10 13>;
qcom,mdss-smp-data = <22 4096>;
+ qcom,mdss-rot-block-size = <64>;
qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
0x00000900 0x0000A00>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-qpic-panel.txt b/Documentation/devicetree/bindings/fb/mdss-qpic-panel.txt
new file mode 100644
index 0000000..95f0fa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-qpic-panel.txt
@@ -0,0 +1,37 @@
+Qualcomm mdss-qpic-panel
+
+mdss-qpic-panel is a panel device which can be driven by qpic.
+
+Required properties:
+- compatible: Must be "qcom,mdss-qpic-panel"
+- qcom,mdss-pan-res: A two dimensional array that specifies the panel
+ resolution.
+- qcom,mdss-pan-bpp: Specifies the panel bits per pixel.
+- qcom,refresh_rate: Panel refresh rate
+- vdd-supply: Phandle for vdd regulator device node.
+- avdd-supply: Phandle for avdd regulator device node.
+- qcom,cs-gpio: Phandle for cs gpio device node.
+- qcom,te-gpio: Phandle for te gpio device node.
+- qcom,rst-gpio: Phandle for rst gpio device node.
+- qcom,ad8-gpio: Phandle for ad8 gpio device node.
+
+Optional properties:
+- label: A string used as a descriptive name of the panel
+
+
+Example:
+/ {
+ qcom,mdss_lcdc_ili9341_qvga {
+ compatible = "qcom,mdss-qpic-panel";
+ label = "ili qvga lcdc panel";
+ vdd-supply = <&pm8019_l11>;
+ avdd-supply = <&pm8019_l14>;
+ qcom,cs-gpio = <&msmgpio 21 0>;
+ qcom,te-gpio = <&msmgpio 22 0>;
+ qcom,rst-gpio = <&msmgpio 23 0>;
+ qcom,ad8-gpio = <&msmgpio 20 0>;
+ qcom,mdss-pan-res = <240 320>;
+ qcom,mdss-pan-bpp = <18>;
+ qcom,refresh_rate = <60>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/fb/mdss-qpic.txt b/Documentation/devicetree/bindings/fb/mdss-qpic.txt
new file mode 100644
index 0000000..0fa3a32
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-qpic.txt
@@ -0,0 +1,18 @@
+Qualcomm mdss-qpic
+
+mdss-qpic is a qpic controller device which supports dma transmission to MIPI
+and LCDC panel.
+
+Required properties:
+- compatible: must be "qcom,mdss_qpic"
+- reg: offset and length of the register set for the device.
+- reg-names : names to refer to register sets related to this device
+- interrupts: IRQ line
+
+Example:
+ qcom,msm_qpic@f9ac0000 {
+ compatible = "qcom,mdss_qpic";
+ reg = <0xf9ac0000 0x24000>;
+ reg-names = "qpic_base";
+ interrupts = <0 251 0>;
+ };
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index b9bac1d..812a895 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -51,12 +51,17 @@
Required properties for RGB led:
- qcom,mode: mode the led should operate in, options 0 = PWM, 1 = LPG
- qcom,pwm-channel: pwm channel the led will operate on
+
+Required properties for PWM mode only:
- qcom,pwm-us: time the pwm device will modulate at (us)
Required properties for LPG mode only:
-- qcom,duty-ms: duty cycle time the led will operate at (ms)
- qcom,duty-pcts: array of values for duty cycle to go through
- qcom,start-idx: starting point duty-pcts array
+- qcom,pause-lo: pause at low end of cycle
+- qcom,pause-hi: pause at high end of cycle
+- qcom,ramp-step-ms: step between each cycle (ms)
+- qcom,lut-flags: flags to be used in lut configuration
Optional properties for RGB led:
- linux,default-trigger: trigger the led from external modules such as display
@@ -90,12 +95,14 @@
linux,name = "led:rgb_blue";
qcom,mode = <1>;
qcom,pwm-channel = <4>;
- qcom,pwm-us = <1000>;
- qcom,duty-ms = <20>;
qcom,start-idx = <1>;
qcom,idx-len = <10>;
qcom,duty-pcts = [00 19 32 4B 64
64 4B 32 19 00];
+ qcom,lut-flags = <3>;
+ qcom,pause-lo = <0>;
+ qcom,pause-hi = <0>;
+ qcom,ramp-step-ms = <255>;
qcom,max-current = <12>;
qcom,default-state = "on";
qcom,turn-off-delay-ms = <500>;
diff --git a/Documentation/devicetree/bindings/media/video/msm-csid.txt b/Documentation/devicetree/bindings/media/video/msm-csid.txt
index 76a2825..50b085b 100644
--- a/Documentation/devicetree/bindings/media/video/msm-csid.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-csid.txt
@@ -10,6 +10,10 @@
- interrupts : should contain the csid interrupt.
- interrupt-names : should specify relevant names to each interrupts
property defined.
+- qcom,csi-vdd-voltage : should specify voltage level
+ for mipi csi in uV.
+- qcom,mipi-csi-vdd-supply : should contain regulator to be used for
+ this csid core
Example:
@@ -20,4 +24,6 @@
reg-names = "csid";
interrupts = <0 51 0>;
interrupt-names = "csiphy";
+ qcom,csi-vdd-voltage = <1800000>;
+ qcom,mipi-csi-vdd-supply = <&pm8941_l12>;
};
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
new file mode 100644
index 0000000..34c344a
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -0,0 +1,27 @@
+QPNP-MISC
+
+QPNP-MISC provides a way to read the PMIC part number and revision.
+
+Required properties:
+- compatible : should be "qcom,qpnp-misc"
+- reg : offset and length of the PMIC peripheral register map.
+
+Example:
+ qcom,spmi@fc4c0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ qcom,pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+ }
+ };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index d5937cf..87281f7 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -12,6 +12,8 @@
Required "interrupt-names" are "hc_irq" and "pwr_irq".
- <supply-name>-supply: phandle to the regulator device tree node
Required "supply-name" are "vdd" and "vdd-io".
+ - qcom,clk-rates: this is an array that specifies supported SDHC clock
+ frequencies for a slot, Units - Hz.
Required alias:
- The slot number is specified via an alias with the following format
@@ -112,6 +114,7 @@
qcom,bus-width = <4>;
qcom,nonremovable;
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
gpios = <&msmgpio 40 0>, /* CLK */
<&msmgpio 39 0>, /* CMD */
@@ -120,7 +123,6 @@
<&msmgpio 36 0>, /* DATA2 */
<&msmgpio 35 0>; /* DATA3 */
qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
- qcom,cpu-dma-latency-us = <200>;
};
sdhc_2: qcom,sdhc@f98a4900 {
@@ -143,6 +145,7 @@
vdd-io-supply = <&pm8941_l13>;
qcom,bus-width = <4>;
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
qcom,pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
diff --git a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
index 7b9feae..6c3e98e 100644
--- a/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
+++ b/Documentation/devicetree/bindings/net/wireless/ath/ath6kl.txt
@@ -2,15 +2,15 @@
Required properties:
- compatible: Can be "qca,ar6004-sdio" for SDIO device and
- "qca,ar6004-hsic" for HSIC devcie.
+ "qca,ar6004-hsic" for HSIC device. For AR6003, "qca,ar6003-sdio" can be
+ used.
- qca,chip-pwd-l-gpios: specify GPIO for CHIP_PWD_L.
Optional Properties:
- cell-index: WLAN Hardware index.
- qca,pm-enable-gpios: Specify this GPIO if internal PMU needs to be used.
- - qca,ar6004-vbatt-supply: Specify this if VBATT is provided through a
- regulator.
- - qca,ar6004-vdd-io-supply: Specify this if VDD-IO is provided through a
+ - qca,vbatt-supply: Specify this if VBATT is provided through a regulator.
+ - qca,vdd-io-supply: Specify this if VDD-IO is provided through a
regulator.
Example:
@@ -20,5 +20,5 @@
compatible = "qca,ar6004-sdio";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
index 2764657..70f8b55 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-lpass.txt
@@ -10,7 +10,7 @@
- reg: Pairs of physical base addresses and region sizes of
memory mapped registers.
- reg-names: Names of the bases for the above registers. "qdsp6_base"
- and "halt_base" are expected.
+ "halt_base", and "restart_reg" are expected.
- interrupts: The lpass watchdog interrupt
- vdd_cx-supply: Reference to the regulator that supplies the vdd_cx domain.
- qcom,firmware-name: Base name of the firmware image. Ex. "lpass"
@@ -23,8 +23,9 @@
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
- <0xfd485100 0x00010>;
- reg-names = "qdsp6_base", "halt_base";
+ <0xfd485100 0x00010>,
+ <0xfc4016c0 0x00004>;
+ reg-names = "qdsp6_base", "halt_base", "restart_reg";
interrupts = <0 194 1>;
vdd_cx-supply = <&pm8841_s2>;
qcom,firmware-name = "lpass";
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index df3f71c..acd0ae3 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -10,13 +10,14 @@
- reg: Pairs of physical base addresses and region sizes of
memory mapped registers.
- reg-names: Names of the bases for the above registers. "qdsp6_base",
- "halt_base", "rmb_base", "restart_reg", and
- "metadata_base" are expected.
+ "halt_base", "rmb_base", and "restart_reg" are expected.
- interrupts: The modem watchdog interrupt
- vdd_mss-supply: Reference to the regulator that supplies the processor.
- vdd_cx-supply: Reference to the regulator that supplies the vdd_cx domain.
- vdd_mx-supply: Reference to the regulator that supplies the memory rail.
- qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
+- qcom,gpio-err-fatal: GPIO used by the modem to indicate error fatal to the apps.
+- qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
Optional properties:
- vdd_pll-supply: Reference to the regulator that supplies the PLL's rail.
@@ -32,10 +33,9 @@
reg = <0xfc880000 0x100>,
<0xfd485000 0x400>,
<0xfc820000 0x020>,
- <0xfc401680 0x004>,
- <0x0d1f0000 0x4000>;
+ <0xfc401680 0x004>;
reg-names = "qdsp6_base", "halt_base", "rmb_base",
- "restart_reg", metadata_base";
+ "restart_reg";
interrupts = <0 24 1>;
vdd_mss-supply = <&pm8841_s3>;
vdd_cx-supply = <&pm8841_s2>;
@@ -44,4 +44,10 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
+
+ /* GPIO inputs from mss */
+ gpio_err_fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ gpio_force_stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
diff --git a/Documentation/devicetree/bindings/power/opp.txt b/Documentation/devicetree/bindings/power/opp.txt
new file mode 100644
index 0000000..74499e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/opp.txt
@@ -0,0 +1,25 @@
+* Generic OPP Interface
+
+SoCs have a standard set of tuples consisting of frequency and
+voltage pairs that the device will support per voltage domain. These
+are called Operating Performance Points or OPPs.
+
+Properties:
+- operating-points: An array of 2-tuples items, and each item consists
+ of frequency and voltage like <freq-kHz vol-uV>.
+ freq: clock frequency in kHz
+ vol: voltage in microvolt
+
+Examples:
+
+cpu@0 {
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ next-level-cache = <&L2>;
+ operating-points = <
+ /* kHz uV */
+ 792000 1100000
+ 396000 950000
+ 198000 850000
+ >;
+};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 2832693..f5465a4 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -45,8 +45,8 @@
battery temperature of 250 decidegree
Celsius, state of charge to be 50%
and disable charging.
-- qcom,chg-warm-bat-degc: Warm battery temperature in degC.
-- qcom,chg-cool-bat-degc: Cool battery temperature in degC.
+- qcom,chg-warm-bat-decidegc: Warm battery temperature in decidegC.
+- qcom,chg-cool-bat-decidegc: Cool battery temperature in decidegC.
Note that if both warm and cool battery
temperatures are set, the corresponding
ibatmax and bat-mv properties are
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
index f1f4e94..3854598 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
@@ -20,6 +20,13 @@
- qcom,adc-bit-resolution : Bit resolution of the ADC.
- qcom,adc-vdd-reference : Voltage reference used by the ADC.
+Optional properties:
+- qcom,thermal-node : If present a thermal node is created and the channel is registered as
+ part of the thermal sysfs which allows clients to use the thermal framework
+ to set temperature thresholds and receive notification when the temperature
+ crosses a set threshold, read temperature and enable/set trip types supported
+ by the thermal framework.
+
Channel nodes
NOTE: Atleast one Channel node is required.
@@ -105,7 +112,7 @@
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1800>;
- /* Channel Node */
+ /* Channel Node to be registered as part of thermal sysfs */
chan@b5 {
label = "pa_therm1";
reg = <0xb5>;
@@ -116,5 +123,19 @@
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <0>;
qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
};
+
+ /* Channel Node */
+ chan@6 {
+ label = "vbat_sns";
+ reg = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x78>;
+ };
};
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
new file mode 100644
index 0000000..9ce5421
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -0,0 +1,20 @@
+synopsys DWC3 CORE
+
+DWC3- USB3 CONTROLLER
+
+Required properties:
+ - compatible: must be "synopsys,dwc3"
+ - reg : Address and length of the register set for the device
+ - interrupts: Interrupts used by the dwc3 controller.
+
+Optional properties:
+ - tx-fifo-resize: determines if the FIFO *has* to be reallocated.
+
+This is usually a subnode to DWC3 glue to which it is connected.
+
+dwc3@4a030000 {
+ compatible = "synopsys,dwc3";
+ reg = <0x4a030000 0xcfff>;
+ interrupts = <0 92 4>
+ tx-fifo-resize;
+};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 9f8bbd9..1fb2ba9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -10,6 +10,19 @@
Required "supply-name" is "HSIC_VDDCX" and optionally - "HSIC_GDSC".
Optional properties :
+- interrupt-parent - This must provide reference to the current
+ device node.
+- #address-cells - Should provide a value of 0.
+- interrupts - Should be <0 1 2> and it is an index to the
+ interrupt-map.
+- #interrupt-cells - should provide a value of 1.
+- #interrupt-mask - should provide a value of 0xffffffff.
+- interrupt-map - Must create mapping for the number of interrupts
+ that are defined in above interrupts property.
+ For HSIC device node, it should define 3 mappings for
+ core_irq, async_irq and wakeup in the format
+ mentioned in below example node of HSIC.
+
- interrupt-names : Optional interrupt resource entries are:
"async_irq" : Interrupt from HSIC for asynchronous events in HSIC LPM.
"wakeup" : Wakeup interrupt from HSIC during suspend (or XO shutdown).
@@ -25,21 +38,45 @@
STROBE GPIO PAD.
- hsic,data-pad-offset : Offset of TLMM register for configuring HSIC
DATA GPIO PAD.
+- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
+ below optional properties:
+ - qcom,msm_bus,name
+ - qcom,msm_bus,num_cases
+ - qcom,msm_bus,active_only
+ - qcom,msm_bus,num_paths
+ - qcom,msm_bus,vectors
+
Example MSM HSIC EHCI controller device node :
- hsic@f9a15000 {
+ hsic_host: hsic@f9a15000 {
compatible = "qcom,hsic-host";
reg = <0xf9a15000 0x400>;
- interrupts = <0 136 0>;
- interrupt-names = "core_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&hsic_host>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 136 0
+ 1 &intc 0 148 0
+ 2 &msmgpio 144 0x8>;
+ interrupt-names = "core_irq", "async_irq", "wakeup";
HSIC_VDDCX-supply = <&pm8019_l12>;
HSIC_GDSC-supply = <&gdsc_usb_hsic>;
hsic,strobe-gpio = <&msmgpio 144 0x00>;
hsic,data-gpio = <&msmgpio 145 0x00>;
+ hsic,resume-gpio = <&msmgpio 80 0x00>;
hsic,ignore-cal-pad-config;
hsic,strobe-pad-offset = <0x2050>;
hsic,data-pad-offset = <0x2054>;
- };
+
+ qcom,msm-bus,name = "hsic";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <85 512 0 0>,
+ <85 512 40000 160000>;
+ };
SMSC HSIC HUB
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 9a1c759..a5fac80 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -522,7 +522,7 @@
coherent_pool=nn[KMG] [ARM,KNL]
Sets the size of memory pool for coherent, atomic dma
- allocations if Contiguous Memory Allocator (CMA) is used.
+ allocations, by default set to 256K.
code_bytes [X86] How many bytes of object code to print
in an oops report.
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index f09a78a..2825288 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -136,6 +136,371 @@
29 01 00 00 00 02 5E 03
29 01 00 00 00 02 6C 00
29 01 00 00 00 02 6D 00
+ 29 01 00 00 00 02 FB 01
+ 29 01 00 00 00 02 FF 01
+ 29 01 00 00 00 02 FB 01
+ 29 01 00 00 00 02 75 00
+ 29 01 00 00 00 02 76 7D
+ 29 01 00 00 00 02 77 00
+ 29 01 00 00 00 02 78 8A
+ 29 01 00 00 00 02 79 00
+ 29 01 00 00 00 02 7A 9C
+ 29 01 00 00 00 02 7B 00
+ 29 01 00 00 00 02 7C B1
+ 29 01 00 00 00 02 7D 00
+ 29 01 00 00 00 02 7E BF
+ 29 01 00 00 00 02 7F 00
+ 29 01 00 00 00 02 80 CF
+ 29 01 00 00 00 02 81 00
+ 29 01 00 00 00 02 82 DD
+ 29 01 00 00 00 02 83 00
+ 29 01 00 00 00 02 84 E8
+ 29 01 00 00 00 02 85 00
+ 29 01 00 00 00 02 86 F2
+ 29 01 00 00 00 02 87 01
+ 29 01 00 00 00 02 88 1F
+ 29 01 00 00 00 02 89 01
+ 29 01 00 00 00 02 8A 41
+ 29 01 00 00 00 02 8B 01
+ 29 01 00 00 00 02 8C 78
+ 29 01 00 00 00 02 8D 01
+ 29 01 00 00 00 02 8E A5
+ 29 01 00 00 00 02 8F 01
+ 29 01 00 00 00 02 90 EE
+ 29 01 00 00 00 02 91 02
+ 29 01 00 00 00 02 92 29
+ 29 01 00 00 00 02 93 02
+ 29 01 00 00 00 02 94 2A
+ 29 01 00 00 00 02 95 02
+ 29 01 00 00 00 02 96 5D
+ 29 01 00 00 00 02 97 02
+ 29 01 00 00 00 02 98 93
+ 29 01 00 00 00 02 99 02
+ 29 01 00 00 00 02 9A B8
+ 29 01 00 00 00 02 9B 02
+ 29 01 00 00 00 02 9C E7
+ 29 01 00 00 00 02 9D 03
+ 29 01 00 00 00 02 9E 07
+ 29 01 00 00 00 02 9F 03
+ 29 01 00 00 00 02 A0 37
+ 29 01 00 00 00 02 A2 03
+ 29 01 00 00 00 02 A3 46
+ 29 01 00 00 00 02 A4 03
+ 29 01 00 00 00 02 A5 56
+ 29 01 00 00 00 02 A6 03
+ 29 01 00 00 00 02 A7 66
+ 29 01 00 00 00 02 A9 03
+ 29 01 00 00 00 02 AA 7A
+ 29 01 00 00 00 02 AB 03
+ 29 01 00 00 00 02 AC 93
+ 29 01 00 00 00 02 AD 03
+ 29 01 00 00 00 02 AE A3
+ 29 01 00 00 00 02 AF 03
+ 29 01 00 00 00 02 B0 B4
+ 29 01 00 00 00 02 B1 03
+ 29 01 00 00 00 02 B2 CB
+ 29 01 00 00 00 02 B3 00
+ 29 01 00 00 00 02 B4 7D
+ 29 01 00 00 00 02 B5 00
+ 29 01 00 00 00 02 B6 8A
+ 29 01 00 00 00 02 B7 00
+ 29 01 00 00 00 02 B8 9C
+ 29 01 00 00 00 02 B9 00
+ 29 01 00 00 00 02 BA B1
+ 29 01 00 00 00 02 BB 00
+ 29 01 00 00 00 02 BC BF
+ 29 01 00 00 00 02 BD 00
+ 29 01 00 00 00 02 BE CF
+ 29 01 00 00 00 02 BF 00
+ 29 01 00 00 00 02 C0 DD
+ 29 01 00 00 00 02 C1 00
+ 29 01 00 00 00 02 C2 E8
+ 29 01 00 00 00 02 C3 00
+ 29 01 00 00 00 02 C4 F2
+ 29 01 00 00 00 02 C5 01
+ 29 01 00 00 00 02 C6 1F
+ 29 01 00 00 00 02 C7 01
+ 29 01 00 00 00 02 C8 41
+ 29 01 00 00 00 02 C9 01
+ 29 01 00 00 00 02 CA 78
+ 29 01 00 00 00 02 CB 01
+ 29 01 00 00 00 02 CC A5
+ 29 01 00 00 00 02 CD 01
+ 29 01 00 00 00 02 CE EE
+ 29 01 00 00 00 02 CF 02
+ 29 01 00 00 00 02 D0 29
+ 29 01 00 00 00 02 D1 02
+ 29 01 00 00 00 02 D2 2A
+ 29 01 00 00 00 02 D3 02
+ 29 01 00 00 00 02 D4 5D
+ 29 01 00 00 00 02 D5 02
+ 29 01 00 00 00 02 D6 93
+ 29 01 00 00 00 02 D7 02
+ 29 01 00 00 00 02 D8 B8
+ 29 01 00 00 00 02 D9 02
+ 29 01 00 00 00 02 DA E7
+ 29 01 00 00 00 02 DB 03
+ 29 01 00 00 00 02 DC 07
+ 29 01 00 00 00 02 DD 03
+ 29 01 00 00 00 02 DE 37
+ 29 01 00 00 00 02 DF 03
+ 29 01 00 00 00 02 E0 46
+ 29 01 00 00 00 02 E1 03
+ 29 01 00 00 00 02 E2 56
+ 29 01 00 00 00 02 E3 03
+ 29 01 00 00 00 02 E4 66
+ 29 01 00 00 00 02 E5 03
+ 29 01 00 00 00 02 E6 7A
+ 29 01 00 00 00 02 E7 03
+ 29 01 00 00 00 02 E8 93
+ 29 01 00 00 00 02 E9 03
+ 29 01 00 00 00 02 EA A3
+ 29 01 00 00 00 02 EB 03
+ 29 01 00 00 00 02 EC B4
+ 29 01 00 00 00 02 ED 03
+ 29 01 00 00 00 02 EE CB
+ 29 01 00 00 00 02 EF 00
+ 29 01 00 00 00 02 F0 ED
+ 29 01 00 00 00 02 F1 00
+ 29 01 00 00 00 02 F2 F3
+ 29 01 00 00 00 02 F3 00
+ 29 01 00 00 00 02 F4 FE
+ 29 01 00 00 00 02 F5 01
+ 29 01 00 00 00 02 F6 09
+ 29 01 00 00 00 02 F7 01
+ 29 01 00 00 00 02 F8 13
+ 29 01 00 00 00 02 F9 01
+ 29 01 00 00 00 02 FA 1D
+ 29 01 00 00 00 02 FF 02
+ 29 01 00 00 00 02 FB 01
+ 29 01 00 00 00 02 00 01
+ 29 01 00 00 00 02 01 26
+ 29 01 00 00 00 02 02 01
+ 29 01 00 00 00 02 03 2F
+ 29 01 00 00 00 02 04 01
+ 29 01 00 00 00 02 05 37
+ 29 01 00 00 00 02 06 01
+ 29 01 00 00 00 02 07 56
+ 29 01 00 00 00 02 08 01
+ 29 01 00 00 00 02 09 70
+ 29 01 00 00 00 02 0A 01
+ 29 01 00 00 00 02 0B 9D
+ 29 01 00 00 00 02 0C 01
+ 29 01 00 00 00 02 0D C2
+ 29 01 00 00 00 02 0E 01
+ 29 01 00 00 00 02 0F FF
+ 29 01 00 00 00 02 10 02
+ 29 01 00 00 00 02 11 31
+ 29 01 00 00 00 02 12 02
+ 29 01 00 00 00 02 13 32
+ 29 01 00 00 00 02 14 02
+ 29 01 00 00 00 02 15 60
+ 29 01 00 00 00 02 16 02
+ 29 01 00 00 00 02 17 94
+ 29 01 00 00 00 02 18 02
+ 29 01 00 00 00 02 19 B5
+ 29 01 00 00 00 02 1A 02
+ 29 01 00 00 00 02 1B E3
+ 29 01 00 00 00 02 1C 03
+ 29 01 00 00 00 02 1D 03
+ 29 01 00 00 00 02 1E 03
+ 29 01 00 00 00 02 1F 2D
+ 29 01 00 00 00 02 20 03
+ 29 01 00 00 00 02 21 3A
+ 29 01 00 00 00 02 22 03
+ 29 01 00 00 00 02 23 48
+ 29 01 00 00 00 02 24 03
+ 29 01 00 00 00 02 25 57
+ 29 01 00 00 00 02 26 03
+ 29 01 00 00 00 02 27 68
+ 29 01 00 00 00 02 28 03
+ 29 01 00 00 00 02 29 7B
+ 29 01 00 00 00 02 2A 03
+ 29 01 00 00 00 02 2B 90
+ 29 01 00 00 00 02 2D 03
+ 29 01 00 00 00 02 2F A0
+ 29 01 00 00 00 02 30 03
+ 29 01 00 00 00 02 31 CB
+ 29 01 00 00 00 02 32 00
+ 29 01 00 00 00 02 33 ED
+ 29 01 00 00 00 02 34 00
+ 29 01 00 00 00 02 35 F3
+ 29 01 00 00 00 02 36 00
+ 29 01 00 00 00 02 37 FE
+ 29 01 00 00 00 02 38 01
+ 29 01 00 00 00 02 39 09
+ 29 01 00 00 00 02 3A 01
+ 29 01 00 00 00 02 3B 13
+ 29 01 00 00 00 02 3D 01
+ 29 01 00 00 00 02 3F 1D
+ 29 01 00 00 00 02 40 01
+ 29 01 00 00 00 02 41 26
+ 29 01 00 00 00 02 42 01
+ 29 01 00 00 00 02 43 2F
+ 29 01 00 00 00 02 44 01
+ 29 01 00 00 00 02 45 37
+ 29 01 00 00 00 02 46 01
+ 29 01 00 00 00 02 47 56
+ 29 01 00 00 00 02 48 01
+ 29 01 00 00 00 02 49 70
+ 29 01 00 00 00 02 4A 01
+ 29 01 00 00 00 02 4B 9D
+ 29 01 00 00 00 02 4C 01
+ 29 01 00 00 00 02 4D C2
+ 29 01 00 00 00 02 4E 01
+ 29 01 00 00 00 02 4F FF
+ 29 01 00 00 00 02 50 02
+ 29 01 00 00 00 02 51 31
+ 29 01 00 00 00 02 52 02
+ 29 01 00 00 00 02 53 32
+ 29 01 00 00 00 02 54 02
+ 29 01 00 00 00 02 55 60
+ 29 01 00 00 00 02 56 02
+ 29 01 00 00 00 02 58 94
+ 29 01 00 00 00 02 59 02
+ 29 01 00 00 00 02 5A B5
+ 29 01 00 00 00 02 5B 02
+ 29 01 00 00 00 02 5C E3
+ 29 01 00 00 00 02 5D 03
+ 29 01 00 00 00 02 5E 03
+ 29 01 00 00 00 02 5F 03
+ 29 01 00 00 00 02 60 2D
+ 29 01 00 00 00 02 61 03
+ 29 01 00 00 00 02 62 3A
+ 29 01 00 00 00 02 63 03
+ 29 01 00 00 00 02 64 48
+ 29 01 00 00 00 02 65 03
+ 29 01 00 00 00 02 66 57
+ 29 01 00 00 00 02 67 03
+ 29 01 00 00 00 02 68 68
+ 29 01 00 00 00 02 69 03
+ 29 01 00 00 00 02 6A 7B
+ 29 01 00 00 00 02 6B 03
+ 29 01 00 00 00 02 6C 90
+ 29 01 00 00 00 02 6D 03
+ 29 01 00 00 00 02 6E A0
+ 29 01 00 00 00 02 6F 03
+ 29 01 00 00 00 02 70 CB
+ 29 01 00 00 00 02 71 00
+ 29 01 00 00 00 02 72 19
+ 29 01 00 00 00 02 73 00
+ 29 01 00 00 00 02 74 36
+ 29 01 00 00 00 02 75 00
+ 29 01 00 00 00 02 76 55
+ 29 01 00 00 00 02 77 00
+ 29 01 00 00 00 02 78 70
+ 29 01 00 00 00 02 79 00
+ 29 01 00 00 00 02 7A 83
+ 29 01 00 00 00 02 7B 00
+ 29 01 00 00 00 02 7C 99
+ 29 01 00 00 00 02 7D 00
+ 29 01 00 00 00 02 7E A8
+ 29 01 00 00 00 02 7F 00
+ 29 01 00 00 00 02 80 B7
+ 29 01 00 00 00 02 81 00
+ 29 01 00 00 00 02 82 C5
+ 29 01 00 00 00 02 83 00
+ 29 01 00 00 00 02 84 F7
+ 29 01 00 00 00 02 85 01
+ 29 01 00 00 00 02 86 1E
+ 29 01 00 00 00 02 87 01
+ 29 01 00 00 00 02 88 60
+ 29 01 00 00 00 02 89 01
+ 29 01 00 00 00 02 8A 95
+ 29 01 00 00 00 02 8B 01
+ 29 01 00 00 00 02 8C E1
+ 29 01 00 00 00 02 8D 02
+ 29 01 00 00 00 02 8E 20
+ 29 01 00 00 00 02 8F 02
+ 29 01 00 00 00 02 90 23
+ 29 01 00 00 00 02 91 02
+ 29 01 00 00 00 02 92 59
+ 29 01 00 00 00 02 93 02
+ 29 01 00 00 00 02 94 94
+ 29 01 00 00 00 02 95 02
+ 29 01 00 00 00 02 96 B4
+ 29 01 00 00 00 02 97 02
+ 29 01 00 00 00 02 98 E1
+ 29 01 00 00 00 02 99 03
+ 29 01 00 00 00 02 9A 01
+ 29 01 00 00 00 02 9B 03
+ 29 01 00 00 00 02 9C 28
+ 29 01 00 00 00 02 9D 03
+ 29 01 00 00 00 02 9E 30
+ 29 01 00 00 00 02 9F 03
+ 29 01 00 00 00 02 A0 37
+ 29 01 00 00 00 02 A2 03
+ 29 01 00 00 00 02 A3 3B
+ 29 01 00 00 00 02 A4 03
+ 29 01 00 00 00 02 A5 40
+ 29 01 00 00 00 02 A6 03
+ 29 01 00 00 00 02 A7 50
+ 29 01 00 00 00 02 A9 03
+ 29 01 00 00 00 02 AA 6D
+ 29 01 00 00 00 02 AB 03
+ 29 01 00 00 00 02 AC 80
+ 29 01 00 00 00 02 AD 03
+ 29 01 00 00 00 02 AE CB
+ 29 01 00 00 00 02 AF 00
+ 29 01 00 00 00 02 B0 19
+ 29 01 00 00 00 02 B1 00
+ 29 01 00 00 00 02 B2 36
+ 29 01 00 00 00 02 B3 00
+ 29 01 00 00 00 02 B4 55
+ 29 01 00 00 00 02 B5 00
+ 29 01 00 00 00 02 B6 70
+ 29 01 00 00 00 02 B7 00
+ 29 01 00 00 00 02 B8 83
+ 29 01 00 00 00 02 B9 00
+ 29 01 00 00 00 02 BA 99
+ 29 01 00 00 00 02 BB 00
+ 29 01 00 00 00 02 BC A8
+ 29 01 00 00 00 02 BD 00
+ 29 01 00 00 00 02 BE B7
+ 29 01 00 00 00 02 BF 00
+ 29 01 00 00 00 02 C0 C5
+ 29 01 00 00 00 02 C1 00
+ 29 01 00 00 00 02 C2 F7
+ 29 01 00 00 00 02 C3 01
+ 29 01 00 00 00 02 C4 1E
+ 29 01 00 00 00 02 C5 01
+ 29 01 00 00 00 02 C6 60
+ 29 01 00 00 00 02 C7 01
+ 29 01 00 00 00 02 C8 95
+ 29 01 00 00 00 02 C9 01
+ 29 01 00 00 00 02 CA E1
+ 29 01 00 00 00 02 CB 02
+ 29 01 00 00 00 02 CC 20
+ 29 01 00 00 00 02 CD 02
+ 29 01 00 00 00 02 CE 23
+ 29 01 00 00 00 02 CF 02
+ 29 01 00 00 00 02 D0 59
+ 29 01 00 00 00 02 D1 02
+ 29 01 00 00 00 02 D2 94
+ 29 01 00 00 00 02 D3 02
+ 29 01 00 00 00 02 D4 B4
+ 29 01 00 00 00 02 D5 02
+ 29 01 00 00 00 02 D6 E1
+ 29 01 00 00 00 02 D7 03
+ 29 01 00 00 00 02 D8 01
+ 29 01 00 00 00 02 D9 03
+ 29 01 00 00 00 02 DA 28
+ 29 01 00 00 00 02 DB 03
+ 29 01 00 00 00 02 DC 30
+ 29 01 00 00 00 02 DD 03
+ 29 01 00 00 00 02 DE 37
+ 29 01 00 00 00 02 DF 03
+ 29 01 00 00 00 02 E0 3B
+ 29 01 00 00 00 02 E1 03
+ 29 01 00 00 00 02 E2 40
+ 29 01 00 00 00 02 E3 03
+ 29 01 00 00 00 02 E4 50
+ 29 01 00 00 00 02 E5 03
+ 29 01 00 00 00 02 E6 6D
+ 29 01 00 00 00 02 E7 03
+ 29 01 00 00 00 02 E8 80
+ 29 01 00 00 00 02 E9 03
+ 29 01 00 00 00 02 EA CB
29 01 00 00 00 02 FF 01
29 01 00 00 00 02 FB 01
29 01 00 00 00 02 FF 02
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index c488ab1..ec42cfc 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -95,5 +95,225 @@
reg = <0x1>;
#address-cells = <1>;
#size-cells = <1>;
+
+ regulator@1400 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1400 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ regulator@1700 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_s2";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1700 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
+ };
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
+ };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
+ };
+ };
+
+ regulator@1a00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1a00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
+ };
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
+ };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
+ };
+ };
+
+ regulator@1d00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_s4";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1d00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1d00 {
+ reg = <0x1d00 0x100>;
+ };
+ qcom,ps@1e00 {
+ reg = <0x1e00 0x100>;
+ };
+ qcom,freq@1f00 {
+ reg = <0x1f00 0x100>;
+ };
+ };
+
+ regulator@4000 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l1";
+ reg = <0x4000 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4100 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l2";
+ reg = <0x4100 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4200 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l3";
+ reg = <0x4200 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4300 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l4";
+ reg = <0x4300 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4400 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l5";
+ reg = <0x4400 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4500 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l6";
+ reg = <0x4500 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4600 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l7";
+ reg = <0x4600 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4700 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l8";
+ reg = <0x4700 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4800 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l9";
+ reg = <0x4800 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4900 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l10";
+ reg = <0x4900 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4b00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l12";
+ reg = <0x4b00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4d00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l14";
+ reg = <0x4d00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4e00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l15";
+ reg = <0x4e00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4f00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l16";
+ reg = <0x4f00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5000 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l17";
+ reg = <0x5000 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5100 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l18";
+ reg = <0x5100 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5200 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l19";
+ reg = <0x5200 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5300 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l20";
+ reg = <0x5300 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5400 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l21";
+ reg = <0x5400 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5500 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8110_l22";
+ reg = <0x5500 0x100>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index b996766..e2b6a66 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -152,6 +152,54 @@
};
};
+ pm8226_bms: qcom,bms {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-bms";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,r-sense-uohm = <10000>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,r-conn-mohm = <18>;
+ qcom,shutdown-soc-valid-limit = <20>;
+ qcom,adjust-soc-low-threshold = <25>;
+ qcom,adjust-soc-high-threshold = <45>;
+ qcom,ocv-voltage-high-threshold-uv = <3750000>;
+ qcom,ocv-voltage-low-threshold-uv = <3650000>;
+ qcom,low-soc-calculate-soc-threshold = <15>;
+ qcom,low-soc-calculate-soc-ms = <5000>;
+ qcom,calculate-soc-ms = <20000>;
+ qcom,chg-term-ua = <100000>;
+ qcom,batt-type = <0>;
+
+ qcom,bms-iadc@3800 {
+ reg = <0x3800 0x100>;
+ };
+
+ qcom,bms-bms@4000 {
+ reg = <0x4000 0x100>;
+ interrupts = <0x0 0x40 0x0>,
+ <0x0 0x40 0x1>,
+ <0x0 0x40 0x2>,
+ <0x0 0x40 0x3>,
+ <0x0 0x40 0x4>,
+ <0x0 0x40 0x5>,
+ <0x0 0x40 0x6>,
+ <0x0 0x40 0x7>;
+
+ interrupt-names = "vsense_for_r",
+ "vsense_avg",
+ "sw_cc_thr",
+ "ocv_thr",
+ "charge_begin",
+ "good_ocv",
+ "ocv_for_r",
+ "cc_thr";
+ };
+ };
+
pm8226_gpios: gpios {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
@@ -294,6 +342,17 @@
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@c {
+ label = "ref_buf_625mv";
+ reg = <0xc>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
};
iadc@3600 {
@@ -630,5 +689,43 @@
compatible = "qcom,qpnp-regulator";
status = "disabled";
};
+
+ qcom,leds@d300 {
+ compatible = "qcom,leds-qpnp";
+ status = "disable";
+ reg = <0xd300 0x100>;
+ label = "flash";
+ pm8226_flash0: qcom,flash_0 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <0>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <1>;
+ qcom,safety-timer;
+ label = "flash";
+ linux,default-trigger =
+ "flash0_trigger";
+ qcom,id = <1>;
+ linux,name = "led:flash_0";
+ qcom,current = <625>;
+ };
+
+ pm8226_flash1: qcom,flash_1 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <0>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <1>;
+ qcom,safety-timer;
+ linux,default-trigger =
+ "flash1_trigger";
+ label = "flash";
+ qcom,id = <2>;
+ linux,name = "led:flash_1";
+ qcom,current = <625>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 320c3e4a..9761e01 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -22,6 +22,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ pm8941_misc: qcom,misc@900 {
+ compatible = "qcom,qpnp-misc";
+ reg = <0x900 0x100>;
+ };
+
qcom,revid@100 {
compatible = "qcom,qpnp-revid";
reg = <0x100 0x100>;
@@ -170,10 +175,10 @@
qcom,chg-ibatmax-ma = <1500>;
qcom,chg-ibatsafe-ma = <1500>;
qcom,chg-thermal-mitigation = <1500 700 600 325>;
- qcom,chg-cool-bat-degc = <10>;
+ qcom,chg-cool-bat-decidegc = <100>;
qcom,chg-cool-bat-mv = <4100>;
qcom,chg-ibatmax-warm-ma = <350>;
- qcom,chg-warm-bat-degc = <45>;
+ qcom,chg-warm-bat-decidegc = <450>;
qcom,chg-warm-bat-mv = <4100>;
qcom,chg-ibatmax-cool-ma = <350>;
qcom,chg-vbatdet-delta-mv = <350>;
@@ -825,6 +830,30 @@
qcom,btm-channel-number = <0x68>;
};
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <1>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x88>;
+ };
+
+ chan@6 {
+ label = "vbat_sns";
+ reg = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x90>;
+ };
+
chan@b5 {
label = "pa_therm1";
reg = <0xb5>;
@@ -835,6 +864,7 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
};
chan@b7 {
@@ -847,6 +877,7 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
qcom,btm-channel-number = <0x78>;
+ qcom,thermal-node;
};
chan@b4 {
@@ -859,6 +890,20 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
qcom,btm-channel-number = <0x80>;
+ qcom,thermal-node;
+ };
+
+ chan@b3 {
+ label = "msm_therm";
+ reg = <0xb3>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ qcom,btm-channel-number = <0x98>;
+ qcom,thermal-node;
};
};
};
diff --git a/arch/arm/boot/dts/msm8226-bus.dtsi b/arch/arm/boot/dts/msm8226-bus.dtsi
index 750e591..3c41e9e 100644
--- a/arch/arm/boot/dts/msm8226-bus.dtsi
+++ b/arch/arm/boot/dts/msm8226-bus.dtsi
@@ -1012,8 +1012,8 @@
qcom,qport = <0>;
qcom,ws = <10000>;
qcom,mas-hw-id = <0>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
};
mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
new file mode 100644
index 0000000..b7f837f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+
+ led_flash0: qcom,camera-led-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-led-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+ };
+};
+
+&cci {
+
+ actuator0: qcom,actuator@6e {
+ cell-index = <3>;
+ reg = <0x6c 0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov8825";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
index 2a9fdf2..e94459e 100644
--- a/arch/arm/boot/dts/msm8226-camera.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -1,4 +1,5 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,8 +12,125 @@
*/
/ {
- qcom,cam_server {
- compatible = "qcom,cam_server";
- reg = <0xfd8C0000 0x10000>;
+ qcom,msm-cam@fd8c0000 {
+ compatible = "qcom,msm-cam";
+ reg = <0xfd8c0000 0x10000>;
+ reg-names = "msm-cam";
+ };
+
+ qcom,csiphy@fda0ac00 {
+ cell-index = <0>;
+ compatible = "qcom,csiphy";
+ reg = <0xfda0ac00 0x200>;
+ reg-names = "csiphy";
+ interrupts = <0 78 0>;
+ interrupt-names = "csiphy";
+ };
+
+ qcom,csiphy@fda0b000 {
+ cell-index = <1>;
+ compatible = "qcom,csiphy";
+ reg = <0xfda0b000 0x200>;
+ reg-names = "csiphy";
+ interrupts = <0 79 0>;
+ interrupt-names = "csiphy";
+ };
+
+ qcom,csid@fda08000 {
+ cell-index = <0>;
+ compatible = "qcom,csid";
+ reg = <0xfda08000 0x100>;
+ reg-names = "csid";
+ interrupts = <0 51 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8226_l4>;
+ };
+
+ qcom,csid@fda08400 {
+ cell-index = <1>;
+ compatible = "qcom,csid";
+ reg = <0xfda08400 0x100>;
+ reg-names = "csid";
+ interrupts = <0 52 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8226_l4>;
+ };
+
+ qcom,ispif@fda0a000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif";
+ reg = <0xfda0a000 0x500>;
+ reg-names = "ispif";
+ interrupts = <0 55 0>;
+ interrupt-names = "ispif";
+ };
+
+ qcom,vfe@fda10000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe40";
+ reg = <0xfda10000 0x1000>,
+ <0xfda40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 57 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe>;
+ };
+
+ qcom,jpeg@fda1c000 {
+ cell-index = <0>;
+ compatible = "qcom,jpeg";
+ reg = <0xfda1c000 0x400>;
+ reg-names = "jpeg";
+ interrupts = <0 59 0>;
+ interrupt-names = "jpeg";
+ vdd-supply = <&gdsc_jpeg>;
+ };
+
+ qcom,irqrouter@fda00000 {
+ cell-index = <0>;
+ compatible = "qcom,irqrouter";
+ reg = <0xfda00000 0x100>;
+ reg-names = "irqrouter";
+ };
+
+ qcom,cpp@fda04000 {
+ cell-index = <0>;
+ compatible = "qcom,cpp";
+ reg = <0xfda04000 0x100>,
+ <0xfda40000 0x200>,
+ <0xfda18000 0x008>;
+ reg-names = "cpp", "cpp_vbif", "cpp_hw";
+ interrupts = <0 49 0>;
+ interrupt-names = "cpp";
+ vdd-supply = <&gdsc_vfe>;
+ };
+
+ cci: qcom,cci@fda0c000 {
+ cell-index = <0>;
+ compatible = "qcom,cci";
+ reg = <0xfda0c000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "cci";
+ interrupts = <0 50 0>;
+ interrupt-names = "cci";
+ gpios = <&msmgpio 29 0>,
+ <&msmgpio 30 0>;
+ qcom,gpio-tbl-num = <0 1>;
+ qcom,gpio-tbl-flags = <1 1>;
+ qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+ "CCI_I2C_CLK0";
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index fa77c35..04b7c7e 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
/ {
model = "Qualcomm MSM 8226 CDP";
@@ -89,7 +90,30 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 Internal1",
+ "MIC BIAS1 Internal1", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic",
+ "DMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic1",
+ "DMIC2", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic2",
+ "DMIC3", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic3",
+ "DMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic4";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
};
@@ -193,6 +217,13 @@
};
gpio@c100 { /* GPIO 2 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-sel = <2>;
+ qcom,master-en = <1>;
};
gpio@c200 { /* GPIO 3 */
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index b891d3d..35d329c 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -15,7 +15,7 @@
compatible = "arm,coresight-tmc";
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
- reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+ reg-names = "tmc-base", "bam-base";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
@@ -52,7 +52,7 @@
tmc_etf: tmc@fc307000 {
compatible = "arm,coresight-tmc";
reg = <0xfc307000 0x1000>;
- reg-names = "tmc-etf-base";
+ reg-names = "tmc-base";
coresight-id = <3>;
coresight-name = "coresight-tmc-etf";
@@ -67,7 +67,7 @@
funnel_merg: funnel@fc31b000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31b000 0x1000>;
- reg-names = "funnel-merg-base";
+ reg-names = "funnel-base";
coresight-id = <4>;
coresight-name = "coresight-funnel-merg";
@@ -80,7 +80,7 @@
funnel_in0: funnel@fc319000 {
compatible = "arm,coresight-funnel";
reg = <0xfc319000 0x1000>;
- reg-names = "funnel-in0-base";
+ reg-names = "funnel-base";
coresight-id = <5>;
coresight-name = "coresight-funnel-in0";
@@ -93,7 +93,7 @@
funnel_in1: funnel@fc31a000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31a000 0x1000>;
- reg-names = "funnel-in1-base";
+ reg-names = "funnel-base";
coresight-id = <6>;
coresight-name = "coresight-funnel-in1";
@@ -106,7 +106,7 @@
funnel_a7ss: funnel@fc345000 {
compatible = "arm,coresight-funnel";
reg = <0xfc345000 0x1000>;
- reg-names = "funnel-a7ss-base";
+ reg-names = "funnel-base";
coresight-id = <7>;
coresight-name = "coresight-funnel-a7ss";
@@ -119,7 +119,7 @@
funnel_mmss: funnel@fc364000 {
compatible = "arm,coresight-funnel";
reg = <0xfc364000 0x1000>;
- reg-names = "funnel-mmss-base";
+ reg-names = "funnel-base";
coresight-id = <8>;
@@ -147,7 +147,7 @@
etm0: etm@fc33c000 {
compatible = "arm,coresight-etm";
reg = <0xfc33c000 0x1000>;
- reg-names = "etm0-base";
+ reg-names = "etm-base";
coresight-id = <10>;
coresight-name = "coresight-etm0";
@@ -162,7 +162,7 @@
etm1: etm@fc33d000 {
compatible = "arm,coresight-etm";
reg = <0xfc33d000 0x1000>;
- reg-names = "etm1-base";
+ reg-names = "etm-base";
coresight-id = <11>;
coresight-name = "coresight-etm1";
@@ -177,7 +177,7 @@
etm2: etm@fc33e000 {
compatible = "arm,coresight-etm";
reg = <0xfc33e000 0x1000>;
- reg-names = "etm2-base";
+ reg-names = "etm-base";
coresight-id = <12>;
coresight-name = "coresight-etm2";
@@ -192,7 +192,7 @@
etm3: etm@fc33f000 {
compatible = "arm,coresight-etm";
reg = <0xfc33f000 0x1000>;
- reg-names = "etm3-base";
+ reg-names = "etm-base";
coresight-id = <13>;
coresight-name = "coresight-etm3";
@@ -219,7 +219,7 @@
cti0: cti@fc308000 {
compatible = "arm,coresight-cti";
reg = <0xfc308000 0x1000>;
- reg-names = "cti0-base";
+ reg-names = "cti-base";
coresight-id = <15>;
coresight-name = "coresight-cti0";
@@ -229,7 +229,7 @@
cti1: cti@fc309000 {
compatible = "arm,coresight-cti";
reg = <0xfc309000 0x1000>;
- reg-names = "cti1-base";
+ reg-names = "cti-base";
coresight-id = <16>;
coresight-name = "coresight-cti1";
@@ -239,7 +239,7 @@
cti2: cti@fc30a000 {
compatible = "arm,coresight-cti";
reg = <0xfc30a000 0x1000>;
- reg-names = "cti2-base";
+ reg-names = "cti-base";
coresight-id = <17>;
coresight-name = "coresight-cti2";
@@ -249,7 +249,7 @@
cti3: cti@fc30b000 {
compatible = "arm,coresight-cti";
reg = <0xfc30b000 0x1000>;
- reg-names = "cti3-base";
+ reg-names = "cti-base";
coresight-id = <18>;
coresight-name = "coresight-cti3";
@@ -259,7 +259,7 @@
cti4: cti@fc30c000 {
compatible = "arm,coresight-cti";
reg = <0xfc30c000 0x1000>;
- reg-names = "cti4-base";
+ reg-names = "cti-base";
coresight-id = <19>;
coresight-name = "coresight-cti4";
@@ -269,7 +269,7 @@
cti5: cti@fc30d000 {
compatible = "arm,coresight-cti";
reg = <0xfc30d000 0x1000>;
- reg-names = "cti5-base";
+ reg-names = "cti-base";
coresight-id = <20>;
coresight-name = "coresight-cti5";
@@ -279,7 +279,7 @@
cti6: cti@fc30e000 {
compatible = "arm,coresight-cti";
reg = <0xfc30e000 0x1000>;
- reg-names = "cti6-base";
+ reg-names = "cti-base";
coresight-id = <21>;
coresight-name = "coresight-cti6";
@@ -289,7 +289,7 @@
cti7: cti@fc30f000 {
compatible = "arm,coresight-cti";
reg = <0xfc30f000 0x1000>;
- reg-names = "cti7-base";
+ reg-names = "cti-base";
coresight-id = <22>;
coresight-name = "coresight-cti7";
@@ -299,7 +299,7 @@
cti8: cti@fc310000 {
compatible = "arm,coresight-cti";
reg = <0xfc310000 0x1000>;
- reg-names = "cti8-base";
+ reg-names = "cti-base";
coresight-id = <23>;
coresight-name = "coresight-cti8";
@@ -309,7 +309,7 @@
cti_l2: cti@fc340000 {
compatible = "arm,coresight-cti";
reg = <0xfc340000 0x1000>;
- reg-names = "cti-l2-base";
+ reg-names = "cti-base";
coresight-id = <24>;
coresight-name = "coresight-cti-l2";
@@ -319,7 +319,7 @@
cti_cpu0: cti@fc341000 {
compatible = "arm,coresight-cti";
reg = <0xfc341000 0x1000>;
- reg-names = "cti-cpu0-base";
+ reg-names = "cti-base";
coresight-id = <25>;
coresight-name = "coresight-cti-cpu0";
@@ -329,7 +329,7 @@
cti_cpu1: cti@fc342000 {
compatible = "arm,coresight-cti";
reg = <0xfc342000 0x1000>;
- reg-names = "cti-cpu1-base";
+ reg-names = "cti-base";
coresight-id = <26>;
coresight-name = "coresight-cti-cpu1";
@@ -339,7 +339,7 @@
cti_cpu2: cti@fc343000 {
compatible = "arm,coresight-cti";
reg = <0xfc343000 0x1000>;
- reg-names = "cti-cpu2-base";
+ reg-names = "cti-base";
coresight-id = <27>;
coresight-name = "coresight-cti-cpu2";
@@ -349,7 +349,7 @@
cti_cpu3: cti@fc344000 {
compatible = "arm,coresight-cti";
reg = <0xfc344000 0x1000>;
- reg-names = "cti-cpu3-base";
+ reg-names = "cti-base";
coresight-id = <28>;
coresight-name = "coresight-cti-cpu3";
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index 2734726..ebd7749 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -24,9 +24,9 @@
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
- <26 512 0 1600000>, <89 604 0 6400000>,
- <26 512 0 3200000>, <89 604 0 12800000>,
- <26 512 0 4264000>, <89 604 0 12800000>;
+ <26 512 0 1600000>, <89 604 0 3200000>,
+ <26 512 0 3200000>, <89 604 0 5120000>,
+ <26 512 0 4256000>, <89 604 0 6400000>;
/* GDSC oxili regulators */
vddcx-supply = "\0";
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 21ed66a..9c76512 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -19,6 +19,7 @@
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ qcom,max-clk-rate = <200000000>;
qcom,mdss-pipe-vig-off = <0x00001200>;
qcom,mdss-pipe-rgb-off = <0x00001E00>;
qcom,mdss-pipe-dma-off = <0x00002A00>;
@@ -33,6 +34,7 @@
qcom,mdss-dspp-off = <0x00004600>;
qcom,mdss-wb-off = <0x00011100 0x00013100>;
qcom,mdss-intf-off = <0x00000000 0x00021300>;
+ qcom,mdss-rot-block-size = <64>;
qcom,vbif-settings = <0x004 0x00000001>,
<0x0D8 0x00000707>,
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index e747cb5..be831b4 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
/ {
model = "Qualcomm MSM 8226 MTP";
@@ -89,7 +90,22 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
};
@@ -155,6 +171,10 @@
&spmi_bus {
qcom,pm8226@1 {
+ qcom,leds@d300 {
+ status = "okay";
+ };
+
qcom,leds@d800 {
status = "okay";
qcom,wled_0 {
@@ -190,6 +210,13 @@
};
gpio@c100 { /* GPIO 2 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-sel = <2>;
+ qcom,master-en = <1>;
};
gpio@c200 { /* GPIO 3 */
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index acc4597..6bd5ea9 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
+/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
/ {
model = "Qualcomm MSM 8226 QRD";
@@ -89,7 +90,22 @@
};
sound {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
};
@@ -158,6 +174,10 @@
&spmi_bus {
qcom,pm8226@1 {
+ qcom,leds@d300 {
+ status = "okay";
+ };
+
qcom,leds@d800 {
status = "okay";
qcom,wled_0 {
@@ -193,6 +213,13 @@
};
gpio@c100 { /* GPIO 2 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <2>;
+ qcom,out-strength = <3>;
+ qcom,src-sel = <2>;
+ qcom,master-en = <1>;
};
gpio@c200 { /* GPIO 3 */
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index c39d987..448a5be 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,18 +10,16 @@
* GNU General Public License for more details.
*/
-/* QPNP controlled regulators: */
+/* SPM controlled regulators: */
&spmi_bus {
qcom,pm8226@1 {
- pm8226_s2: regulator@1700 {
- status = "okay";
+ pm8226_s2: spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
regulator-name = "8226_s2";
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1150000>;
- regulator-always-on;
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1275000>;
};
};
};
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
index 60f63a8..1b08246 100644
--- a/arch/arm/boot/dts/msm8226-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -12,8 +12,7 @@
/ {
qcom,smp2p-modem {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <1>;
qcom,irq-bitmask = <0x4000>;
interrupts = <0 27 1>;
@@ -21,8 +20,7 @@
qcom,smp2p-adsp {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <2>;
qcom,irq-bitmask = <0x400>;
interrupts = <0 158 1>;
@@ -30,8 +28,7 @@
qcom,smp2p-wcnss {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <4>;
qcom,irq-bitmask = <0x40000>;
interrupts = <0 143 1>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 0bc8efd..25c534b 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -12,6 +12,7 @@
/include/ "skeleton.dtsi"
/include/ "msm8226-ion.dtsi"
+/include/ "msm8226-camera.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8226-iommu.dtsi"
/include/ "msm8226-pm.dtsi"
@@ -227,27 +228,6 @@
sound {
compatible = "qcom,msm8226-audio-tapan";
qcom,model = "msm8226-tapan-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "AMIC1", "MIC BIAS1 Internal1",
- "MIC BIAS1 Internal1", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCRight Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic",
- "DMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Digital Mic1",
- "DMIC2", "MIC BIAS1 External",
- "MIC BIAS1 External", "Digital Mic2",
- "DMIC3", "MIC BIAS3 External",
- "MIC BIAS3 External", "Digital Mic3",
- "DMIC4", "MIC BIAS3 External",
- "MIC BIAS3 External", "Digital Mic4";
-
qcom,tapan-mclk-clk-freq = <9600000>;
};
@@ -380,11 +360,63 @@
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <240>;
};
+
+ qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
};
qcom,msm-pcm-hostless {
compatible = "qcom,msm-pcm-hostless";
};
+ qcom,pronto@fb21b000 {
+ compatible = "qcom,pil-pronto";
+ reg = <0xfb21b000 0x3000>,
+ <0xfc401700 0x4>,
+ <0xfd485300 0xc>;
+ reg-names = "pmu_base", "clk_base", "halt_base";
+ interrupts = <0 149 1>;
+ vdd_pronto_pll-supply = <&pm8226_l12>;
+
+ qcom,firmware-name = "wcnss";
+ };
+ qcom,wcnss-wlan@fb000000 {
+ compatible = "qcom,wcnss_wlan";
+ reg = <0xfb000000 0x280000>;
+ reg-names = "wcnss_mmio";
+ interrupts = <0 145 0 0 146 0>;
+ interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+ qcom,pronto-vddmx-supply = <&pm8226_l3>;
+ qcom,pronto-vddcx-supply = <&pm8226_s1>;
+ qcom,pronto-vddpx-supply = <&pm8226_l6>;
+ qcom,iris-vddxo-supply = <&pm8226_l10>;
+ qcom,iris-vddrfa-supply = <&pm8226_l24>;
+ qcom,iris-vddpa-supply = <&pm8226_l16>;
+ qcom,iris-vdddig-supply = <&pm8226_l24>;
+
+ gpios = <&msmgpio 40 0>, <&msmgpio 41 0>, <&msmgpio 42 0>, <&msmgpio 43 0>, <&msmgpio 44 0>;
+ qcom,has_pronto_hw;
+ };
+
+ qcom,msm-adsp-sensors {
+ compatible = "qcom,msm-adsp-sensors";
+ qcom,src-id = <11>;
+ qcom,dst-id = <604>;
+ qcom,ab = <32505856>;
+ qcom,ib = <32505856>;
+ };
qcom,wdt@f9017000 {
compatible = "qcom,msm-watchdog";
@@ -591,11 +623,16 @@
qcom,firmware-name = "wcnss";
};
+ qcom,iris-fm {
+ compatible = "qcom,iris_fm";
+ };
+
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
- <0xfd485100 0x00010>;
- reg-names = "qdsp6_base", "halt_base";
+ <0xfd485100 0x00010>,
+ <0xfc4016c0 0x00004>;
+ reg-names = "qdsp6_base", "halt_base", "restart_reg";
vdd_cx-supply = <&pm8226_s1_corner>;
interrupts = <0 162 1>;
@@ -608,10 +645,9 @@
<0xfd485000 0x400>,
<0xfc820000 0x020>,
<0xfc401680 0x004>,
- <0x0d1fc000 0x4000>,
<0xfd485194 0x4>;
reg-names = "qdsp6_base", "halt_base", "rmb_base",
- "restart_reg", "metadata_base", "cxrail_bhs_reg";
+ "restart_reg", "cxrail_bhs_reg";
interrupts = <0 24 1>;
vdd_mss-supply = <&pm8226_s1>;
@@ -623,6 +659,12 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
+
+ /* GPIO input from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
qcom,msm-mem-hole {
@@ -691,9 +733,9 @@
qcom,msm-rng-iface-clk;
};
- qcom,tz-log@fc5b82c {
+ qcom,tz-log@fe805720 {
compatible = "qcom,tz-log";
- reg = <0x0fc5b82c 0x1000>;
+ reg = <0x0fe805720 0x1000>;
};
jtag_mm0: jtagmm@fc33c000 {
@@ -723,6 +765,12 @@
<0xfc336000 0x1000>;
reg-names = "etm-base","debug-base";
};
+
+ qcom,ipc-spinlock@fd484000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0xfd484000 0x400>;
+ qcom,num-locks = <8>;
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
new file mode 100644
index 0000000..390c02a
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+ qcom,msm-id = <147 1 0>;
+
+ serial@f991f000 {
+ status = "ok";
+ };
+};
+
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 298cb68..3612078 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -15,7 +15,7 @@
compatible = "arm,coresight-tmc";
reg = <0xfc326000 0x1000>,
<0xfc37c000 0x3000>;
- reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+ reg-names = "tmc-base", "bam-base";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
@@ -23,6 +23,7 @@
coresight-id = <0>;
coresight-name = "coresight-tmc-etr";
coresight-nr-inports = <1>;
+ coresight-ctis = <&cti0 &cti8>;
};
tpiu: tpiu@fc320000 {
@@ -51,7 +52,7 @@
tmc_etf: tmc@fc325000 {
compatible = "arm,coresight-tmc";
reg = <0xfc325000 0x1000>;
- reg-names = "tmc-etf-base";
+ reg-names = "tmc-base";
coresight-id = <3>;
coresight-name = "coresight-tmc-etf";
@@ -60,12 +61,13 @@
coresight-child-list = <&replicator>;
coresight-child-ports = <0>;
coresight-default-sink;
+ coresight-ctis = <&cti0 &cti8>;
};
funnel_merg: funnel@fc323000 {
compatible = "arm,coresight-funnel";
reg = <0xfc323000 0x1000>;
- reg-names = "funnel-merg-base";
+ reg-names = "funnel-base";
coresight-id = <4>;
coresight-name = "coresight-funnel-merg";
@@ -78,7 +80,7 @@
funnel_in0: funnel@fc321000 {
compatible = "arm,coresight-funnel";
reg = <0xfc321000 0x1000>;
- reg-names = "funnel-in0-base";
+ reg-names = "funnel-base";
coresight-id = <5>;
coresight-name = "coresight-funnel-in0";
@@ -91,7 +93,7 @@
funnel_in1: funnel@fc322000 {
compatible = "arm,coresight-funnel";
reg = <0xfc322000 0x1000>;
- reg-names = "funnel-in1-base";
+ reg-names = "funnel-base";
coresight-id = <6>;
coresight-name = "coresight-funnel-in1";
@@ -104,7 +106,7 @@
funnel_a7ss: funnel@fc355000 {
compatible = "arm,coresight-funnel";
reg = <0xfc355000 0x1000>;
- reg-names = "funnel-a7ss-base";
+ reg-names = "funnel-base";
coresight-id = <7>;
coresight-name = "coresight-funnel-a7ss";
@@ -128,15 +130,209 @@
coresight-child-ports = <7>;
};
+ etm0: etm@fc34c000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc34c000 0x1000>;
+ reg-names = "etm-base";
+
+ coresight-id = <9>;
+ coresight-name = "coresight-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_a7ss>;
+ coresight-child-ports = <0>;
+
+ qcom,pc-save;
+ qcom,round-robin;
+ };
+
+ etm1: etm@fc34d000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc34d000 0x1000>;
+ reg-names = "etm-base";
+
+ coresight-id = <10>;
+ coresight-name = "coresight-etm1";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_a7ss>;
+ coresight-child-ports = <1>;
+
+ qcom,pc-save;
+ qcom,round-robin;
+ };
+
+ etm2: etm@fc34e000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc34e000 0x1000>;
+ reg-names = "etm-base";
+
+ coresight-id = <11>;
+ coresight-name = "coresight-etm2";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_a7ss>;
+ coresight-child-ports = <2>;
+
+ qcom,pc-save;
+ qcom,round-robin;
+ };
+
+ etm3: etm@fc34f000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc34f000 0x1000>;
+ reg-names = "etm-base";
+
+ coresight-id = <12>;
+ coresight-name = "coresight-etm3";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_a7ss>;
+ coresight-child-ports = <3>;
+
+ qcom,pc-save;
+ qcom,round-robin;
+ };
+
csr: csr@fc301000 {
compatible = "qcom,coresight-csr";
reg = <0xfc301000 0x1000>;
reg-names = "csr-base";
- coresight-id = <9>;
+ coresight-id = <13>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
qcom,blk-size = <3>;
};
+
+ cti0: cti@fc310000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc310000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-cti0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti1: cti@fc311000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc311000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-cti1";
+ coresight-nr-inports = <0>;
+ };
+
+ cti2: cti@fc312000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc312000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-cti2";
+ coresight-nr-inports = <0>;
+ };
+
+ cti3: cti@fc313000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc313000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-cti3";
+ coresight-nr-inports = <0>;
+ };
+
+ cti4: cti@fc314000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc314000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <18>;
+ coresight-name = "coresight-cti4";
+ coresight-nr-inports = <0>;
+ };
+
+ cti5: cti@fc315000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc315000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <19>;
+ coresight-name = "coresight-cti5";
+ coresight-nr-inports = <0>;
+ };
+
+ cti6: cti@fc316000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc316000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <20>;
+ coresight-name = "coresight-cti6";
+ coresight-nr-inports = <0>;
+ };
+
+ cti7: cti@fc317000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc317000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <21>;
+ coresight-name = "coresight-cti7";
+ coresight-nr-inports = <0>;
+ };
+
+ cti8: cti@fc318000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc318000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <22>;
+ coresight-name = "coresight-cti8";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_cpu0: cti@fc351000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc351000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <23>;
+ coresight-name = "coresight-cti-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_cpu1: cti@fc352000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc352000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <24>;
+ coresight-name = "coresight-cti-cpu1";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_cpu2: cti@fc353000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc353000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <25>;
+ coresight-name = "coresight-cti-cpu2";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_cpu3: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <26>;
+ coresight-name = "coresight-cti-cpu3";
+ coresight-nr-inports = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
index 52a8c47..0f48517 100644
--- a/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
+++ b/arch/arm/boot/dts/msm8610-iommu-domains.dtsi
@@ -27,7 +27,7 @@
qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
};
- qcom,iommu-domain3 {
+ q6_domain_ns:qcom,iommu-domain3 {
label = "lpass_video";
qcom,iommu-contexts = <&lpass_video_shared>;
qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
new file mode 100644
index 0000000..70ac0e8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+ qcom,msm-id = <147 8 0>;
+
+ serial@f991f000 {
+ status = "ok";
+ };
+};
+
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index d6e143c..ff16b8d 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -306,10 +306,12 @@
qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 56>, /* q6_wdog_expired_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
@@ -317,17 +319,17 @@
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
<0xff 179>, /* o_wcss_apss_asic_intr
-
+ <0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
+ <0xff 161>, /* lpass_irq_out_spare[4] /
+ <0xff 162>, /* lpass_irq_out_spare[5]*/
+ <0xff 234>, /* lpass_irq_out_spare[6]*/
+ <0xff 235>, /* lpass_irq_out_spare[7]*/
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
<0xff 190>, /* lpass_irq_out_apcs(2) */
<0xff 191>, /* lpass_irq_out_apcs(3) */
<0xff 192>, /* lpass_irq_out_apcs(4) */
- <0xff 193>, /* lpass_irq_out_apcs(5) */
<0xff 194>, /* lpass_irq_out_apcs(6) */
- <0xff 195>, /* lpass_irq_out_apcs(7) */
- <0xff 196>, /* lpass_irq_out_apcs(8) */
- <0xff 197>, /* lpass_irq_out_apcs(9) */
<0xff 200>, /* rpm_ipc(4) */
<0xff 201>, /* rpm_ipc(5) */
<0xff 202>, /* rpm_ipc(6) */
@@ -336,47 +338,54 @@
<0xff 205>, /* rpm_ipc(25) */
<0xff 206>, /* rpm_ipc(26) */
<0xff 207>, /* rpm_ipc(27) */
+ <0xff 258>, /* rpm_ipc(28) */
+ <0xff 259>, /* rpm_ipc(29) */
+ <0xff 275>, /* rpm_ipc(30) */
+ <0xff 276>, /* rpm_ipc(31) */
+ <0xff 269>, /* rpm_wdog_expired_irq */
<0xff 240>; /* summary_irq_kpss */
qcom,gpio-parent = <&msmgpio>;
- qcom,gpio-map = <3 102>,
- <4 1 >,
+ qcom,gpio-map = <3 1>,
+ <4 4 >,
<5 5 >,
<6 9 >,
- <7 18>,
- <8 20>,
- <9 24>,
+ <7 13>,
+ <8 17>,
+ <9 21>,
<10 27>,
- <11 28>,
- <12 34>,
- <13 35>,
- <14 37>,
- <15 42>,
- <16 44>,
- <17 46>,
- <18 50>,
- <19 54>,
- <20 59>,
- <21 61>,
- <22 62>,
- <23 64>,
- <24 65>,
- <25 66>,
- <26 67>,
- <27 68>,
- <28 71>,
- <29 72>,
- <30 73>,
- <31 74>,
- <32 75>,
- <33 77>,
- <34 79>,
- <35 80>,
- <36 82>,
- <37 86>,
- <38 92>,
- <39 93>,
- <40 95>;
+ <11 29>,
+ <12 31>,
+ <13 33>,
+ <14 35>,
+ <15 37>,
+ <16 38>,
+ <17 39>,
+ <18 41>,
+ <19 46>,
+ <20 48>,
+ <21 49>,
+ <22 50>,
+ <23 51>,
+ <24 52>,
+ <25 54>,
+ <26 62>,
+ <27 63>,
+ <28 64>,
+ <29 65>,
+ <30 66>,
+ <31 67>,
+ <32 68>,
+ <33 69>,
+ <34 71>,
+ <35 72>,
+ <36 106>,
+ <37 107>,
+ <38 108>,
+ <39 109>,
+ <40 110>,
+ <54 111>,
+ <55 113>;
};
qcom,pm-8x60@fe805664 {
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 362d126..f11f04b 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -12,216 +12,215 @@
/* Stub Regulators */
- / {
- pm8110_s1: regulator-s1 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_s1";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
-
+/ {
pm8110_s1_corner: regulator-s1-corner {
compatible = "qcom,stub-regulator";
regulator-name = "8110_s1_corner";
+ qcom,hpm-min-load = <100000>;
regulator-min-microvolt = <1>;
regulator-max-microvolt = <7>;
qcom,consumer-supplies = "vdd_dig", "";
};
+};
- pm8110_s2: regulator-s2 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_s2";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- };
+/* QPNP controlled regulators: */
- pm8110_s3: regulator-s3 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_s3";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1350000>;
- regulator-max-microvolt = <1350000>;
- };
+&spmi_bus {
- pm8110_s4: regulator-s4 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_s4";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <2150000>;
- regulator-max-microvolt = <2150000>;
- };
+ qcom,pm8110@1 {
- pm8110_l1: regulator-l1 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l1";
- parent-supply = <&pm8110_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- };
+ pm8110_s1: regulator@1400 {
+ status = "okay";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ };
- pm8110_l2: regulator-l2 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l2";
- parent-supply = <&pm8110_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
+ pm8110_s2: regulator@1700 {
+ status = "okay";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ };
- pm8110_l3: regulator-l3 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l3";
- parent-supply = <&pm8110_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- };
+ pm8110_s3: regulator@1a00 {
+ status = "okay";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ };
- pm8110_l4: regulator-l4 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l4";
- parent-supply = <&pm8110_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
+ pm8110_s4: regulator@1d00 {
+ status = "okay";
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ qcom,enable-time = <500>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ };
- pm8110_l5: regulator-l5 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l5";
- parent-supply = <&pm8110_s3>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- };
+ pm8110_l1: regulator@4000 {
+ status = "okay";
+ parent-supply = <&pm8110_s3>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l6: regulator-l6 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l6";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8110_l2: regulator@4100 {
+ status = "okay";
+ parent-supply = <&pm8110_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,enable-time = <200>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ };
- pm8110_l7: regulator-l7 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l7";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- };
+ pm8110_l3: regulator@4200 {
+ status = "okay";
+ parent-supply = <&pm8110_s3>;
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,enable-time = <200>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ };
- pm8110_l8: regulator-l8 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l8";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8110_l4: regulator@4300 {
+ status = "okay";
+ parent-supply = <&pm8110_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l9: regulator-l9 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l9";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- };
+ pm8110_l5: regulator@4400 {
+ status = "okay";
+ parent-supply = <&pm8110_s3>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l10: regulator-l10 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l10";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,consumer-supplies = "vdd_sr2_pll", "";
- };
+ pm8110_l6: regulator@4500 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ };
- pm8110_l12: regulator-l12 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l12";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- };
+ pm8110_l7: regulator@4600 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l14: regulator-l14 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l14";
- parent-supply = <&pm8110_s4>;
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
+ pm8110_l8: regulator@4700 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l15: regulator-l15 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l15";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- };
+ pm8110_l9: regulator@4800 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l16: regulator-l16 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l16";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- };
+ pm8110_l10: regulator@4900 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,consumer-supplies = "vdd_sr2_pll", "";
+ };
- pm8110_l17: regulator-l17 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l17";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- };
+ pm8110_l12: regulator@4b00 {
+ status = "okay";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l18: regulator-l18 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l18";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8110_l14: regulator@4d00 {
+ status = "okay";
+ parent-supply = <&pm8110_s4>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l19: regulator-l19 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l19";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- };
+ pm8110_l15: regulator@4e00 {
+ status = "okay";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l20: regulator-l20 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l20";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- };
+ pm8110_l16: regulator@4f00 {
+ status = "okay";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l21: regulator-l21 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l21";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- };
+ pm8110_l17: regulator@5000 {
+ status = "okay";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ qcom,enable-time = <200>;
+ };
- pm8110_l22: regulator-l22 {
- compatible = "qcom,stub-regulator";
- regulator-name = "8110_l22";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
+ pm8110_l18: regulator@5100 {
+ status = "okay";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ };
+
+ pm8110_l19: regulator@5200 {
+ status = "okay";
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,enable-time = <200>;
+ };
+
+ pm8110_l20: regulator@5300 {
+ status = "okay";
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,enable-time = <200>;
+ };
+
+ pm8110_l21: regulator@5400 {
+ status = "okay";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ };
+
+ pm8110_l22: regulator@5500 {
+ status = "okay";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,enable-time = <200>;
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index b78c3af..d945619 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -71,7 +71,12 @@
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
- hfi = "q6";
+ qcom,vidc-ns-map = <0x40000000 0x40000000>;
+ qcom,iommu-groups = <&q6_domain_ns>;
+ qcom,iommu-group-buffer-types = <0xfff>;
+ qcom,buffer-type-tz-usage-map = <0x1 0x1>,
+ <0x1fe 0x2>;
+ qcom,hfi = "q6";
};
usb@f9a55000 {
@@ -236,6 +241,7 @@
compatible = "qcom,rpm-smd";
rpm-channel-name = "rpm_requests";
rpm-channel-type = <15>; /* SMD_APPS_RPM */
+ rpm-standalone;
};
qcom,msm-mem-hole {
@@ -428,11 +434,33 @@
compatible = "qcom,msm-pcm-hostless";
};
+ qcom,mss@fc880000 {
+ compatible = "qcom,pil-q6v5-mss";
+ reg = <0xfc880000 0x100>,
+ <0xfd485000 0x400>,
+ <0xfc820000 0x020>,
+ <0xfc401680 0x004>,
+ <0xfd485194 0x4>;
+ reg-names = "qdsp6_base", "halt_base", "rmb_base",
+ "restart_reg", "cxrail_bhs_reg";
+
+ interrupts = <0 24 1>;
+ vdd_mss-supply = <&pm8110_s1>;
+ vdd_cx-supply = <&pm8110_s1_corner>;
+ vdd_mx-supply = <&pm8110_l3>;
+ vdd_pll-supply = <&pm8110_l10>;
+ qcom,vdd_pll = <1800000>;
+ qcom,is-loadable;
+ qcom,firmware-name = "mba";
+ qcom,pil-self-auth;
+ };
+
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
- <0xfd485100 0x00010>;
- reg-names = "qdsp6_base", "halt_base";
+ <0xfd485100 0x00010>,
+ <0xfc4016c0 0x00004>;
+ reg-names = "qdsp6_base", "halt_base", "restart_reg";
interrupts = <0 162 1>;
vdd_cx-supply = <&pm8110_s1_corner>;
qcom,firmware-name = "adsp";
@@ -487,8 +515,8 @@
/include/ "msm8610-iommu-domains.dtsi"
-/include/ "msm8610-regulator.dtsi"
/include/ "msm-pm8110.dtsi"
+/include/ "msm8610-regulator.dtsi"
&pm8110_vadc {
chan@0 {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index 8f58c3e..828e7ae 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -1166,8 +1166,8 @@
qcom,qport = <0>;
qcom,ws = <10000>;
qcom,mas-hw-id = <0>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
};
mas-ampss-m1 {
@@ -1180,8 +1180,8 @@
qcom,qport = <1>;
qcom,ws = <10000>;
qcom,mas-hw-id = <0>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
};
mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
index 24438f0..3fb5b20 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
@@ -15,7 +15,7 @@
actuator0: qcom,actuator@18 {
cell-index = <0>;
- reg = <0x18 0x0>;
+ reg = <0x18>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
};
@@ -27,6 +27,7 @@
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "s5k3l1yx";
cam_vdig-supply = <&pm8941_l3>;
@@ -61,6 +62,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0 0x1210>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "imx135";
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs3>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c>;
@@ -98,7 +137,7 @@
qcom,camera@90 {
compatible = "qcom,mt9m114";
- reg = <0x90 0x0>;
+ reg = <0x90>;
qcom,slave-id = <0x90 0x0 0x2481>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 95cafdb..0bd303f 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -54,7 +54,8 @@
reg-names = "csid";
interrupts = <0 51 0>;
interrupt-names = "csid";
- mipi_csi_vdd-supply = <&pm8941_l12>;
+ qcom,csi-vdd-voltage = <1800000>;
+ qcom,mipi-csi-vdd-supply = <&pm8941_l12>;
};
qcom,csid@fda08400 {
@@ -64,7 +65,8 @@
reg-names = "csid";
interrupts = <0 52 0>;
interrupt-names = "csid";
- mipi_csi_vdd-supply = <&pm8941_l12>;
+ qcom,csi-vdd-voltage = <1800000>;
+ qcom,mipi-csi-vdd-supply = <&pm8941_l12>;
};
qcom,csid@fda08800 {
@@ -74,7 +76,8 @@
reg-names = "csid";
interrupts = <0 53 0>;
interrupt-names = "csid";
- mipi_csi_vdd-supply = <&pm8941_l12>;
+ qcom,csi-vdd-voltage = <1800000>;
+ qcom,mipi-csi-vdd-supply = <&pm8941_l12>;
};
qcom,csid@fda08C00 {
@@ -84,7 +87,8 @@
reg-names = "csid";
interrupts = <0 54 0>;
interrupt-names = "csid";
- mipi_csi_vdd-supply = <&pm8941_l12>;
+ qcom,csi-vdd-voltage = <1800000>;
+ qcom,mipi-csi-vdd-supply = <&pm8941_l12>;
};
qcom,ispif@fda0A000 {
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 2c513e8..adab873 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -194,6 +194,7 @@
sound {
qcom,model = "msm8974-taiko-cdp-snd-card";
qcom,hdmi-audio-rx;
+ qcom,us-euro-gpios = <&pm8941_gpios 20 0>;
};
usb2_otg_sw: regulator-tpd4s214 {
@@ -205,19 +206,34 @@
enable-active-high;
};
- hsic@f9a00000 {
- compatible = "qcom,hsic-host";
- reg = <0xf9a00000 0x400>;
- interrupts = <0 136 0>, <0 148 0>;
- interrupt-names = "core_irq", "async_irq";
- HSIC_VDDCX-supply = <&pm8841_s2>;
- HSIC_GDSC-supply = <&gdsc_usb_hsic>;
- hsic,strobe-gpio = <&msmgpio 144 0x00>;
- hsic,data-gpio = <&msmgpio 145 0x00>;
- hsic,resume-gpio = <&msmgpio 80 0x00>;
- hsic,ignore-cal-pad-config;
- hsic,strobe-pad-offset = <0x2050>;
- hsic,data-pad-offset = <0x2054>;
+ hsic_host: hsic@f9a00000 {
+ compatible = "qcom,hsic-host";
+ reg = <0xf9a00000 0x400>;
+ #address-cells = <0>;
+ interrupt-parent = <&hsic_host>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 136 0
+ 1 &intc 0 148 0
+ 2 &msmgpio 144 0x8>;
+ interrupt-names = "core_irq", "async_irq", "wakeup";
+ HSIC_VDDCX-supply = <&pm8841_s2>;
+ HSIC_GDSC-supply = <&gdsc_usb_hsic>;
+ hsic,strobe-gpio = <&msmgpio 144 0x00>;
+ hsic,data-gpio = <&msmgpio 145 0x00>;
+ hsic,resume-gpio = <&msmgpio 80 0x00>;
+ hsic,ignore-cal-pad-config;
+ hsic,strobe-pad-offset = <0x2050>;
+ hsic,data-pad-offset = <0x2054>;
+
+ qcom,msm-bus,name = "hsic";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <85 512 0 0>,
+ <85 512 40000 160000>;
};
};
@@ -300,6 +316,8 @@
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -333,8 +351,6 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -484,6 +500,14 @@
};
gpio@d300 { /* GPIO 20 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
+ qcom,invert = <0>; /* Output low initially */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@d400 { /* GPIO 21 */
@@ -541,6 +565,7 @@
&pm8941_mpps {
mpp@a000 { /* MPP 1 */
+ status = "disabled";
};
mpp@a100 { /* MPP 2 */
@@ -592,6 +617,55 @@
};
};
+/* CoreSight */
+&tpiu {
+ qcom,seta-gpios = <&msmgpio 31 0>,
+ <&msmgpio 32 0>,
+ <&msmgpio 33 0>,
+ <&msmgpio 34 0>,
+ <&msmgpio 35 0>,
+ <&msmgpio 36 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 38 0>,
+ <&msmgpio 39 0>,
+ <&msmgpio 40 0>,
+ <&msmgpio 41 0>,
+ <&msmgpio 42 0>,
+ <&msmgpio 43 0>,
+ <&msmgpio 44 0>,
+ <&msmgpio 45 0>,
+ <&msmgpio 46 0>,
+ <&msmgpio 47 0>,
+ <&msmgpio 48 0>;
+ qcom,seta-gpios-func = <4 4 4 3 4 4 4 3 4 3 5 5 5 5 4 4 5 5>;
+ qcom,seta-gpios-drv = <7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7>;
+ qcom,seta-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
+ qcom,seta-gpios-dir = <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
+
+ qcom,setb-gpios = <&msmgpio 15 0>,
+ <&msmgpio 16 0>,
+ <&msmgpio 17 0>,
+ <&msmgpio 18 0>,
+ <&msmgpio 19 0>,
+ <&msmgpio 20 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 22 0>,
+ <&msmgpio 23 0>,
+ <&msmgpio 24 0>,
+ <&msmgpio 25 0>,
+ <&msmgpio 26 0>,
+ <&msmgpio 27 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 89 0>,
+ <&msmgpio 90 0>,
+ <&msmgpio 91 0>,
+ <&msmgpio 92 0>;
+ qcom,setb-gpios-func = <2 2 2 2 5 5 5 5 6 6 6 7 7 5 2 3 3 3>;
+ qcom,setb-gpios-drv = <7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7>;
+ qcom,setb-gpios-pull = <0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0>;
+ qcom,setb-gpios-dir = <2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2>;
+};
+
&slim_msm {
taiko_codec {
qcom,cdc-micbias1-ext-cap;
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index 5df8f10..c064b59 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -15,7 +15,7 @@
compatible = "arm,coresight-tmc";
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
- reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+ reg-names = "tmc-base", "bam-base";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
@@ -34,6 +34,11 @@
coresight-id = <1>;
coresight-name = "coresight-tpiu";
coresight-nr-inports = <1>;
+
+ vdd-supply = <&pm8941_l21>;
+
+ qcom,vdd-voltage-level = <2950000 2950000>;
+ qcom,vdd-current-level = <9000 800000>;
};
replicator: replicator@fc31c000 {
@@ -52,7 +57,7 @@
tmc_etf: tmc@fc307000 {
compatible = "arm,coresight-tmc";
reg = <0xfc307000 0x1000>;
- reg-names = "tmc-etf-base";
+ reg-names = "tmc-base";
coresight-id = <3>;
coresight-name = "coresight-tmc-etf";
@@ -67,7 +72,7 @@
funnel_merg: funnel@fc31b000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31b000 0x1000>;
- reg-names = "funnel-merg-base";
+ reg-names = "funnel-base";
coresight-id = <4>;
coresight-name = "coresight-funnel-merg";
@@ -80,7 +85,7 @@
funnel_in0: funnel@fc319000 {
compatible = "arm,coresight-funnel";
reg = <0xfc319000 0x1000>;
- reg-names = "funnel-in0-base";
+ reg-names = "funnel-base";
coresight-id = <5>;
coresight-name = "coresight-funnel-in0";
@@ -93,7 +98,7 @@
funnel_in1: funnel@fc31a000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31a000 0x1000>;
- reg-names = "funnel-in1-base";
+ reg-names = "funnel-base";
coresight-id = <6>;
coresight-name = "coresight-funnel-in1";
@@ -106,7 +111,7 @@
funnel_kpss: funnel@fc345000 {
compatible = "arm,coresight-funnel";
reg = <0xfc345000 0x1000>;
- reg-names = "funnel-kpss-base";
+ reg-names = "funnel-base";
coresight-id = <7>;
coresight-name = "coresight-funnel-kpss";
@@ -119,7 +124,7 @@
funnel_mmss: funnel@fc364000 {
compatible = "arm,coresight-funnel";
reg = <0xfc364000 0x1000>;
- reg-names = "funnel-mmss-base";
+ reg-names = "funnel-base";
coresight-id = <8>;
@@ -147,7 +152,7 @@
etm0: etm@fc33c000 {
compatible = "arm,coresight-etm";
reg = <0xfc33c000 0x1000>;
- reg-names = "etm0-base";
+ reg-names = "etm-base";
coresight-id = <10>;
coresight-name = "coresight-etm0";
@@ -163,7 +168,7 @@
etm1: etm@fc33d000 {
compatible = "arm,coresight-etm";
reg = <0xfc33d000 0x1000>;
- reg-names = "etm1-base";
+ reg-names = "etm-base";
coresight-id = <11>;
coresight-name = "coresight-etm1";
@@ -179,7 +184,7 @@
etm2: etm@fc33e000 {
compatible = "arm,coresight-etm";
reg = <0xfc33e000 0x1000>;
- reg-names = "etm2-base";
+ reg-names = "etm-base";
coresight-id = <12>;
coresight-name = "coresight-etm2";
@@ -195,7 +200,7 @@
etm3: etm@fc33f000 {
compatible = "arm,coresight-etm";
reg = <0xfc33f000 0x1000>;
- reg-names = "etm3-base";
+ reg-names = "etm-base";
coresight-id = <13>;
coresight-name = "coresight-etm3";
@@ -223,7 +228,7 @@
cti0: cti@fc308000 {
compatible = "arm,coresight-cti";
reg = <0xfc308000 0x1000>;
- reg-names = "cti0-base";
+ reg-names = "cti-base";
coresight-id = <15>;
coresight-name = "coresight-cti0";
@@ -233,7 +238,7 @@
cti1: cti@fc309000 {
compatible = "arm,coresight-cti";
reg = <0xfc309000 0x1000>;
- reg-names = "cti1-base";
+ reg-names = "cti-base";
coresight-id = <16>;
coresight-name = "coresight-cti1";
@@ -243,7 +248,7 @@
cti2: cti@fc30a000 {
compatible = "arm,coresight-cti";
reg = <0xfc30a000 0x1000>;
- reg-names = "cti2-base";
+ reg-names = "cti-base";
coresight-id = <17>;
coresight-name = "coresight-cti2";
@@ -253,7 +258,7 @@
cti3: cti@fc30b000 {
compatible = "arm,coresight-cti";
reg = <0xfc30b000 0x1000>;
- reg-names = "cti3-base";
+ reg-names = "cti-base";
coresight-id = <18>;
coresight-name = "coresight-cti3";
@@ -263,7 +268,7 @@
cti4: cti@fc30c000 {
compatible = "arm,coresight-cti";
reg = <0xfc30c000 0x1000>;
- reg-names = "cti4-base";
+ reg-names = "cti-base";
coresight-id = <19>;
coresight-name = "coresight-cti4";
@@ -273,7 +278,7 @@
cti5: cti@fc30d000 {
compatible = "arm,coresight-cti";
reg = <0xfc30d000 0x1000>;
- reg-names = "cti5-base";
+ reg-names = "cti-base";
coresight-id = <20>;
coresight-name = "coresight-cti5";
@@ -283,7 +288,7 @@
cti6: cti@fc30e000 {
compatible = "arm,coresight-cti";
reg = <0xfc30e000 0x1000>;
- reg-names = "cti6-base";
+ reg-names = "cti-base";
coresight-id = <21>;
coresight-name = "coresight-cti6";
@@ -293,7 +298,7 @@
cti7: cti@fc30f000 {
compatible = "arm,coresight-cti";
reg = <0xfc30f000 0x1000>;
- reg-names = "cti7-base";
+ reg-names = "cti-base";
coresight-id = <22>;
coresight-name = "coresight-cti7";
@@ -303,7 +308,7 @@
cti8: cti@fc310000 {
compatible = "arm,coresight-cti";
reg = <0xfc310000 0x1000>;
- reg-names = "cti8-base";
+ reg-names = "cti-base";
coresight-id = <23>;
coresight-name = "coresight-cti8";
@@ -313,7 +318,7 @@
cti_l2: cti@fc340000 {
compatible = "arm,coresight-cti";
reg = <0xfc340000 0x1000>;
- reg-names = "cti-l2-base";
+ reg-names = "cti-base";
coresight-id = <24>;
coresight-name = "coresight-cti-l2";
@@ -323,7 +328,7 @@
cti_cpu0: cti@fc341000 {
compatible = "arm,coresight-cti";
reg = <0xfc341000 0x1000>;
- reg-names = "cti-cpu0-base";
+ reg-names = "cti-base";
coresight-id = <25>;
coresight-name = "coresight-cti-cpu0";
@@ -333,7 +338,7 @@
cti_cpu1: cti@fc342000 {
compatible = "arm,coresight-cti";
reg = <0xfc342000 0x1000>;
- reg-names = "cti-cpu1-base";
+ reg-names = "cti-base";
coresight-id = <26>;
coresight-name = "coresight-cti-cpu1";
@@ -343,7 +348,7 @@
cti_cpu2: cti@fc343000 {
compatible = "arm,coresight-cti";
reg = <0xfc343000 0x1000>;
- reg-names = "cti-cpu2-base";
+ reg-names = "cti-base";
coresight-id = <27>;
coresight-name = "coresight-cti-cpu2";
@@ -353,7 +358,7 @@
cti_cpu3: cti@fc344000 {
compatible = "arm,coresight-cti";
reg = <0xfc344000 0x1000>;
- reg-names = "cti-cpu3-base";
+ reg-names = "cti-base";
coresight-id = <28>;
coresight-name = "coresight-cti-cpu3";
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index b18bf88..e70d5d8 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -296,6 +296,8 @@
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -329,8 +331,6 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -536,6 +536,7 @@
&pm8941_mpps {
mpp@a000 { /* MPP 1 */
+ status = "disabled";
};
mpp@a100 { /* MPP 2 */
diff --git a/arch/arm/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index b1f39d1..31afd9c 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -20,6 +20,10 @@
reg = <30>;
};
+ qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+ reg = <21>;
+ };
+
qcom,ion-heap@8 { /* CP_MM HEAP */
compatible = "qcom,msm-ion-reserve";
reg = <8>;
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index a35b9d2..8a8a8b7 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -299,6 +299,15 @@
qca,bt-reset-gpio = <&pm8941_gpios 34 0>;
};
+ bt_ar3002_sleep {
+ compatible = "qca,ar3002_bluesleep";
+ host-wake-gpio = <&msmgpio 79 0>;
+ ext-wake-gpio = <&msmgpio 51 0>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <79 2>;
+ interrupt-names = "host_wake";
+ };
+
sound {
qcom,model = "msm8974-taiko-liquid-snd-card";
@@ -606,6 +615,7 @@
&pm8941_mpps {
mpp@a000 { /* MPP 1 */
+ status = "disabled";
};
mpp@a100 { /* MPP 2 */
@@ -758,6 +768,8 @@
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -780,8 +792,6 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 2f9adbb..0912a33 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -19,6 +19,7 @@
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ qcom,max-clk-rate = <320000000>;
qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
0x00001A00>;
qcom,mdss-pipe-rgb-off = <0x00001E00 0x00002200
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 4f0469c..d61de02 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -267,6 +267,8 @@
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
+ qcom,vdd-always-on;
+ qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <800 500000>;
@@ -300,8 +302,6 @@
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <9000 800000>;
- qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 2950000>;
qcom,vdd-io-current-level = <6 22000>;
@@ -508,6 +508,7 @@
&pm8941_mpps {
mpp@a000 { /* MPP 1 */
+ status = "disabled";
};
mpp@a100 { /* MPP 2 */
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 5eff79c..05451671 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -93,6 +93,15 @@
qcom,use-voltage-corner;
compatible = "qcom,rpm-regulator-smd";
};
+ pm8841_s2_floor_corner: regulator-s2-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8841_s2_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
};
rpm-regulator-smpb3 {
@@ -121,6 +130,15 @@
regulator-max-microvolt = <7>;
qcom,init-voltage-corner = <3>; /* SVS SOC */
};
+ pm8841_s4_floor_corner: regulator-s4-floor-corner {
+ compatible = "qcom,rpm-regulator-smd";
+ regulator-name = "8841_s4_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
};
rpm-regulator-smpa1 {
@@ -502,4 +520,15 @@
gpio = <&pm8941_mpps 5 0>;
enable-active-high;
};
+
+ /*
+ * vph_pwr_vreg represents the unregulated battery voltage supply
+ * VPH_PWR that is present whenever the device is powered on.
+ */
+ vph_pwr_vreg: vph_pwr_vreg {
+ compatible = "regulator-fixed";
+ status = "disabled";
+ regulator-name = "vph_pwr";
+ regulator-always-on;
+ };
};
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
index 511f91f..1b08246 100644
--- a/arch/arm/boot/dts/msm8974-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -12,8 +12,7 @@
/ {
qcom,smp2p-modem {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <1>;
qcom,irq-bitmask = <0x4000>;
interrupts = <0 27 1>;
@@ -21,8 +20,7 @@
qcom,smp2p-adsp {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <2>;
qcom,irq-bitmask = <0x400>;
interrupts = <0 158 1>;
@@ -30,8 +28,7 @@
qcom,smp2p-wcnss {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <4>;
qcom,irq-bitmask = <0x40000>;
interrupts = <0 143 1>;
@@ -103,6 +100,29 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
+ /* SMP2P SSR Driver for inbound entry from modem. */
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* SMP2P SSR Driver for outbound entry to modem */
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
/* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index 319debe..e591dee 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -32,4 +32,6 @@
2 &intc 0 133 0
3 &spmi_bus 0x0 0x0 0x9 0x0>;
interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+ qcom,misc-ref = <&pm8941_misc>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index 5759b56..4efad9e 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -20,3 +20,18 @@
compatible = "qcom,msm8974-fluid", "qcom,msm8974";
qcom,msm-id = <126 3 0x20000>;
};
+
+&usb3 {
+ #address-cells = <0>;
+ interrupt-parent = <&usb3>;
+ interrupts = <0 1 2 3>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 131 0
+ 1 &intc 0 179 0
+ 2 &intc 0 133 0
+ 3 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+ qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 6812f60..86584f8 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -20,3 +20,18 @@
compatible = "qcom,msm8974-liquid", "qcom,msm8974";
qcom,msm-id = <126 9 0x20000>;
};
+
+&usb3 {
+ #address-cells = <0>;
+ interrupt-parent = <&usb3>;
+ interrupts = <0 1 2 3>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 131 0
+ 1 &intc 0 179 0
+ 2 &intc 0 133 0
+ 3 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+ qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index b29d4ca..a2e2ffa 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -20,3 +20,18 @@
compatible = "qcom,msm8974-mtp", "qcom,msm8974";
qcom,msm-id = <126 8 0x20000>;
};
+
+&usb3 {
+ #address-cells = <0>;
+ interrupt-parent = <&usb3>;
+ interrupts = <0 1 2 3>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 131 0
+ 1 &intc 0 179 0
+ 2 &intc 0 133 0
+ 3 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+
+ qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 2cfb192..24b68b5 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -28,11 +28,12 @@
qcom,saw2-spm-dly= <0x3C102800>;
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
- qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
- 30 06 26 30 0F];
- qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+ 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
};
qcom,spm@f9099000 {
@@ -50,11 +51,12 @@
qcom,saw2-spm-dly= <0x3C102800>;
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
- qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
- 30 06 26 30 0F];
- qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+ 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
};
qcom,spm@f90a9000 {
@@ -72,11 +74,12 @@
qcom,saw2-spm-dly= <0x3C102800>;
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
- qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
- 30 06 26 30 0F];
- qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+ 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
};
qcom,spm@f90b9000 {
@@ -94,11 +97,12 @@
qcom,saw2-spm-dly= <0x3C102800>;
qcom,saw2-spm-ctl = <0x1>;
qcom,saw2-spm-cmd-wfi = [03 0b 0f];
- qcom,saw2-spm-cmd-ret = [42 1b 00 d0 03 d4 5b 0b 00 42 1b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 80 10 E0 03 3B E4 5B 82 10 0B
- 30 06 26 30 0F];
- qcom,saw2-spm-cmd-pc = [00 20 50 80 60 70 10 E0 07 6E 70 3B
- E4 5B 82 3F 50 10 0B 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d0 c0 a0 90 03 d0 98 a2 c0
+ 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 90 a0 b0 03 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 90 a0 b0 07 3b 98 a2 b0 82
+ 10 0b 30 06 26 30 0f];
};
qcom,spm@f9012000 {
@@ -122,10 +126,9 @@
qcom,phase-port = <0x1>;
qcom,pfm-port = <0x2>;
qcom,saw2-spm-cmd-ret = [1f 00 20 03 22 00 0f];
- qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 42 07 78 80 44 22 50
- 3b 60 02 32 50 0f];
- qcom,saw2-spm-cmd-pc = [00 10 32 60 70 80 b0 11 42 07 01 b0 78
- 80 12 44 50 3b 60 02 32 50 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 42 07 44 22 50 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+ 50 02 32 50 0f];
};
qcom,lpm-resources {
@@ -423,7 +426,6 @@
reg = <0xfe805664 0x40>;
qcom,pc-mode = "tz_l2_int";
qcom,use-sync-timer;
- qcom,saw-turns-off-pll;
qcom,cpu-sleep-status@f9088008{
compatible = "qcom,cpu-sleep-status";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index aa3742f..7557657 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -98,6 +98,11 @@
qcom,has-ocmem;
};
+ qcom,vidc {
+ compatible = "qcom,msm-vidc";
+ qcom,hfi = "q6";
+ };
+
qcom,wfd {
compatible = "qcom,msm-wfd";
};
@@ -351,6 +356,7 @@
reg-names = "hc_mem", "core_mem";
interrupts = <0 123 0>, <0 138 0>;
interrupt-names = "hc_irq", "pwr_irq";
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
qcom,cpu-dma-latency-us = <200>;
@@ -377,6 +383,7 @@
interrupts = <0 125 0>, <0 221 0>;
interrupt-names = "hc_irq", "pwr_irq";
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;
qcom,bus-width = <4>;
qcom,cpu-dma-latency-us = <200>;
@@ -410,6 +417,7 @@
<&msmgpio 35 0>; /* DATA3 */
qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
qcom,bus-width = <4>;
qcom,cpu-dma-latency-us = <200>;
@@ -443,6 +451,7 @@
<&msmgpio 92 0>; /* DATA3 */
qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
qcom,bus-width = <4>;
qcom,cpu-dma-latency-us = <200>;
@@ -741,8 +750,9 @@
qcom,lpass@fe200000 {
compatible = "qcom,pil-q6v5-lpass";
reg = <0xfe200000 0x00100>,
- <0xfd485100 0x00010>;
- reg-names = "qdsp6_base", "halt_base";
+ <0xfd485100 0x00010>,
+ <0xfc4016c0 0x00004>;
+ reg-names = "qdsp6_base", "halt_base", "restart_reg";
vdd_cx-supply = <&pm8841_s2_corner>;
interrupts = <0 162 1>;
@@ -979,10 +989,9 @@
reg = <0xfc880000 0x100>,
<0xfd485000 0x400>,
<0xfc820000 0x020>,
- <0xfc401680 0x004>,
- <0x0d1fc000 0x4000>;
+ <0xfc401680 0x004>;
reg-names = "qdsp6_base", "halt_base", "rmb_base",
- "restart_reg", "metadata_base";
+ "restart_reg";
interrupts = <0 24 1>;
vdd_mss-supply = <&pm8841_s3>;
@@ -993,6 +1002,12 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
+
+ /* GPIO input from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
qcom,pronto@fb21b000 {
@@ -1102,9 +1117,9 @@
qcom,ipi-ping;
};
- qcom,tz-log@fc03000 {
+ qcom,tz-log@fe805720 {
compatible = "qcom,tz-log";
- reg = <0x0fc03000 0x1000>;
+ reg = <0xfe805720 0x1000>;
};
qcom,venus@fdce0000 {
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 0af8fa5..69a1d7b 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -15,7 +15,7 @@
compatible = "arm,coresight-tmc";
reg = <0xfc322000 0x1000>,
<0xfc37c000 0x3000>;
- reg-names = "tmc-etr-base", "tmc-etr-bam-base";
+ reg-names = "tmc-base", "bam-base";
qcom,memory-reservation-type = "EBI1";
qcom,memory-reservation-size = <0x20000>; /* 128K EBI1 buffer */
@@ -52,7 +52,7 @@
tmc_etf: tmc@fc307000 {
compatible = "arm,coresight-tmc";
reg = <0xfc307000 0x1000>;
- reg-names = "tmc-etf-base";
+ reg-names = "tmc-base";
coresight-id = <3>;
coresight-name = "coresight-tmc-etf";
@@ -67,7 +67,7 @@
funnel_merg: funnel@fc31b000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31b000 0x1000>;
- reg-names = "funnel-merg-base";
+ reg-names = "funnel-base";
coresight-id = <4>;
coresight-name = "coresight-funnel-merg";
@@ -80,7 +80,7 @@
funnel_in0: funnel@fc319000 {
compatible = "arm,coresight-funnel";
reg = <0xfc319000 0x1000>;
- reg-names = "funnel-in0-base";
+ reg-names = "funnel-base";
coresight-id = <5>;
coresight-name = "coresight-funnel-in0";
@@ -93,7 +93,7 @@
funnel_in1: funnel@fc31a000 {
compatible = "arm,coresight-funnel";
reg = <0xfc31a000 0x1000>;
- reg-names = "funnel-in1-base";
+ reg-names = "funnel-base";
coresight-id = <6>;
coresight-name = "coresight-funnel-in1";
@@ -147,7 +147,7 @@
cti0: cti@fc308000 {
compatible = "arm,coresight-cti";
reg = <0xfc308000 0x1000>;
- reg-names = "cti0-base";
+ reg-names = "cti-base";
coresight-id = <10>;
coresight-name = "coresight-cti0";
@@ -157,7 +157,7 @@
cti1: cti@fc309000 {
compatible = "arm,coresight-cti";
reg = <0xfc309000 0x1000>;
- reg-names = "cti1-base";
+ reg-names = "cti-base";
coresight-id = <11>;
coresight-name = "coresight-cti1";
@@ -167,7 +167,7 @@
cti2: cti@fc30a000 {
compatible = "arm,coresight-cti";
reg = <0xfc30a000 0x1000>;
- reg-names = "cti2-base";
+ reg-names = "cti-base";
coresight-id = <12>;
coresight-name = "coresight-cti2";
@@ -177,7 +177,7 @@
cti3: cti@fc30b000 {
compatible = "arm,coresight-cti";
reg = <0xfc30b000 0x1000>;
- reg-names = "cti3-base";
+ reg-names = "cti-base";
coresight-id = <13>;
coresight-name = "coresight-cti3";
@@ -187,7 +187,7 @@
cti4: cti@fc30c000 {
compatible = "arm,coresight-cti";
reg = <0xfc30c000 0x1000>;
- reg-names = "cti4-base";
+ reg-names = "cti-base";
coresight-id = <14>;
coresight-name = "coresight-cti4";
@@ -197,7 +197,7 @@
cti5: cti@fc30d000 {
compatible = "arm,coresight-cti";
reg = <0xfc30d000 0x1000>;
- reg-names = "cti5-base";
+ reg-names = "cti-base";
coresight-id = <15>;
coresight-name = "coresight-cti5";
@@ -207,7 +207,7 @@
cti6: cti@fc30e000 {
compatible = "arm,coresight-cti";
reg = <0xfc30e000 0x1000>;
- reg-names = "cti6-base";
+ reg-names = "cti-base";
coresight-id = <16>;
coresight-name = "coresight-cti6";
@@ -217,7 +217,7 @@
cti7: cti@fc30f000 {
compatible = "arm,coresight-cti";
reg = <0xfc30f000 0x1000>;
- reg-names = "cti7-base";
+ reg-names = "cti-base";
coresight-id = <17>;
coresight-name = "coresight-cti7";
@@ -227,7 +227,7 @@
cti8: cti@fc310000 {
compatible = "arm,coresight-cti";
reg = <0xfc310000 0x1000>;
- reg-names = "cti8-base";
+ reg-names = "cti-base";
coresight-id = <18>;
coresight-name = "coresight-cti8";
@@ -237,7 +237,7 @@
cti_cpu: cti@fc333000 {
compatible = "arm,coresight-cti";
reg = <0xfc333000 0x1000>;
- reg-names = "cti-cpu-base";
+ reg-names = "cti-base";
coresight-id = <19>;
coresight-name = "coresight-cti-cpu";
diff --git a/arch/arm/boot/dts/msm9625-display.dtsi b/arch/arm/boot/dts/msm9625-display.dtsi
new file mode 100644
index 0000000..a160bae
--- /dev/null
+++ b/arch/arm/boot/dts/msm9625-display.dtsi
@@ -0,0 +1,20 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+ qcom,msm_qpic@f9ac0000 {
+ compatible = "qcom,mdss_qpic";
+ reg = <0xf9ac0000 0x24000>;
+ reg-names = "qpic_base";
+ interrupts = <0 251 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm9625-smp2p.dtsi b/arch/arm/boot/dts/msm9625-smp2p.dtsi
index 425bf00..02c95e4 100644
--- a/arch/arm/boot/dts/msm9625-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm9625-smp2p.dtsi
@@ -12,8 +12,7 @@
/ {
qcom,smp2p-modem {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <1>;
qcom,irq-bitmask = <0x4000>;
interrupts = <0 27 1>;
@@ -21,8 +20,7 @@
qcom,smp2p-adsp {
compatible = "qcom,smp2p";
- reg = <0xfa006000 0x1000>, <0x8 0x0>;
- reg-names = "irq-reg-base", "irq-reg-offset";
+ reg = <0xf9011008 0x4>;
qcom,remote-pid = <2>;
qcom,irq-bitmask = <0x400>;
interrupts = <0 158 1>;
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index 6221ba1..cc7a758 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -45,7 +45,15 @@
compatible = "qca,ar6004-sdio";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index 5ff9e92..d78bb77 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -45,7 +45,15 @@
compatible = "qca,ar6004-sdio";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 09a89ab..94fe019 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -13,6 +13,8 @@
/dts-v1/;
/include/ "msm9625-v2.dtsi"
+/include/ "msm9625-display.dtsi"
+/include/ "qpic-panel-ili-qvga.dtsi"
/ {
model = "Qualcomm MSM 9625V2 CDP";
@@ -45,7 +47,15 @@
compatible = "qca,ar6004-hsic";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 7949080..2840024 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -45,7 +45,15 @@
compatible = "qca,ar6004-hsic";
qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
- qca,ar6004-vdd-io-supply = <&pm8019_l11>;
+ qca,vdd-io-supply = <&pm8019_l11>;
+ };
+
+ qca,wlan_ar6003 {
+ cell-index = <0>;
+ compatible = "qca,ar6003-sdio";
+ qca,chip-pwd-l-gpios = <&msmgpio 62 0>;
+ qca,pm-enable-gpios = <&pm8019_gpios 3 0x0>;
+ qca,vdd-io-supply = <&pm8019_l11>;
};
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 9172029..3dbc95d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -140,31 +140,27 @@
qcom,pipe0 {
label = "hsusb-ipa-out-0";
- qcom,usb-bam-mem-type = <0>;
+ qcom,usb-bam-mem-type = <2>;
qcom,bam-type = <1>;
qcom,dir = <0>;
qcom,pipe-num = <0>;
qcom,peer-bam = <2>;
qcom,src-bam-physical-address = <0xf9a44000>;
qcom,src-bam-pipe-index = <1>;
- qcom,data-fifo-offset = <0x2200>;
- qcom,data-fifo-size = <0x1e00>;
- qcom,descriptor-fifo-offset = <0x2100>;
- qcom,descriptor-fifo-size = <0x100>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
};
qcom,pipe1 {
label = "hsusb-ipa-in-0";
- qcom,usb-bam-mem-type = <0>;
+ qcom,usb-bam-mem-type = <2>;
qcom,bam-type = <1>;
qcom,dir = <1>;
qcom,pipe-num = <0>;
qcom,peer-bam = <2>;
qcom,dst-bam-physical-address = <0xf9a44000>;
qcom,dst-bam-pipe-index = <0>;
- qcom,data-fifo-offset = <0x300>;
- qcom,data-fifo-size = <0x1e00>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x300>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
};
qcom,pipe2 {
label = "hsusb-qdss-in-0";
@@ -193,6 +189,7 @@
qcom,dst-bam-pipe-index = <3>;
qcom,data-fifo-size = <0xD480>;
qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe4 {
label = "hsic-ipa-in-1";
@@ -205,6 +202,7 @@
qcom,dst-bam-pipe-index = <4>;
qcom,data-fifo-size = <0xD480>;
qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe5 {
label = "hsic-ipa-in-2";
@@ -217,6 +215,7 @@
qcom,dst-bam-pipe-index = <5>;
qcom,data-fifo-size = <0xD480>;
qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe6 {
label = "hsic-ipa-in-3";
@@ -229,6 +228,7 @@
qcom,dst-bam-pipe-index = <6>;
qcom,data-fifo-size = <0xD480>;
qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,reset-bam-on-connect;
};
qcom,pipe7 {
label = "hsic-ipa-out-0";
@@ -241,6 +241,7 @@
qcom,src-bam-pipe-index = <7>;
qcom,data-fifo-size = <0xD480>;
qcom,descriptor-fifo-size = <0x1A80>;
+ qcom,reset-bam-on-connect;
};
};
diff --git a/arch/arm/boot/dts/msmzinc-ion.dtsi b/arch/arm/boot/dts/msmzinc-ion.dtsi
new file mode 100644
index 0000000..4bf078a
--- /dev/null
+++ b/arch/arm/boot/dts/msmzinc-ion.dtsi
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ion-heap@30 { /* SYSTEM HEAP */
+ reg = <30>;
+ };
+
+ qcom,ion-heap@25 { /* IOMMU HEAP */
+ reg = <25>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msmzinc.dtsi b/arch/arm/boot/dts/msmzinc.dtsi
index d981909..642597d 100644
--- a/arch/arm/boot/dts/msmzinc.dtsi
+++ b/arch/arm/boot/dts/msmzinc.dtsi
@@ -11,6 +11,7 @@
*/
/include/ "skeleton.dtsi"
+/include/ "msmzinc-ion.dtsi"
/ {
model = "Qualcomm MSM ZINC";
@@ -74,15 +75,12 @@
qcom,msm-imem@fe805000 {
compatible = "qcom,msm-imem";
reg = <0xfe805000 0x1000>; /* Address and size of IMEM */
- };
-
- qcom,ion {
- compatible = "qcom,msm-ion";
- #address-cells = <1>;
- #size-cells = <0>;
-
- qcom,ion-heap@30 { /* SYSTEM HEAP */
- reg = <30>;
- };
};
+
+ qcom,msm-rtb {
+ compatible = "qcom,msm-rtb";
+ qcom,memory-reservation-type = "EBI1";
+ qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
+ };
+
};
diff --git a/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi b/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi
new file mode 100644
index 0000000..a0c906e
--- /dev/null
+++ b/arch/arm/boot/dts/qpic-panel-ili-qvga.dtsi
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+ qcom,mdss_lcdc_ili9341_qvga {
+ compatible = "qcom,mdss-qpic-panel";
+ label = "ili qvga lcdc panel";
+ vdd-supply = <&pm8019_l11>;
+ avdd-supply = <&pm8019_l14>;
+ qcom,cs-gpio = <&msmgpio 21 0>;
+ qcom,te-gpio = <&msmgpio 22 0>;
+ qcom,rst-gpio = <&msmgpio 23 0>;
+ qcom,ad8-gpio = <&msmgpio 20 0>;
+ qcom,mdss-pan-res = <240 320>;
+ qcom,mdss-pan-bpp = <18>;
+ qcom,refresh_rate = <60>;
+ };
+};
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 8a7928b..10414e1 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -9,7 +9,6 @@
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
CONFIG_PROFILING=y
@@ -34,7 +33,6 @@
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_ONCRPCROUTER_DEBUG is not set
-# CONFIG_MSM_HW3D is not set
# CONFIG_QSD_AUDIO is not set
# CONFIG_SURF_FFA_GPIO_KEYPAD is not set
CONFIG_MSM_SMCMOD=m
@@ -156,6 +154,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index db2f25d..aa3befa 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -10,7 +10,6 @@
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_SLAB=y
CONFIG_PROFILING=y
@@ -33,7 +32,6 @@
CONFIG_MSM_ONCRPCROUTER=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-# CONFIG_MSM_HW3D is not set
# CONFIG_QSD_AUDIO is not set
# CONFIG_SURF_FFA_GPIO_KEYPAD is not set
CONFIG_MSM_SMCMOD=m
@@ -155,6 +153,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 8eac20f..aea092e 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -15,7 +15,6 @@
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -45,7 +44,6 @@
CONFIG_MSM_IPC_ROUTER=y
# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM7X27A_AUDIO=y
CONFIG_MSM_DMA_TEST=y
CONFIG_MSM_SLEEP_STATS_DEVICE=y
@@ -67,7 +65,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0xC800000
CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -83,7 +80,6 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -249,7 +245,6 @@
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_DIAG_CHAR=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
@@ -271,9 +266,6 @@
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_OV5647=y
CONFIG_AD5046_ACT=y
@@ -286,6 +278,9 @@
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
CONFIG_ION_MSM=y
@@ -356,6 +351,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 27c10d0..b903a0b 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -15,7 +15,6 @@
CONFIG_BLK_DEV_INITRD=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -45,7 +44,6 @@
CONFIG_MSM_IPC_ROUTER=y
# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM7X27A_AUDIO=y
CONFIG_MSM_DMA_TEST=y
CONFIG_MSM_SLEEP_STATS_DEVICE=y
@@ -69,7 +67,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0xC800000
CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -85,7 +82,6 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -251,7 +247,6 @@
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_DIAG_CHAR=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
@@ -273,9 +268,6 @@
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_OV5647=y
CONFIG_AD5046_ACT=y
@@ -288,6 +280,9 @@
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
CONFIG_ION_MSM=y
@@ -357,6 +352,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
deleted file mode 100644
index e46b835..0000000
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ /dev/null
@@ -1,384 +0,0 @@
-# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOCALVERSION="-perf"
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_ASHMEM=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_MSM=y
-CONFIG_ARCH_MSM7X30=y
-# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_MSM_SMD=y
-CONFIG_MSM_SMD_PKG3=y
-CONFIG_MSM_SDIO_DMUX=y
-CONFIG_MSM_SDIO_CMUX=y
-CONFIG_MSM_SDIO_CTL=y
-CONFIG_MSM_ONCRPCROUTER=y
-CONFIG_MSM_RPC_WATCHDOG=y
-CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
-# CONFIG_QSD_AUDIO is not set
-CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
-CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
-CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
-CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
-CONFIG_MSM_MULTIMEDIA_USE_ION=y
-CONFIG_MSM_RPC_PMIC=y
-CONFIG_MSM_RPC_USB=y
-CONFIG_MSM_RPC_PMAPP=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x1A000000
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_IPV6_MIP6=y
-CONFIG_IPV6_TUNNEL=y
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETFILTER=y
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=y
-CONFIG_NF_CONNTRACK_FTP=y
-CONFIG_NF_CONNTRACK_H323=y
-CONFIG_NF_CONNTRACK_IRC=y
-CONFIG_NF_CONNTRACK_NETBIOS_NS=y
-CONFIG_NF_CONNTRACK_PPTP=y
-CONFIG_NF_CONNTRACK_SANE=y
-CONFIG_NF_CONNTRACK_SIP=y
-CONFIG_NF_CONNTRACK_TFTP=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NETFILTER_TPROXY=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_LOG=y
-CONFIG_NETFILTER_XT_TARGET_MARK=y
-CONFIG_NETFILTER_XT_TARGET_NFLOG=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_MATCH_COMMENT=y
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_HELPER=y
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-CONFIG_NETFILTER_XT_MATCH_LENGTH=y
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
-CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
-CONFIG_NETFILTER_XT_MATCH_SOCKET=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
-CONFIG_NETFILTER_XT_MATCH_STRING=y
-CONFIG_NETFILTER_XT_MATCH_TIME=y
-CONFIG_NETFILTER_XT_MATCH_U32=y
-CONFIG_NF_CONNTRACK_IPV4=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_AH=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_NF_NAT=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_MANGLE=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_HTB=y
-CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_SFQ=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NET_CLS_BASIC=y
-CONFIG_NET_CLS_TCINDEX=y
-CONFIG_NET_CLS_FW=y
-CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_FLOW=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_IBS=y
-CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=y
-# CONFIG_CFG80211_WEXT is not set
-CONFIG_RFKILL=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_MTD=y
-CONFIG_MTD_TESTS=m
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=8
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8XXX_UPL=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_LIBRA_SDIOIF=m
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=m
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_MSM=y
-CONFIG_TOUCHSCREEN_TSC2007=y
-CONFIG_TOUCHSCREEN_CY8C_TS=y
-CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_INPUT_GPIO=y
-CONFIG_BOSCH_BMA150=y
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_HS=y
-CONFIG_DIAG_CHAR=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_QUP=y
-CONFIG_I2C_SSBI=y
-CONFIG_SPI=y
-CONFIG_SPI_QSD=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_BATTERY_MSM=y
-CONFIG_SENSORS_MSM_ADC=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_MSM_POPMEM=y
-CONFIG_PMIC8058=y
-CONFIG_MARIMBA_CORE=y
-CONFIG_MARIMBA_CODEC=y
-CONFIG_TIMPANI_CODEC=y
-# CONFIG_MFD_PM8XXX_DEBUG is not set
-# CONFIG_MFD_PM8XXX_PWM is not set
-# CONFIG_MFD_PM8XXX_MISC is not set
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_RADIO_TAVARUA=y
-CONFIG_ION=y
-CONFIG_ION_MSM=y
-CONFIG_MSM_KGSL=y
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_MSM=y
-# CONFIG_FB_MSM_BACKLIGHT is not set
-CONFIG_FB_MSM_LOGO=y
-CONFIG_FB_MSM_TRIPLE_BUFFER=y
-CONFIG_FB_MSM_MDP40=y
-CONFIG_FB_MSM_OVERLAY=y
-CONFIG_FB_MSM_NO_MDP_PIPE_CTRL=y
-CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
-CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
-CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_MSM7KV2_SOC=y
-CONFIG_SND_MVS_SOC=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_MAGICMOUSE=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_EHCI_MSM_72K=y
-CONFIG_USB_ACM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_MSM_72K=y
-CONFIG_USB_G_ANDROID=y
-CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
-CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
-CONFIG_RMNET_SDIO_SMD_DATA_CHANNEL=""
-CONFIG_USB_MSM_ACA=y
-CONFIG_MMC=y
-CONFIG_MMC_PERF_PROFILING=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_MMC_CLKGATE=y
-CONFIG_MMC_PARANOID_SD_INIT=y
-CONFIG_MMC_BLOCK_MINORS=32
-# CONFIG_MMC_BLOCK_BOUNCE is not set
-CONFIG_MMC_TEST=m
-CONFIG_MMC_MSM=y
-# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
-CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
-CONFIG_MMC_MSM_SDC3_SUPPORT=y
-CONFIG_MMC_MSM_SDC4_SUPPORT=y
-CONFIG_LEDS_PMIC8058=y
-CONFIG_SWITCH=y
-CONFIG_SWITCH_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DEBUG=y
-CONFIG_STAGING=y
-CONFIG_ANDROID=y
-CONFIG_ANDROID_BINDER_IPC=y
-CONFIG_ANDROID_LOGGER=y
-CONFIG_ANDROID_RAM_CONSOLE=y
-CONFIG_ANDROID_TIMED_GPIO=y
-CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_YAFFS_FS=y
-CONFIG_YAFFS_DISABLE_TAGS_ECC=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_INFO=y
-CONFIG_DYNAMIC_DEBUG=y
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_DEV_QCRYPTO=m
-CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCEDEV=m
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
deleted file mode 100644
index 5964afb..0000000
--- a/arch/arm/configs/msm7630_defconfig
+++ /dev/null
@@ -1,389 +0,0 @@
-# CONFIG_ARM_PATCH_PHYS_VIRT is not set
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_DEBUG=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_ASHMEM=y
-CONFIG_EMBEDDED=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_MSM=y
-CONFIG_ARCH_MSM7X30=y
-# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_MSM_SMD=y
-CONFIG_MSM_SMD_PKG3=y
-CONFIG_MSM_SDIO_DMUX=y
-CONFIG_MSM_SDIO_CMUX=y
-CONFIG_MSM_SDIO_CTL=y
-CONFIG_MSM_ONCRPCROUTER=y
-CONFIG_MSM_RPC_WATCHDOG=y
-CONFIG_MSM_RMT_STORAGE_CLIENT=y
-# CONFIG_MSM_HW3D is not set
-# CONFIG_QSD_AUDIO is not set
-CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
-CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
-CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
-CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
-CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
-CONFIG_MSM_MULTIMEDIA_USE_ION=y
-CONFIG_MSM_RPC_PMIC=y
-CONFIG_MSM_RPC_USB=y
-CONFIG_MSM_RPC_PMAPP=y
-CONFIG_STRICT_MEMORY_RWX=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x1A000000
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_ADVANCED_ROUTER=y
-CONFIG_IP_MULTIPLE_TABLES=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_ROUTE_INFO=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_IPV6_MIP6=y
-CONFIG_IPV6_TUNNEL=y
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_IPV6_SUBTREES=y
-CONFIG_NETFILTER=y
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=y
-CONFIG_NF_CONNTRACK_FTP=y
-CONFIG_NF_CONNTRACK_H323=y
-CONFIG_NF_CONNTRACK_IRC=y
-CONFIG_NF_CONNTRACK_NETBIOS_NS=y
-CONFIG_NF_CONNTRACK_PPTP=y
-CONFIG_NF_CONNTRACK_SANE=y
-CONFIG_NF_CONNTRACK_SIP=y
-CONFIG_NF_CONNTRACK_TFTP=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NETFILTER_TPROXY=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_LOG=y
-CONFIG_NETFILTER_XT_TARGET_MARK=y
-CONFIG_NETFILTER_XT_TARGET_NFLOG=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_MATCH_COMMENT=y
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_HELPER=y
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-CONFIG_NETFILTER_XT_MATCH_LENGTH=y
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
-CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
-CONFIG_NETFILTER_XT_MATCH_SOCKET=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
-CONFIG_NETFILTER_XT_MATCH_STRING=y
-CONFIG_NETFILTER_XT_MATCH_TIME=y
-CONFIG_NETFILTER_XT_MATCH_U32=y
-CONFIG_NF_CONNTRACK_IPV4=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_AH=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_NF_NAT=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_MANGLE=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_HTB=y
-CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_SFQ=y
-CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_DSMARK=m
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NET_CLS_BASIC=y
-CONFIG_NET_CLS_TCINDEX=y
-CONFIG_NET_CLS_FW=y
-CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_MARK=y
-CONFIG_NET_CLS_FLOW=m
-CONFIG_NET_EMATCH=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_IBS=y
-CONFIG_MSM_BT_POWER=y
-CONFIG_CFG80211=y
-# CONFIG_CFG80211_WEXT is not set
-CONFIG_RFKILL=y
-CONFIG_GENLOCK=y
-CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_MTD=y
-CONFIG_MTD_TESTS=m
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=8
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_HAPTIC_ISA1200=y
-CONFIG_PMIC8XXX_UPL=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_CRYPT=y
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=y
-CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_MODE_SLIP6=y
-CONFIG_LIBRA_SDIOIF=m
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=m
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_PMIC8XXX=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_MSM=y
-CONFIG_TOUCHSCREEN_TSC2007=y
-CONFIG_TOUCHSCREEN_CY8C_TS=y
-CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_INPUT_GPIO=y
-CONFIG_BOSCH_BMA150=y
-# CONFIG_SERIO is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_HS=y
-CONFIG_DIAG_CHAR=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_QUP=y
-CONFIG_I2C_SSBI=y
-CONFIG_SPI=y
-CONFIG_SPI_QSD=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_BATTERY_MSM=y
-CONFIG_SENSORS_MSM_ADC=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_MSM_POPMEM=y
-CONFIG_PMIC8058=y
-CONFIG_MARIMBA_CORE=y
-CONFIG_MARIMBA_CODEC=y
-CONFIG_TIMPANI_CODEC=y
-# CONFIG_MFD_PM8XXX_DEBUG is not set
-# CONFIG_MFD_PM8XXX_PWM is not set
-# CONFIG_MFD_PM8XXX_MISC is not set
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_RADIO_TAVARUA=y
-CONFIG_ION=y
-CONFIG_ION_MSM=y
-CONFIG_MSM_KGSL=y
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_FB=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_MSM=y
-# CONFIG_FB_MSM_BACKLIGHT is not set
-CONFIG_FB_MSM_LOGO=y
-CONFIG_FB_MSM_TRIPLE_BUFFER=y
-CONFIG_FB_MSM_MDP40=y
-CONFIG_FB_MSM_OVERLAY=y
-CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
-CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
-CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-# CONFIG_BACKLIGHT_GENERIC is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-# CONFIG_SND_DRIVERS is not set
-# CONFIG_SND_ARM is not set
-# CONFIG_SND_SPI is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_MSM7KV2_SOC=y
-CONFIG_SND_MVS_SOC=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-# CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_EHCI_MSM_72K=y
-CONFIG_USB_ACM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_MSM_72K=y
-CONFIG_USB_G_ANDROID=y
-CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
-CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
-CONFIG_RMNET_SDIO_SMD_DATA_CHANNEL=""
-CONFIG_USB_MSM_ACA=y
-CONFIG_MMC=y
-CONFIG_MMC_PERF_PROFILING=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_MMC_CLKGATE=y
-CONFIG_MMC_PARANOID_SD_INIT=y
-CONFIG_MMC_BLOCK_MINORS=32
-# CONFIG_MMC_BLOCK_BOUNCE is not set
-CONFIG_MMC_TEST=m
-CONFIG_MMC_MSM=y
-# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
-CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
-CONFIG_MMC_MSM_SDC3_SUPPORT=y
-CONFIG_MMC_MSM_SDC4_SUPPORT=y
-CONFIG_LEDS_PMIC8058=y
-CONFIG_SWITCH=y
-CONFIG_SWITCH_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DEBUG=y
-CONFIG_STAGING=y
-CONFIG_ANDROID=y
-CONFIG_ANDROID_BINDER_IPC=y
-CONFIG_ANDROID_LOGGER=y
-CONFIG_ANDROID_RAM_CONSOLE=y
-CONFIG_ANDROID_TIMED_GPIO=y
-CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_EXT4_FS=y
-CONFIG_FUSE_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_YAFFS_FS=y
-CONFIG_YAFFS_DISABLE_TAGS_ECC=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
-CONFIG_DEBUG_SLAB=y
-CONFIG_DEBUG_SLAB_LEAK=y
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_PROVE_LOCKING=y
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_LIST=y
-CONFIG_DEBUG_PAGEALLOC=y
-CONFIG_DYNAMIC_DEBUG=y
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_DEV_QCRYPTO=m
-CONFIG_CRYPTO_DEV_QCE=m
-CONFIG_CRYPTO_DEV_QCEDEV=m
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index cfdff6f..c0a945e 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -23,7 +23,6 @@
CONFIG_RD_LZMA=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
@@ -36,49 +35,55 @@
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM8610=y
CONFIG_ARCH_MSM8226=y
-CONFIG_SND_SOC_MSM8226=y
-CONFIG_SND_SOC_MSM8X10=y
# CONFIG_MSM_STACKED_MEMORY is not set
CONFIG_CPU_HAS_L2_PMU=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
-CONFIG_MSM_IPC_LOGGING=y
CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_SMP2P=y
CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_LOGGING=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_LPASS_QDSP6V5=y
-CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
CONFIG_MSM_PIL_VENUS=y
+CONFIG_MSM_PIL_PRONTO=y
+CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_NONSECURE=y
CONFIG_MSM_OCMEM_POWER_DISABLE=y
+CONFIG_SENSORS_ADSP=y
+CONFIG_MSM_RTB=y
+CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
CONFIG_SCHED_MC=y
CONFIG_ARM_ARCH_TIMER=y
-CONFIG_HOTPLUG_CPU=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_USE_OF=y
CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -180,8 +185,16 @@
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
CONFIG_NET_CLS_FW=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
@@ -190,18 +203,18 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_KS8851=y
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
-CONFIG_KS8851=y
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
-CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -210,33 +223,56 @@
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
-CONFIG_SPMI=y
-CONFIG_SPMI_MSM_PMIC_ARB=y
-CONFIG_MSM_QPNP_INT=y
-CONFIG_SLIMBUS=y
-CONFIG_SLIMBUS_MSM_NGD=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_SPI=y
-CONFIG_SPI_QUP=y
-CONFIG_SPI_SPIDEV=m
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
-CONFIG_WCD9306_CODEC=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB=y
+CONFIG_MSM_QPNP_INT=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
-CONFIG_HWMON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_CHARGER=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_SENSORS_QPNP_ADC_CURRENT=y
-CONFIG_REGULATOR=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_WCD9306_CODEC=y
CONFIG_REGULATOR_STUB=y
CONFIG_REGULATOR_QPNP=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_MSM_CAMERA is not set
+CONFIG_OV8825=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_ISPIF=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_OV9724=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
CONFIG_FB_MSM_MDSS=y
@@ -248,6 +284,8 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSM8226=y
+CONFIG_SND_SOC_MSM8X10=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
@@ -262,25 +300,34 @@
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_QPNP=y
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_QPNP_PWM=y
-CONFIG_MSM_IOMMU=y
-CONFIG_MSM_IOMMU_PMON=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_QPNP=y
-CONFIG_RTC_CLASS=y
-# CONFIG_RTC_DRV_MSM is not set
-CONFIG_RTC_DRV_QPNP=y
+CONFIG_QPNP_PWM=y
+CONFIG_QPNP_POWER_ON=y
+CONFIG_MSM_IOMMU=y
+CONFIG_MSM_IOMMU_PMON=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_TMC=y
+CONFIG_CORESIGHT_TPIU=y
+CONFIG_CORESIGHT_FUNNEL=y
+CONFIG_CORESIGHT_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
@@ -294,51 +341,16 @@
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_KEYS=y
CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
-CONFIG_QPNP_POWER_ON=y
-CONFIG_LIBCRC32C=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_MEDIA_CAMERA_SUPPORT=y
-# CONFIG_MSM_CAMERA is not set
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_SUBDEV_API=y
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_MSM_OCMEM=y
-CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
-CONFIG_MSM_OCMEM_DEBUG=y
-CONFIG_MSM_OCMEM_NONSECURE=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_TSENS8974=y
-CONFIG_THERMAL_MONITOR=y
-CONFIG_THERMAL_QPNP_ADC_TM=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_RTB_SEPARATE_CPUS=y
-CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_TMC=y
-CONFIG_CORESIGHT_TPIU=y
-CONFIG_CORESIGHT_FUNNEL=y
-CONFIG_CORESIGHT_REPLICATOR=y
-CONFIG_CORESIGHT_STM=y
-CONFIG_CORESIGHT_ETM=y
-CONFIG_CORESIGHT_EVENT=m
-CONFIG_ENABLE_DEFAULT_TRACERS=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index baefac5..dda9bd3 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -21,7 +21,6 @@
CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
CONFIG_PROFILING=y
@@ -47,21 +46,15 @@
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
-CONFIG_MSM_SDIO_DMUX=y
# CONFIG_MSM_RESET_MODEM is not set
# CONFIG_MSM_SMD_NMEA is not set
-CONFIG_MSM_SDIO_TTY=y
# CONFIG_MSM_SMD_QMI is not set
-CONFIG_MSM_SDIO_CMUX=y
CONFIG_MSM_DSPS=y
-CONFIG_MSM_SDIO_CTL=y
CONFIG_MSM_ONCRPCROUTER=y
# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
# CONFIG_MSM_RPCSERVER_WATCHDOG is not set
# CONFIG_MSM_RPCSERVER_HANDSET is not set
CONFIG_MSM_RMT_STORAGE_CLIENT=y
-CONFIG_MSM_SDIO_SMEM=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_MODEM=y
@@ -84,7 +77,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_CPU_FREQ=y
@@ -96,7 +88,6 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -252,7 +243,6 @@
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
CONFIG_SMSC911X=y
@@ -315,10 +305,6 @@
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_IMX074=y
CONFIG_WEBCAM_OV9726=y
@@ -328,6 +314,10 @@
CONFIG_MSM_ACTUATOR=y
CONFIG_MSM_GEMINI=y
CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
CONFIG_ION_MSM=y
@@ -404,7 +394,6 @@
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_SLEEP=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
@@ -413,6 +402,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 28d7b12..abc7460 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -21,7 +21,6 @@
CONFIG_RD_LZMA=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -46,21 +45,15 @@
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
-CONFIG_MSM_SDIO_DMUX=y
# CONFIG_MSM_RESET_MODEM is not set
# CONFIG_MSM_SMD_NMEA is not set
-CONFIG_MSM_SDIO_TTY=y
# CONFIG_MSM_SMD_QMI is not set
-CONFIG_MSM_SDIO_CMUX=y
CONFIG_MSM_DSPS=y
-CONFIG_MSM_SDIO_CTL=y
CONFIG_MSM_ONCRPCROUTER=y
# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
# CONFIG_MSM_RPCSERVER_WATCHDOG is not set
# CONFIG_MSM_RPCSERVER_HANDSET is not set
CONFIG_MSM_RMT_STORAGE_CLIENT=y
-CONFIG_MSM_SDIO_SMEM=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_MODEM=y
@@ -83,7 +76,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_COMPACTION=y
CONFIG_CP_ACCESS=y
CONFIG_CPU_FREQ=y
@@ -95,7 +87,6 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -252,7 +243,6 @@
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
-CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
CONFIG_SMSC911X=y
@@ -315,10 +305,6 @@
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_IMX074=y
CONFIG_WEBCAM_OV9726=y
@@ -328,6 +314,10 @@
CONFIG_MSM_ACTUATOR=y
CONFIG_MSM_GEMINI=y
CONFIG_OV7692=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_RADIO_TAVARUA=y
CONFIG_ION=y
CONFIG_ION_MSM=y
@@ -404,7 +394,6 @@
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_SLEEP=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
@@ -413,6 +402,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index a8ea31d..4e6cb05 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -24,7 +24,6 @@
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -35,6 +34,7 @@
CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM8960=y
CONFIG_ARCH_MSM8930=y
@@ -69,7 +69,6 @@
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_AVS_HW=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_LPASS_QDSP6V4=y
@@ -107,7 +106,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_CPU_FREQ=y
@@ -119,7 +117,10 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -134,8 +135,6 @@
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
@@ -355,11 +354,6 @@
CONFIG_DVB_CORE=m
CONFIG_USER_RC_INPUT=y
CONFIG_IR_GPIO_CIR=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_IMX074=y
CONFIG_MT9M114=y
@@ -376,17 +370,22 @@
CONFIG_MSM_GEMINI=y
CONFIG_MSM_MERCURY=y
CONFIG_MSM_CSI20_HEADER=y
-CONFIG_S5K3L1YX=y
-CONFIG_IMX091=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
+CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
CONFIG_MSM_WFD=y
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-# CONFIG_DVB_FE_CUSTOMISE is not set
CONFIG_DVB_MPQ=m
CONFIG_DVB_MPQ_DEMUX=m
CONFIG_DVB_MPQ_VIDEO=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
@@ -457,14 +456,13 @@
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
# CONFIG_MMC_MSM_SDC2_SUPPORT is not set
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_IOSCHED_TEST=y
-CONFIG_MMC_BLOCK_TEST=y
CONFIG_LEDS_PM8XXX=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -475,6 +473,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
@@ -529,9 +528,3 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 9f10bc4..c4fffb9 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -23,7 +23,6 @@
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -34,6 +33,7 @@
CONFIG_MODVERSIONS=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_EFI_PARTITION=y
+CONFIG_IOSCHED_TEST=y
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM8960=y
CONFIG_ARCH_MSM8930=y
@@ -68,7 +68,6 @@
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_AVS_HW=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_LPASS_QDSP6V4=y
@@ -112,7 +111,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_CPU_FREQ=y
@@ -124,7 +122,10 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -139,8 +140,6 @@
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
@@ -360,11 +359,6 @@
CONFIG_DVB_CORE=m
CONFIG_USER_RC_INPUT=y
CONFIG_IR_GPIO_CIR=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_VIDEOBUF2_MSM_MEM=y
-CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_IMX074=y
CONFIG_MT9M114=y
@@ -380,17 +374,22 @@
CONFIG_MSM_GEMINI=y
CONFIG_MSM_MERCURY=y
CONFIG_MSM_CSI20_HEADER=y
-CONFIG_S5K3L1YX=y
-CONFIG_IMX091=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
+CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
CONFIG_MSM_WFD=y
-CONFIG_RADIO_IRIS=y
-CONFIG_RADIO_IRIS_TRANSPORT=m
-# CONFIG_DVB_FE_CUSTOMISE is not set
CONFIG_DVB_MPQ=m
CONFIG_DVB_MPQ_DEMUX=m
CONFIG_DVB_MPQ_VIDEO=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEOBUF2_MSM_MEM=y
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+# CONFIG_DVB_FE_CUSTOMISE is not set
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
@@ -460,14 +459,13 @@
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
# CONFIG_MMC_MSM_SDC2_SUPPORT is not set
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC3_WP_SUPPORT=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
-CONFIG_IOSCHED_TEST=y
-CONFIG_MMC_BLOCK_TEST=y
CONFIG_LEDS_PM8XXX=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
@@ -478,6 +476,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
@@ -547,9 +546,3 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 224df83..c33a236 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -24,7 +24,6 @@
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -54,7 +53,6 @@
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_IPC_ROUTER_SECURITY=y
CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_LPASS_QDSP6V5=y
@@ -63,6 +61,7 @@
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
@@ -71,6 +70,7 @@
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_SENSORS_ADSP=y
CONFIG_MSM_RTB=y
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_CACHE_ERP=y
@@ -80,6 +80,7 @@
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -90,7 +91,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
@@ -103,7 +103,10 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -117,8 +120,6 @@
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
@@ -226,19 +227,20 @@
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_ATH3K=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
CONFIG_NL80211_TESTMODE=y
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_HAPTIC_ISA1200=y
CONFIG_QSEECOM=y
+CONFIG_QPNP_MISC=y
CONFIG_USB_HSIC_SMSC_HUB=y
CONFIG_TI_DRV2667=y
CONFIG_SCSI=y
@@ -291,7 +293,6 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
-CONFIG_QPNP_REVID=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -322,9 +323,10 @@
# CONFIG_MSM_CAMERA is not set
CONFIG_MT9M114=y
CONFIG_OV2720=y
+CONFIG_IMX135=y
CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CCI=y
CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
CONFIG_MSM_CSI30_HEADER=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
@@ -398,8 +400,8 @@
CONFIG_MMC_BLOCK_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_TRIGGERS=y
@@ -412,6 +414,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
@@ -423,6 +426,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_REVID=y
CONFIG_QPNP_COINCELL=y
CONFIG_MSM_IOMMU=y
CONFIG_MOBICORE_SUPPORT=m
@@ -461,17 +465,10 @@
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
-CONFIG_CRC_CCITT=y
-CONFIG_MSM_EVENT_TIMER=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index e42aa77..1cda524 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -23,7 +23,6 @@
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_KALLSYMS_ALL=y
-CONFIG_ASHMEM=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
@@ -53,7 +52,6 @@
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_IPC_ROUTER_SECURITY=y
CONFIG_MSM_QMI_INTERFACE=y
-# CONFIG_MSM_HW3D is not set
CONFIG_MSM_SUBSYSTEM_RESTART=y
CONFIG_MSM_SYSMON_COMM=y
CONFIG_MSM_PIL_LPASS_QDSP6V5=y
@@ -62,6 +60,7 @@
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
@@ -70,6 +69,7 @@
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_SENSORS_ADSP=y
CONFIG_MSM_RTB=y
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_CACHE_ERP=y
@@ -84,6 +84,7 @@
CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -94,7 +95,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
@@ -107,7 +107,10 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_WAKELOCK=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -121,8 +124,6 @@
CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
@@ -230,20 +231,21 @@
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCISMD=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_ATH3K=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
CONFIG_NL80211_TESTMODE=y
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_TSPP=m
CONFIG_HAPTIC_ISA1200=y
CONFIG_QSEECOM=y
+CONFIG_QPNP_MISC=y
CONFIG_USB_HSIC_SMSC_HUB=y
CONFIG_TI_DRV2667=y
CONFIG_SCSI=y
@@ -296,7 +298,6 @@
CONFIG_SPMI=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
-CONFIG_QPNP_REVID=y
CONFIG_SLIMBUS_MSM_NGD=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -328,9 +329,10 @@
# CONFIG_MSM_CAMERA is not set
CONFIG_MT9M114=y
CONFIG_OV2720=y
+CONFIG_IMX135=y
CONFIG_MSM_CAMERA_SENSOR=y
-CONFIG_MSM_CCI=y
CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
CONFIG_MSM_CSI30_HEADER=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
@@ -406,8 +408,8 @@
CONFIG_MMC_BLOCK_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
-CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_TRIGGERS=y
@@ -420,6 +422,7 @@
CONFIG_STAGING=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
@@ -431,6 +434,7 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_REVID=y
CONFIG_QPNP_COINCELL=y
CONFIG_MSM_IOMMU=y
CONFIG_MSM_IOMMU_PMON=y
@@ -486,17 +490,10 @@
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_KEYS=y
CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=y
-CONFIG_CRC_CCITT=y
-CONFIG_MSM_EVENT_TIMER=y
-CONFIG_PM_WAKELOCKS=y
-CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 9ab1cdd..0fb8538 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -62,7 +62,6 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -185,7 +184,6 @@
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index c2fb1487..8d6bc81 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -34,7 +34,6 @@
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM9625=y
# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_CPU_HAS_L2_PMU=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
@@ -52,15 +51,18 @@
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_RTB=y
+CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_USE_OF=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -71,6 +73,7 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -161,11 +164,18 @@
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_MSM_NAND is not set
CONFIG_MTD_MSM_QPIC_NAND=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
@@ -174,8 +184,8 @@
CONFIG_KS8851=y
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_MSM_RMNET is not set
-# CONFIG_MSM_RMNET_BAM is not set
CONFIG_MSM_RMNET_WWAN=y
+CONFIG_ECM_IPA=y
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
@@ -190,9 +200,8 @@
CONFIG_INPUT_GPIO=m
CONFIG_SERIO_LIBPS2=y
# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HS=y
-CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_SERIAL_MSM_HSL=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
@@ -222,18 +231,35 @@
CONFIG_ION_MSM=y
CONFIG_FB=y
CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC=y
CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MDM9625=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_G_ANDROID=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
@@ -253,7 +279,6 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_IPA=y
-CONFIG_ECM_IPA=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
CONFIG_CORESIGHT_TPIU=y
@@ -262,10 +287,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
-CONFIG_EXT3_FS=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
@@ -298,37 +323,3 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_MSM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 828eaa9..9e9bba9 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -34,7 +34,6 @@
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM9625=y
# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_CPU_HAS_L2_PMU=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
@@ -52,15 +51,18 @@
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_ADSP_LOADER=m
+CONFIG_MSM_RTB=y
+CONFIG_MSM_UARTDM_Core_v14=y
+CONFIG_MSM_BOOT_STATS=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_USE_OF=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -71,6 +73,7 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_PACKET=y
@@ -161,11 +164,18 @@
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_MSM_NAND is not set
CONFIG_MTD_MSM_QPIC_NAND=y
-CONFIG_SYNC=y
-CONFIG_SW_SYNC=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
@@ -174,8 +184,8 @@
CONFIG_KS8851=y
# CONFIG_NET_VENDOR_MICROCHIP is not set
# CONFIG_MSM_RMNET is not set
-# CONFIG_MSM_RMNET_BAM is not set
CONFIG_MSM_RMNET_WWAN=y
+CONFIG_ECM_IPA=y
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
@@ -190,10 +200,9 @@
CONFIG_INPUT_GPIO=m
CONFIG_SERIO_LIBPS2=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HS=y
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
-CONFIG_SERIAL_MSM_HS=y
-CONFIG_MSM_UARTDM_Core_v14=y
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
@@ -223,18 +232,35 @@
CONFIG_ION_MSM=y
CONFIG_FB=y
CONFIG_FB_MSM=y
-CONFIG_FB_MSM_QPIC=y
CONFIG_FB_MSM_QPIC_PANEL_DETECT=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_MDM9625=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_G_ANDROID=y
-CONFIG_USB=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_MMC=y
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
@@ -254,7 +280,6 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_IPA=y
-CONFIG_ECM_IPA=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
CONFIG_CORESIGHT_TPIU=y
@@ -263,10 +288,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_EVENT=m
+CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
-CONFIG_EXT3_FS=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
@@ -299,37 +324,3 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_EHSET=y
-CONFIG_USB_EHCI_MSM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_STORAGE_FREECOM=y
-CONFIG_USB_STORAGE_ISD200=y
-CONFIG_USB_STORAGE_USBAT=y
-CONFIG_USB_STORAGE_SDDR09=y
-CONFIG_USB_STORAGE_SDDR55=y
-CONFIG_USB_STORAGE_JUMPSHOT=y
-CONFIG_USB_STORAGE_ALAUDA=y
-CONFIG_USB_STORAGE_ONETOUCH=y
-CONFIG_USB_STORAGE_KARMA=y
-CONFIG_USB_STORAGE_CYPRESS_ATACB=y
-CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_SCSI=y
-CONFIG_SCSI_TGT=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MSM_RTB=y
-CONFIG_MSM_MEMORY_DUMP=y
-CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS_GC is not set
-CONFIG_MSM_BOOT_STATS=y
diff --git a/arch/arm/configs/msmzinc_defconfig b/arch/arm/configs/msmzinc_defconfig
index b74b204..678b086 100644
--- a/arch/arm/configs/msmzinc_defconfig
+++ b/arch/arm/configs/msmzinc_defconfig
@@ -211,6 +211,7 @@
CONFIG_GENLOCK_MISCDEVICE=y
CONFIG_SYNC=y
CONFIG_SW_SYNC=y
+CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_HAPTIC_ISA1200=y
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index abb222f..3cc2b52 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -318,7 +318,7 @@
* DMA region above it's default value of 2MB. It must be called before the
* memory allocator is initialised, i.e. before any core_initcall.
*/
-extern void __init init_consistent_dma_size(unsigned long size);
+static inline void init_consistent_dma_size(unsigned long size) { }
/*
* For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f7d993f..ac51e25 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -281,7 +281,6 @@
select MSM_RPM_STATS_LOG
select QMI_ENCDEC
select DONT_MAP_HOLE_AFTER_MEMBANK0
- select SENSORS_ADSP
select MSM_ULTRASOUND_B
select MSM_LPM_TEST
select MSM_RPM_LOG
@@ -428,6 +427,7 @@
select ARM_HAS_SG_CHAIN
select REGULATOR
select MSM_RPM_REGULATOR_SMD
+ select MSM_SPM_REGULATOR
config ARCH_MSM8226
bool "MSM8226"
@@ -463,7 +463,9 @@
select ARM_HAS_SG_CHAIN
select REGULATOR
select MSM_RPM_REGULATOR_SMD
+ select MSM_SPM_REGULATOR
select MSM_JTAG_MM if CORESIGHT_ETM
+ select MSM_CPR_REGULATOR
endmenu
choice
@@ -1823,7 +1825,6 @@
config MSM_HW3D
tristate "MSM Hardware 3D Register Driver"
depends on ANDROID_PMEM
- default y
help
Provides access to registers needed by the userspace OpenGL|ES
library.
@@ -2062,6 +2063,16 @@
be used on systems which contain an RPM which communicates with the
application processor over SMD.
+config MSM_SPM_REGULATOR
+ bool "SPM regulator driver"
+ depends on REGULATOR && SPMI && OF_SPMI
+ help
+ Enable support for the SPM regulator driver which is used for
+ setting voltages of processor supply regulators via the SPM module
+ found inside of the MSM chips. The SPM regulator driver can be used
+ on MSM systems where the APSS processor cores are supplied by their
+ own PMIC regulator.
+
config MSM_SMCMOD
tristate "Secure Monitor Call (SMC) Module"
default n
@@ -2631,6 +2642,8 @@
config SENSORS_ADSP
bool "Enable Sensors Driver Support for ADSP"
+ depends on (ARCH_MSM8226 || ARCH_MSM8974)
+ default y
help
Add support for sensors ADSP driver.
This driver is used for exercising different sensors use cases,
@@ -2895,4 +2908,20 @@
display init, total boot time.
This figures are reported in mpm sleep clock cycles and have a
resolution of 31 bits as 1 bit is used as an overflow check.
+
+config MSM_XPU_ERR_FATAL
+ bool "Configure XPU violations as fatal errors"
+ help
+ Select if XPU violations have to be configured as fatal errors.
+
+config MSM_CPR_REGULATOR
+ bool "RBCPR regulator driver for APC"
+ depends on REGULATOR
+ depends on OF
+ help
+ Compile in RBCPR (RapidBridge Core Power Reduction) driver to support
+ corner vote for APC power rail. The driver takes PTE process voltage
+ suggestions in efuse as initial settings. It converts corner vote
+ to voltage value before writing to a voltage regulator API, such as
+ that provided by spm-regulator driver.
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 161ee3d..d07b094 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -79,6 +79,7 @@
obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_gpio.o
obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_gpio_test.o smp2p_spinlock_test.o
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
+obj-$(CONFIG_MSM_XPU_ERR_FATAL) += scm-xpu.o
obj-$(CONFIG_MSM_SECURE_IO) += scm-io.o
obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
obj-$(CONFIG_MSM_PIL) += scm-pas.o
@@ -209,6 +210,7 @@
endif
obj-$(CONFIG_MSM_RPM_REGULATOR_SMD) += rpm-regulator-smd.o
+obj-$(CONFIG_MSM_SPM_REGULATOR) += spm-regulator.o
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
obj-y += subsystem_notif.o
@@ -420,3 +422,4 @@
obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o
obj-$(CONFIG_ARCH_MSM8974) += msm_mpmctr.o
+obj-$(CONFIG_MSM_CPR_REGULATOR) += cpr-regulator.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 8ba1b39..73ea435 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -57,7 +57,7 @@
{ 1, 300000, PLL0, 4, 2, 1150000, 1150000, 4 },
{ 1, 384000, ACPUPLL, 5, 0, 1150000, 1150000, 4 },
{ 1, 600000, PLL0, 4, 0, 1150000, 1150000, 6 },
- { 1, 787200, ACPUPLL, 5, 0, 1150000, 1150000, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0, 998400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0, 1190400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
{ 0 }
@@ -98,13 +98,13 @@
drv_data.apcs_rcg_config = drv_data.apcs_rcg_cmd + 4;
- drv_data.vdd_cpu = regulator_get(&pdev->dev, "a7_cpu");
+ drv_data.vdd_cpu = devm_regulator_get(&pdev->dev, "a7_cpu");
if (IS_ERR(drv_data.vdd_cpu)) {
dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_cpu");
return PTR_ERR(drv_data.vdd_cpu);
}
- drv_data.vdd_mem = regulator_get(&pdev->dev, "a7_mem");
+ drv_data.vdd_mem = devm_regulator_get(&pdev->dev, "a7_mem");
if (IS_ERR(drv_data.vdd_mem)) {
dev_err(&pdev->dev, "regulator for %s get failed\n", "a7_mem");
return PTR_ERR(drv_data.vdd_mem);
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index b439088..34952fb 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -105,13 +105,13 @@
if (!drv_data.apcs_cpu_pwr_ctl)
return -ENOMEM;
- drv_data.vdd_cpu = regulator_get(&pdev->dev, "a5_cpu");
+ drv_data.vdd_cpu = devm_regulator_get(&pdev->dev, "a5_cpu");
if (IS_ERR(drv_data.vdd_cpu)) {
dev_err(&pdev->dev, "regulator for %s get failed\n", "a5_cpu");
return PTR_ERR(drv_data.vdd_cpu);
}
- drv_data.vdd_mem = regulator_get(&pdev->dev, "a5_mem");
+ drv_data.vdd_mem = devm_regulator_get(&pdev->dev, "a5_mem");
if (IS_ERR(drv_data.vdd_mem)) {
dev_err(&pdev->dev, "regulator for %s get failed\n", "a5_mem");
return PTR_ERR(drv_data.vdd_mem);
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 9104f98..88bf919 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -40,7 +40,7 @@
#define POLL_INTERVAL_US 1
#define APCS_RCG_UPDATE_TIMEOUT_US 20
-static struct acpuclk_drv_data *acpuclk_init_data;
+static struct acpuclk_drv_data *priv;
static uint32_t bus_perf_client;
/* Update the bus bandwidth request. */
@@ -48,7 +48,7 @@
{
int ret;
- if (bw >= acpuclk_init_data->bus_scale->num_usecases) {
+ if (bw >= priv->bus_scale->num_usecases) {
pr_err("invalid bandwidth request (%d)\n", bw);
return;
}
@@ -67,15 +67,13 @@
int rc = 0;
/* Increase vdd_mem before vdd_cpu. vdd_mem should be >= vdd_cpu. */
- rc = regulator_set_voltage(acpuclk_init_data->vdd_mem, vdd_mem,
- acpuclk_init_data->vdd_max_mem);
+ rc = regulator_set_voltage(priv->vdd_mem, vdd_mem, priv->vdd_max_mem);
if (rc) {
pr_err("vdd_mem increase failed (%d)\n", rc);
return rc;
}
- rc = regulator_set_voltage(acpuclk_init_data->vdd_cpu, vdd_cpu,
- acpuclk_init_data->vdd_max_cpu);
+ rc = regulator_set_voltage(priv->vdd_cpu, vdd_cpu, priv->vdd_max_cpu);
if (rc)
pr_err("vdd_cpu increase failed (%d)\n", rc);
@@ -88,16 +86,14 @@
int ret;
/* Update CPU voltage. */
- ret = regulator_set_voltage(acpuclk_init_data->vdd_cpu, vdd_cpu,
- acpuclk_init_data->vdd_max_cpu);
+ ret = regulator_set_voltage(priv->vdd_cpu, vdd_cpu, priv->vdd_max_cpu);
if (ret) {
pr_err("vdd_cpu decrease failed (%d)\n", ret);
return;
}
/* Decrease vdd_mem after vdd_cpu. vdd_mem should be >= vdd_cpu. */
- ret = regulator_set_voltage(acpuclk_init_data->vdd_mem, vdd_mem,
- acpuclk_init_data->vdd_max_mem);
+ ret = regulator_set_voltage(priv->vdd_mem, vdd_mem, priv->vdd_max_mem);
if (ret)
pr_err("vdd_mem decrease failed (%d)\n", ret);
}
@@ -142,14 +138,14 @@
{
int rc = 0;
unsigned int tgt_freq_hz = tgt_s->khz * 1000;
- struct clkctl_acpu_speed *strt_s = acpuclk_init_data->current_speed;
- struct clkctl_acpu_speed *cxo_s = &acpuclk_init_data->freq_tbl[0];
- struct clk *strt = acpuclk_init_data->src_clocks[strt_s->src].clk;
- struct clk *tgt = acpuclk_init_data->src_clocks[tgt_s->src].clk;
+ struct clkctl_acpu_speed *strt_s = priv->current_speed;
+ struct clkctl_acpu_speed *cxo_s = &priv->freq_tbl[0];
+ struct clk *strt = priv->src_clocks[strt_s->src].clk;
+ struct clk *tgt = priv->src_clocks[tgt_s->src].clk;
if (strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL) {
/* Switch to another always on src */
- select_clk_source_div(acpuclk_init_data, cxo_s);
+ select_clk_source_div(priv, cxo_s);
/* Re-program acpu pll */
if (atomic)
@@ -167,7 +163,7 @@
BUG_ON(clk_prepare_enable(tgt));
/* Switch back to acpu pll */
- select_clk_source_div(acpuclk_init_data, tgt_s);
+ select_clk_source_div(priv, tgt_s);
} else if (strt_s->src != ACPUPLL && tgt_s->src == ACPUPLL) {
rc = clk_set_rate(tgt, tgt_freq_hz);
@@ -177,16 +173,16 @@
}
if (atomic)
- clk_enable(tgt);
+ rc = clk_enable(tgt);
else
- clk_prepare_enable(tgt);
+ rc = clk_prepare_enable(tgt);
if (rc) {
pr_err("ACPU PLL enable failed\n");
return rc;
}
- select_clk_source_div(acpuclk_init_data, tgt_s);
+ select_clk_source_div(priv, tgt_s);
if (atomic)
clk_disable(strt);
@@ -195,17 +191,17 @@
} else {
if (atomic)
- clk_enable(tgt);
+ rc = clk_enable(tgt);
else
- clk_prepare_enable(tgt);
+ rc = clk_prepare_enable(tgt);
if (rc) {
pr_err("%s enable failed\n",
- acpuclk_init_data->src_clocks[tgt_s->src].name);
+ priv->src_clocks[tgt_s->src].name);
return rc;
}
- select_clk_source_div(acpuclk_init_data, tgt_s);
+ select_clk_source_div(priv, tgt_s);
if (atomic)
clk_disable(strt);
@@ -224,16 +220,16 @@
int rc = 0;
if (reason == SETRATE_CPUFREQ)
- mutex_lock(&acpuclk_init_data->lock);
+ mutex_lock(&priv->lock);
- strt_s = acpuclk_init_data->current_speed;
+ strt_s = priv->current_speed;
/* Return early if rate didn't change */
if (rate == strt_s->khz)
goto out;
/* Find target frequency */
- for (tgt_s = acpuclk_init_data->freq_tbl; tgt_s->khz != 0; tgt_s++)
+ for (tgt_s = priv->freq_tbl; tgt_s->khz != 0; tgt_s++)
if (tgt_s->khz == rate)
break;
if (tgt_s->khz == 0) {
@@ -261,7 +257,7 @@
if (rc)
goto out;
- acpuclk_init_data->current_speed = tgt_s;
+ priv->current_speed = tgt_s;
pr_debug("CPU speed change complete\n");
/* Nothing else to do for SWFI or power-collapse. */
@@ -277,13 +273,13 @@
out:
if (reason == SETRATE_CPUFREQ)
- mutex_unlock(&acpuclk_init_data->lock);
+ mutex_unlock(&priv->lock);
return rc;
}
static unsigned long acpuclk_cortex_get_rate(int cpu)
{
- return acpuclk_init_data->current_speed->khz;
+ return priv->current_speed->khz;
}
#ifdef CONFIG_CPU_FREQ_MSM
@@ -293,18 +289,17 @@
{
int i, freq_cnt = 0;
- /* Construct the freq_table tables from acpuclk_init_data->freq_tbl. */
- for (i = 0; acpuclk_init_data->freq_tbl[i].khz != 0
+ /* Construct the freq_table tables from priv->freq_tbl. */
+ for (i = 0; priv->freq_tbl[i].khz != 0
&& freq_cnt < ARRAY_SIZE(freq_table); i++) {
- if (!acpuclk_init_data->freq_tbl[i].use_for_scaling)
+ if (!priv->freq_tbl[i].use_for_scaling)
continue;
freq_table[freq_cnt].index = freq_cnt;
- freq_table[freq_cnt].frequency =
- acpuclk_init_data->freq_tbl[i].khz;
+ freq_table[freq_cnt].frequency = priv->freq_tbl[i].khz;
freq_cnt++;
}
/* freq_table not big enough to store all usable freqs. */
- BUG_ON(acpuclk_init_data->freq_tbl[i].khz != 0);
+ BUG_ON(priv->freq_tbl[i].khz != 0);
freq_table[freq_cnt].index = freq_cnt;
freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
@@ -332,43 +327,40 @@
unsigned long max_cpu_khz = 0;
int i, rc;
- acpuclk_init_data = data;
- mutex_init(&acpuclk_init_data->lock);
+ priv = data;
+ mutex_init(&priv->lock);
- bus_perf_client = msm_bus_scale_register_client(
- acpuclk_init_data->bus_scale);
+ bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
if (!bus_perf_client) {
pr_err("Unable to register bus client\n");
BUG();
}
for (i = 0; i < NUM_SRC; i++) {
- if (!acpuclk_init_data->src_clocks[i].name)
+ if (!priv->src_clocks[i].name)
continue;
- acpuclk_init_data->src_clocks[i].clk =
- clk_get(&pdev->dev,
- acpuclk_init_data->src_clocks[i].name);
- BUG_ON(IS_ERR(acpuclk_init_data->src_clocks[i].clk));
+ priv->src_clocks[i].clk =
+ devm_clk_get(&pdev->dev, priv->src_clocks[i].name);
+ BUG_ON(IS_ERR(priv->src_clocks[i].clk));
}
/* Improve boot time by ramping up CPU immediately */
- for (i = 0; acpuclk_init_data->freq_tbl[i].khz != 0; i++)
- if (acpuclk_init_data->freq_tbl[i].use_for_scaling)
- max_cpu_khz = acpuclk_init_data->freq_tbl[i].khz;
+ for (i = 0; priv->freq_tbl[i].khz != 0; i++)
+ if (priv->freq_tbl[i].use_for_scaling)
+ max_cpu_khz = priv->freq_tbl[i].khz;
/* Initialize regulators */
- rc = increase_vdd(acpuclk_init_data->vdd_max_cpu,
- acpuclk_init_data->vdd_max_mem);
+ rc = increase_vdd(priv->vdd_max_cpu, priv->vdd_max_mem);
if (rc)
goto err_vdd;
- rc = regulator_enable(acpuclk_init_data->vdd_mem);
+ rc = regulator_enable(priv->vdd_mem);
if (rc) {
dev_err(&pdev->dev, "regulator_enable for mem failed\n");
goto err_vdd;
}
- rc = regulator_enable(acpuclk_init_data->vdd_cpu);
+ rc = regulator_enable(priv->vdd_cpu);
if (rc) {
dev_err(&pdev->dev, "regulator_enable for cpu failed\n");
goto err_vdd_cpu;
@@ -388,15 +380,7 @@
return 0;
err_vdd_cpu:
- regulator_disable(acpuclk_init_data->vdd_mem);
+ regulator_disable(priv->vdd_mem);
err_vdd:
- regulator_put(acpuclk_init_data->vdd_mem);
- regulator_put(acpuclk_init_data->vdd_cpu);
-
- for (i = 0; i < NUM_SRC; i++) {
- if (!acpuclk_init_data->src_clocks[i].name)
- continue;
- clk_put(acpuclk_init_data->src_clocks[i].clk);
- }
return rc;
}
diff --git a/arch/arm/mach-msm/acpuclock-krait-debug.c b/arch/arm/mach-msm/acpuclock-krait-debug.c
index a29735e..f11b9fc 100644
--- a/arch/arm/mach-msm/acpuclock-krait-debug.c
+++ b/arch/arm/mach-msm/acpuclock-krait-debug.c
@@ -249,6 +249,56 @@
}
DEFINE_SIMPLE_ATTRIBUTE(boost_fops, boost_get, NULL, "%lld\n");
+static int acpu_table_show(struct seq_file *m, void *unused)
+{
+ const struct acpu_level *level;
+
+ seq_printf(m, "CPU_KHz PLL_L_Val L2_KHz VDD_Dig VDD_Mem ");
+ seq_printf(m, "BW_Mbps VDD_Core UA_Core AVS\n");
+
+ for (level = drv->acpu_freq_tbl; level->speed.khz != 0; level++) {
+
+ const struct l2_level *l2 =
+ &drv->l2_freq_tbl[level->l2_level];
+ u32 bw = drv->bus_scale->usecase[l2->bw_level].vectors[0].ib;
+
+ if (!level->use_for_scaling)
+ continue;
+
+ /* CPU speed information */
+ seq_printf(m, "%7lu %9u ",
+ level->speed.khz,
+ level->speed.pll_l_val);
+
+ /* L2 level information */
+ seq_printf(m, "%7lu %7d %7d %7u ",
+ l2->speed.khz,
+ l2->vdd_dig,
+ l2->vdd_mem,
+ bw / 1000000);
+
+ /* Core voltage information */
+ seq_printf(m, "%8d %7d %3d\n",
+ level->vdd_core,
+ level->ua_core,
+ level->avsdscr_setting);
+ }
+
+ return 0;
+}
+
+static int acpu_table_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpu_table_show, inode->i_private);
+}
+
+static const struct file_operations acpu_table_fops = {
+ .open = acpu_table_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static void __cpuinit add_scalable_dir(int sc_id)
{
char sc_name[8];
@@ -326,6 +376,8 @@
&speed_bin_fops);
debugfs_create_file("pvs_bin", S_IRUGO, base_dir, NULL, &pvs_bin_fops);
debugfs_create_file("boost_uv", S_IRUGO, base_dir, NULL, &boost_fops);
+ debugfs_create_file("acpu_table", S_IRUGO, base_dir, NULL,
+ &acpu_table_fops);
for_each_online_cpu(cpu)
add_scalable_dir(cpu);
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 9566cea..a6f4423 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -44,8 +44,6 @@
#define PRI_SRC_SEL_HFPLL 1
#define PRI_SRC_SEL_HFPLL_DIV2 2
-#define SECCLKAGD BIT(4)
-
static DEFINE_MUTEX(driver_lock);
static DEFINE_SPINLOCK(l2_lock);
@@ -75,20 +73,10 @@
{
u32 regval;
- /* 8064 Errata: disable sec_src clock gating during switch. */
regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
- regval |= SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* Program the MUX */
regval &= ~(0x3 << 2);
regval |= ((sec_src_sel & 0x3) << 2);
set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
- /* 8064 Errata: re-enabled sec_src clock gating. */
- regval &= ~SECCLKAGD;
- set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
/* Wait for switch to complete. */
mb();
udelay(1);
@@ -620,9 +608,8 @@
writel_relaxed(drv.hfpll_data->droop_val,
sc->hfpll_base + drv.hfpll_data->droop_offset);
- /* Set an initial rate and enable the PLL. */
+ /* Set an initial PLL rate. */
hfpll_set_rate(sc, tgt_s);
- hfpll_enable(sc, false);
}
static int __cpuinit rpm_regulator_init(struct scalable *sc, enum vregs vreg,
@@ -793,7 +780,9 @@
regval &= ~(0x3 << 6);
set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
- /* Switch to the target clock source. */
+ /* Enable and switch to the target clock source. */
+ if (tgt_s->src == HFPLL)
+ hfpll_enable(sc, false);
set_pri_clk_src(sc, tgt_s->pri_src_sel);
sc->cur_speed = tgt_s;
@@ -922,11 +911,12 @@
static void __init cpufreq_table_init(void)
{
int cpu;
+ int freq_cnt = 0;
for_each_possible_cpu(cpu) {
- int i, freq_cnt = 0;
+ int i;
/* Construct the freq_table tables from acpu_freq_tbl. */
- for (i = 0; drv.acpu_freq_tbl[i].speed.khz != 0
+ for (i = 0, freq_cnt = 0; drv.acpu_freq_tbl[i].speed.khz != 0
&& freq_cnt < ARRAY_SIZE(*freq_table); i++) {
if (drv.acpu_freq_tbl[i].use_for_scaling) {
freq_table[cpu][freq_cnt].index = freq_cnt;
@@ -941,12 +931,11 @@
freq_table[cpu][freq_cnt].index = freq_cnt;
freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
- dev_info(drv.dev, "CPU%d: %d frequencies supported\n",
- cpu, freq_cnt);
-
/* Register table with CPUFreq. */
cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
}
+
+ dev_info(drv.dev, "CPU Frequencies Supported: %d\n", freq_cnt);
}
#else
static void __init cpufreq_table_init(void) {}
diff --git a/arch/arm/mach-msm/audio-7627a-devices.c b/arch/arm/mach-msm/audio-7627a-devices.c
index 61d06e7..95727de 100644
--- a/arch/arm/mach-msm/audio-7627a-devices.c
+++ b/arch/arm/mach-msm/audio-7627a-devices.c
@@ -13,7 +13,6 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
-#include <linux/android_pmem.h>
#include <mach/board.h>
#include "board-msm7627a.h"
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 48abd35..42bde8f 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1887,7 +1887,7 @@
static struct gpiomux_setting mdm2ap_status_gpio_run_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
};
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index e8e75df..819ca56 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -90,6 +90,18 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting wcnss_5wire_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting gpio_i2c_config = {
.func = GPIOMUX_FUNC_3,
.drv = GPIOMUX_DRV_2MA,
@@ -239,6 +251,152 @@
},
};
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+ {
+ .gpio = 40,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 41,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 42,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 43,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 44,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+};
+
+static struct gpiomux_setting gpio_suspend_config[] = {
+ {
+ .func = GPIOMUX_FUNC_GPIO, /* IN-NP */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+ {
+ .func = GPIOMUX_FUNC_GPIO, /* O-LOW */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+ },
+};
+
+static struct gpiomux_setting cam_settings[] = {
+ {
+ .func = GPIOMUX_FUNC_1, /*active 1*/ /* 0 */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*suspend*/ /* 1 */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*i2c suspend*/ /* 2 */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*active 0*/ /* 3 */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_GPIO, /*suspend 0*/ /* 4 */
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+};
+
+
+static struct msm_gpiomux_config msm_sensor_configs[] __initdata = {
+ {
+ .gpio = 26, /* CAM_MCLK0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 27, /* CAM_MCLK1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+
+ },
+ {
+ .gpio = 29, /* CCI_I2C_SDA0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 30, /* CCI_I2C_SCL0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 36, /* CAM1_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 37, /* CAM1_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 35, /* CAM2_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 28, /* CAM2_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+
+};
+
void __init msm8226_init_gpiomux(void)
{
int rc;
@@ -256,10 +414,13 @@
ARRAY_SIZE(msm_keypad_configs));
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+ msm_gpiomux_install(wcnss_5wire_interface,
+ ARRAY_SIZE(wcnss_5wire_interface));
msm_gpiomux_install(&sd_card_det, 1);
msm_gpiomux_install(msm_synaptics_configs,
ARRAY_SIZE(msm_synaptics_configs));
msm_gpiomux_install_nowrite(msm_lcd_configs,
ARRAY_SIZE(msm_lcd_configs));
+ msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
}
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index dcab9ca..872fabe 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -24,9 +24,6 @@
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/memory.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
#include <linux/regulator/qpnp-regulator.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 2723e20..5f5366f 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -49,6 +49,7 @@
#include "platsmp.h"
#include "spm.h"
#include "lpm_resources.h"
+#include "modem_notifier.h"
static struct memtype_reserve msm8610_reserve_table[] __initdata = {
[MEMTYPE_SMI] = {
@@ -94,6 +95,8 @@
void __init msm8610_add_drivers(void)
{
+ msm_init_modem_notifier_list();
+ msm_smd_init();
msm_rpm_driver_init();
msm_lpmrs_module_init();
msm_spm_device_init();
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 1aa7508..bf8f895 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -243,25 +243,25 @@
static struct gpiomux_setting ap2mdm_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_4MA,
.pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting mdm2ap_status_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
};
static struct gpiomux_setting mdm2ap_errfatal_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_16MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting ap2mdm_kpdpwr_n_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_4MA,
.pull = GPIOMUX_PULL_DOWN,
};
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index f864583..e624e3f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -20,9 +20,6 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/memory.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
#include <linux/regulator/machine.h>
#include <linux/regulator/krait-regulator.h>
#include <linux/msm_thermal.h>
@@ -126,6 +123,14 @@
"msm_sdcc.3", NULL),
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98E4000, \
"msm_sdcc.4", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
+ "msm_sdcc.1", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+ "msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+ "msm_sdcc.3", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98E4900, \
+ "msm_sdcc.4", NULL),
OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
"msm_rng", NULL),
OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 1b76441..75aaaec 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -276,6 +276,57 @@
},
};
+static struct gpiomux_setting qpic_lcdc_a_d = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_10MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting qpic_lcdc_cs = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_10MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting qpic_lcdc_rs = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_10MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting qpic_lcdc_te = {
+ .func = GPIOMUX_FUNC_7,
+ .drv = GPIOMUX_DRV_10MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm9625_qpic_lcdc_configs[] __initdata = {
+ {
+ .gpio = 20, /* a_d */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &qpic_lcdc_a_d,
+ },
+ },
+ {
+ .gpio = 21, /* cs */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &qpic_lcdc_cs,
+ },
+ },
+ {
+ .gpio = 22, /* te */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &qpic_lcdc_te,
+ },
+ },
+ {
+ .gpio = 23, /* rs */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &qpic_lcdc_rs,
+ },
+ },
+};
+
void __init msm9625_init_gpiomux(void)
{
int rc;
@@ -296,4 +347,7 @@
ARRAY_SIZE(mdm9625_cdc_reset_config));
msm_gpiomux_install(sdc2_card_det_config,
ARRAY_SIZE(sdc2_card_det_config));
+ msm_gpiomux_install(msm9625_qpic_lcdc_configs,
+ ARRAY_SIZE(msm9625_qpic_lcdc_configs));
+
}
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index 5f0d75f..cca38b0 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -54,7 +54,6 @@
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/i2c.h>
-#include <linux/android_pmem.h>
#include <mach/camera.h>
#ifdef CONFIG_USB_G_ANDROID
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 0654a0d..be3c1a3 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -39,7 +39,6 @@
#include <linux/msm_adc.h>
#include <linux/dma-mapping.h>
#include <linux/regulator/consumer.h>
-
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
@@ -54,7 +53,6 @@
#include <mach/msm_spi.h>
#include <mach/qdsp5v2/msm_lpa.h>
#include <mach/dma.h>
-#include <linux/android_pmem.h>
#include <linux/input/msm_ts.h>
#include <mach/pmic.h>
#include <mach/rpc_pmapp.h>
@@ -3531,19 +3529,6 @@
}
#endif
-static struct android_pmem_platform_data android_pmem_pdata = {
- .name = "pmem",
- .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
- .cached = 1,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = { .platform_data = &android_pmem_pdata },
-};
-
#ifndef CONFIG_SPI_QSD
static int lcdc_gpio_array_num[] = {
45, /* spi_clk */
@@ -4021,32 +4006,6 @@
.id = -1,
};
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
- .name = "pmem_adsp",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
- .name = "pmem_audio",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI0,
-};
-
-static struct platform_device android_pmem_adsp_device = {
- .name = "android_pmem",
- .id = 2,
- .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct platform_device android_pmem_audio_device = {
- .name = "android_pmem",
- .id = 4,
- .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -5395,7 +5354,6 @@
#ifdef CONFIG_I2C_SSBI
&msm_device_ssbi7,
#endif
- &android_pmem_device,
&msm_fb_device,
#ifdef CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE
&msm_v4l2_video_overlay_device,
@@ -5407,8 +5365,6 @@
&msm_rotator_device,
#endif
&lcdc_sharp_panel_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
&msm_device_i2c,
&msm_device_i2c_2,
&msm_device_uart_dm1,
@@ -7234,39 +7190,6 @@
#endif
}
-static void __init size_pmem_devices(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-
- android_pmem_adsp_pdata.size = size;
- android_pmem_audio_pdata.size = pmem_audio_size;
- android_pmem_pdata.size = pmem_sf_size;
-#endif
-#endif
-}
-
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
- msm7x30_reserve_table[p->memory_type].size += p->size;
-}
-#endif
-#endif
-
-static void __init reserve_pmem_memory(void)
-{
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
- reserve_memory_for(&android_pmem_pdata);
- msm7x30_reserve_table[MEMTYPE_EBI0].size += pmem_kernel_ebi0_size;
-#endif
-#endif
-}
-
static void __init reserve_mdp_memory(void)
{
mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
@@ -7294,8 +7217,6 @@
static void __init msm7x30_calculate_reserve_sizes(void)
{
fix_sizes();
- size_pmem_devices();
- reserve_pmem_memory();
reserve_mdp_memory();
size_ion_devices();
reserve_ion_memory();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 02a753a..6b98393 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -41,10 +41,6 @@
#include <linux/dma-mapping.h>
#include <linux/i2c/bq27520.h>
-#ifdef CONFIG_ANDROID_PMEM
-#include <linux/android_pmem.h>
-#endif
-
#if defined(CONFIG_SMB137B_CHARGER) || defined(CONFIG_SMB137B_CHARGER_MODULE)
#include <linux/i2c/smb137b.h>
#endif
@@ -2808,47 +2804,6 @@
.dev.platform_data = &msm_fb_pdata,
};
-#ifdef CONFIG_ANDROID_PMEM
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct android_pmem_platform_data android_pmem_pdata = {
- .name = "pmem",
- .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
- .cached = 1,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = {.platform_data = &android_pmem_pdata},
-};
-
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
- .name = "pmem_adsp",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
- .name = "android_pmem",
- .id = 2,
- .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
- .name = "pmem_audio",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
- .name = "android_pmem",
- .id = 4,
- .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#define PMEM_BUS_WIDTH(_bw) \
{ \
.vectors = &(struct msm_bus_vectors){ \
@@ -2891,6 +2846,49 @@
{
return (void *)msm_bus_scale_register_client(&smi_client_pdata);
}
+
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
+static struct android_pmem_platform_data android_pmem_pdata = {
+ .name = "pmem",
+ .allocator_type = PMEM_ALLOCATORTYPE_ALLORNOTHING,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = {.platform_data = &android_pmem_pdata},
+};
+
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+ .name = "pmem_audio",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+ .name = "android_pmem",
+ .id = 4,
+ .dev = { .platform_data = &android_pmem_audio_pdata },
+};
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct android_pmem_platform_data android_pmem_smipool_pdata = {
.name = "pmem_smipool",
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index c823c39..413927c 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -169,22 +169,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -1358,17 +1350,6 @@
},
};
-static struct branch_clk gcc_noc_conf_xpu_ahb_clk = {
- .cbcr_reg = NOC_CONF_XPU_AHB_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[GCC_BASE],
- .c = {
- .dbg_name = "gcc_noc_conf_xpu_ahb_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(gcc_noc_conf_xpu_ahb_clk.c),
- },
-};
-
static struct branch_clk gcc_pdm2_clk = {
.cbcr_reg = PDM2_CBCR,
.has_sibling = 0,
@@ -1582,7 +1563,6 @@
static struct measure_mux_entry measure_mux_GCC[] = {
{ &gcc_periph_noc_ahb_clk.c, GCC_BASE, 0x0010 },
- { &gcc_noc_conf_xpu_ahb_clk.c, GCC_BASE, 0x0018 },
{ &gcc_mss_cfg_ahb_clk.c, GCC_BASE, 0x0030 },
{ &gcc_mss_q6_bimc_axi_clk.c, GCC_BASE, 0x0031 },
{ &gcc_usb_hsic_ahb_clk.c, GCC_BASE, 0x0058 },
@@ -1668,7 +1648,7 @@
F_MMSS( 100000000, gpll0, 6, 0, 0),
F_MMSS( 150000000, gpll0, 4, 0, 0),
F_MMSS( 200000000, mmpll0_pll, 4, 0, 0),
- F_MMSS( 266000000, mmpll0_pll, 3, 0, 0),
+ F_MMSS( 266666666, mmpll0_pll, 3, 0, 0),
F_END
};
@@ -1820,14 +1800,17 @@
CLK_INIT(dsipll0_pixel_clk_src),
};
-static struct clk_freq_tbl pixel_freq = {
- .src_clk = &dsipll0_pixel_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
+static struct clk_freq_tbl pixel_freq_tbl[] = {
+ {
+ .src_clk = &dsipll0_pixel_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
+ },
+ F_END
};
static struct rcg_clk pclk0_clk_src = {
.cmd_rcgr_reg = PCLK0_CMD_RCGR,
- .current_freq = &pixel_freq,
+ .current_freq = pixel_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_pixel_clk_src,
@@ -1919,6 +1902,8 @@
};
static struct clk_freq_tbl ftbl_camss_mclk0_1_clk[] = {
+ F_MMSS( 19200000, xo, 1, 0, 0),
+ F_MMSS( 24000000, gpll0, 5, 1, 5),
F_MMSS( 66670000, gpll0, 9, 0, 0),
F_END
};
@@ -2007,14 +1992,17 @@
},
};
-static struct clk_freq_tbl byte_freq = {
- .src_clk = &dsipll0_byte_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+static struct clk_freq_tbl byte_freq_tbl[] = {
+ {
+ .src_clk = &dsipll0_byte_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+ },
+ F_END
};
static struct rcg_clk byte0_clk_src = {
.cmd_rcgr_reg = BYTE0_CMD_RCGR,
- .current_freq = &byte_freq,
+ .current_freq = byte_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_byte_clk_src,
@@ -2752,19 +2740,12 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
+static const int *vdd_sr2_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -2824,6 +2805,13 @@
static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_lpass_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_mss_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_wlan_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_pil_pronto_clk, &xo.c);
+
+
#ifdef CONFIG_DEBUG_FS
static int measure_clk_set_parent(struct clk *c, struct clk *parent)
{
@@ -3034,20 +3022,20 @@
CLK_LOOKUP("l2_m_clk", l2_m_clk, ""),
/* PIL-LPASS */
- CLK_LOOKUP("xo", xo.c, "fe200000.qcom,lpass"),
+ CLK_LOOKUP("xo", cxo_pil_lpass_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("reg_clk", q6ss_ahbm_clk.c, "fe200000.qcom,lpass"),
/* PIL-MODEM */
- CLK_LOOKUP("xo", xo.c, "fc880000.qcom,mss"),
+ CLK_LOOKUP("xo", cxo_pil_mss_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "fc880000.qcom,mss"),
/* PIL-PRONTO */
- CLK_LOOKUP("xo", xo.c, "fb21b000.qcom,pronto"),
+ CLK_LOOKUP("xo", cxo_pil_pronto_clk.c, "fb21b000.qcom,pronto"),
/* PIL-VENUS */
CLK_LOOKUP("src_clk", vcodec0_clk_src.c, "fdce0000.qcom,venus"),
@@ -3062,7 +3050,8 @@
CLK_LOOKUP("a7sspll", a7sspll.c, "f9011050.qcom,acpuclk"),
/* WCNSS CLOCKS */
- CLK_LOOKUP("xo", xo.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("xo", cxo_wlan_clk.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("rf_clk", cxo_a2.c, "fb000000.qcom,wcnss-wlan"),
/* BUS DRIVER */
CLK_LOOKUP("bus_clk", cnoc_msmbus_clk.c, "msm_config_noc"),
@@ -3147,7 +3136,7 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
/* HSUSB-OTG Clocks */
- CLK_LOOKUP("xo", xo.c, "f9a55000.usb"),
+ CLK_LOOKUP("xo", cxo_otg_clk.c, "f9a55000.usb"),
CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "f9a55000.usb"),
CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "f9a55000.usb"),
@@ -3179,6 +3168,11 @@
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
+ CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "scm"),
+ CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "scm"),
+ CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "scm"),
+ CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "scm"),
+
/* SDCC */
CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "f9824000.qcom,sdcc"),
CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "f9824000.qcom,sdcc"),
@@ -3262,10 +3256,12 @@
CLK_LOOKUP("core_clk", mdss_axi_clk.c, "fd928000.qcom,iommu"),
/* MM sensor clocks */
- CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
/* CCI clocks */
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
@@ -3357,6 +3353,19 @@
CLK_LOOKUP("core_clk", camss_jpeg_jpeg_axi_clk.c,
"fda64000.qcom,iommu"),
+ CLK_LOOKUP("micro_iface_clk", camss_micro_ahb_clk.c,
+ "fda04000.qcom,cpp"),
+ CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+ "fda04000.qcom,cpp"),
+ CLK_LOOKUP("cpp_iface_clk", camss_vfe_cpp_ahb_clk.c,
+ "fda04000.qcom,cpp"),
+ CLK_LOOKUP("cpp_core_clk", camss_vfe_cpp_clk.c, "fda04000.qcom,cpp"),
+ CLK_LOOKUP("cpp_bus_clk", camss_vfe_vfe_axi_clk.c, "fda04000.qcom,cpp"),
+ CLK_LOOKUP("vfe_clk_src", vfe0_clk_src.c, "fda04000.qcom,cpp"),
+ CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
+ "fda04000.qcom,cpp"),
+ CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda04000.qcom,cpp"),
+
/* KGSL Clocks */
CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fdb00000.qcom,kgsl-3d0"),
CLK_LOOKUP("iface_clk", oxilicx_ahb_clk.c, "fdb00000.qcom,kgsl-3d0"),
@@ -3432,6 +3441,12 @@
static void __init msm8226_clock_post_init(void)
{
+ /*
+ * Hold an active set vote for CXO; this is because CXO is expected
+ * to remain on whenever CPUs aren't power collapsed.
+ */
+ clk_prepare_enable(&xo_a_clk.c);
+
/* Set rates for single-rate clocks. */
clk_set_rate(&usb_hs_system_clk_src.c,
usb_hs_system_clk_src.freq_tbl[0].freq_hz);
@@ -3491,23 +3506,23 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8226: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_dig_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8226: Unable to get the sr2_pll regulator!");
/*
* These regulators are used at boot. Ensure they stay on
* while the clock framework comes online.
*/
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
/*
* Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
@@ -3517,11 +3532,8 @@
*/
clk_set_rate(&mmssnoc_ahb_a_clk.c, 40000000);
- /*
- * Hold an active set vote for CXO; this is because CXO is expected
- * to remain on whenever CPUs aren't power collapsed.
- */
- clk_prepare_enable(&xo_a_clk.c);
+ /* Set an initial rate (fmax at nominal) on the MMSSNOC AXI clock */
+ clk_set_rate(&axi_clk_src.c, 200000000);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 0aee878..a645e9c 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -445,22 +445,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -550,20 +542,13 @@
VDD_SR2_PLL_NUM
};
-static struct regulator *vdd_sr2_reg;
+static const int *vdd_sr2_pll_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0),
+ [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+};
-static int set_vdd_sr2_pll(struct clk_vdd_class *vdd_class, int level)
-{
- if (level == VDD_SR2_PLL_ON) {
- return regulator_set_voltage(vdd_sr2_reg, 1800000,
- 1800000);
- } else {
- return regulator_set_voltage(vdd_sr2_reg, 0, 1800000);
- }
-}
-
-static DEFINE_VDD_CLASS(vdd_sr2_pll, set_vdd_sr2_pll,
- VDD_SR2_PLL_NUM);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
+ vdd_sr2_pll_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -3016,7 +3001,12 @@
static struct clk_lookup msm_clocks_8610[] = {
CLK_LOOKUP("xo", gcc_xo_clk_src.c, "msm_otg"),
CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fe200000.qcom,lpass"),
- CLK_LOOKUP("xo", gcc_xo_clk_src.c, "pil-q6v5-mss"),
+
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fc880000.qcom,mss"),
+ CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
+ CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "fc880000.qcom,mss"),
+ CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "fc880000.qcom,mss"),
+
CLK_LOOKUP("xo", gcc_xo_clk_src.c, "pil-mba"),
CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fb000000.qcom,wcnss-wlan"),
CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fb21b000.qcom,pronto"),
@@ -3046,6 +3036,8 @@
CLK_LOOKUP("mem_clk", bimc_msmbus_clk.c, "msm_bimc"),
CLK_LOOKUP("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc"),
CLK_LOOKUP("mem_clk", bimc_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmss_s0_axi_clk.c, "msm_mmss_noc"),
+ CLK_LOOKUP("bus_a_clk", mmss_s0_axi_clk.c, "msm_mmss_noc"),
/* CoreSight clocks */
CLK_LOOKUP("core_clk", qdss_clk.c, "fc326000.tmc"),
@@ -3541,16 +3533,16 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8610: Unable to get the vdd_dig regulator!");
- vdd_sr2_reg = regulator_get(NULL, "vdd_sr2_pll");
- if (IS_ERR(vdd_sr2_reg))
+ vdd_sr2_pll.regulator[0] = regulator_get(NULL, "vdd_sr2_pll");
+ if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
- regulator_set_voltage(vdd_sr2_reg, 1800000, 1800000);
- regulator_enable(vdd_sr2_reg);
+ regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ regulator_enable(vdd_sr2_pll.regulator[0]);
/*
* TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3559,7 +3551,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 0657c21..e6874b7 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/iopoll.h>
+#include <linux/regulator/consumer.h>
#include <mach/rpm-regulator-smd.h>
#include <mach/socinfo.h>
@@ -637,22 +638,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct rpm_regulator *vdd_dig_reg;
-
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return rpm_regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
#define RPM_MISC_CLK_TYPE 0x306b6c63
#define RPM_BUS_CLK_TYPE 0x316b6c63
@@ -714,6 +707,7 @@
static struct pll_vote_clk gpll0_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.base = &virt_bases[GCC_BASE],
@@ -3026,14 +3020,17 @@
CLK_INIT(dsipll0_pixel_clk_src),
};
-static struct clk_freq_tbl byte_freq = {
- .src_clk = &dsipll0_byte_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+static struct clk_freq_tbl byte_freq_tbl[] = {
+ {
+ .src_clk = &dsipll0_byte_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+ },
+ F_END
};
static struct rcg_clk byte0_clk_src = {
.cmd_rcgr_reg = BYTE0_CMD_RCGR,
- .current_freq = &byte_freq,
+ .current_freq = byte_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_byte_clk_src,
@@ -3047,7 +3044,7 @@
static struct rcg_clk byte1_clk_src = {
.cmd_rcgr_reg = BYTE1_CMD_RCGR,
- .current_freq = &byte_freq,
+ .current_freq = byte_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_byte_clk_src,
@@ -3228,14 +3225,17 @@
},
};
-static struct clk_freq_tbl pixel_freq = {
- .src_clk = &dsipll0_pixel_clk_src,
- .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
+static struct clk_freq_tbl pixel_freq_tbl[] = {
+ {
+ .src_clk = &dsipll0_pixel_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_pixel_mm_source_val),
+ },
+ F_END
};
static struct rcg_clk pclk0_clk_src = {
.cmd_rcgr_reg = PCLK0_CMD_RCGR,
- .current_freq = &pixel_freq,
+ .current_freq = pixel_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_pixel_clk_src,
@@ -3248,7 +3248,7 @@
static struct rcg_clk pclk1_clk_src = {
.cmd_rcgr_reg = PCLK1_CMD_RCGR,
- .current_freq = &pixel_freq,
+ .current_freq = pixel_freq_tbl,
.base = &virt_bases[MMSS_BASE],
.c = {
.parent = &dsipll0_pixel_clk_src,
@@ -4739,6 +4739,7 @@
CLK_LOOKUP("xo", cxo_pil_lpass_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("xo", cxo_pil_mss_clk.c, "fc880000.qcom,mss"),
CLK_LOOKUP("xo", cxo_wlan_clk.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("rf_clk", cxo_a2.c, "fb000000.qcom,wcnss-wlan"),
CLK_LOOKUP("xo", cxo_pil_pronto_clk.c, "fb21b000.qcom,pronto"),
CLK_LOOKUP("xo", cxo_dwc3_clk.c, "msm_dwc3"),
CLK_LOOKUP("xo", cxo_ehci_host_clk.c, "msm_ehci_host"),
@@ -4815,6 +4816,11 @@
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
+ CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "scm"),
+ CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "scm"),
+ CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "scm"),
+ CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "scm"),
+
CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
@@ -5477,8 +5483,8 @@
clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
- vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5488,7 +5494,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- rpm_regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
@@ -5543,8 +5549,8 @@
sdcc3_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
sdcc4_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
- vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
@@ -5554,7 +5560,7 @@
* its necessity.
*/
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- rpm_regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
}
struct clock_init_data msm8974_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 9648320..d8e4ed5 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -278,22 +278,14 @@
VDD_DIG_NUM
};
-static const int vdd_corner[] = {
- [VDD_DIG_NONE] = RPM_REGULATOR_CORNER_NONE,
- [VDD_DIG_LOW] = RPM_REGULATOR_CORNER_SVS_SOC,
- [VDD_DIG_NOMINAL] = RPM_REGULATOR_CORNER_NORMAL,
- [VDD_DIG_HIGH] = RPM_REGULATOR_CORNER_SUPER_TURBO,
+static const int *vdd_corner[] = {
+ [VDD_DIG_NONE] = VDD_UV(RPM_REGULATOR_CORNER_NONE),
+ [VDD_DIG_LOW] = VDD_UV(RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_DIG_NOMINAL] = VDD_UV(RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_DIG_HIGH] = VDD_UV(RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static struct regulator *vdd_dig_reg;
-
-int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
- return regulator_set_voltage(vdd_dig_reg, vdd_corner[level],
- RPM_REGULATOR_CORNER_SUPER_TURBO);
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig, VDD_DIG_NUM);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
/* TODO: Needs to confirm the below values */
#define RPM_MISC_CLK_TYPE 0x306b6c63
@@ -344,6 +336,7 @@
static struct pll_vote_clk gpll0_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.soft_vote = &soft_vote_gpll0,
@@ -360,6 +353,7 @@
static struct pll_vote_clk gpll0_activeonly_clk_src = {
.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
+ .en_mask = BIT(0),
.status_reg = (void __iomem *)GPLL0_STATUS_REG,
.status_mask = BIT(17),
.soft_vote = &soft_vote_gpll0,
@@ -2060,12 +2054,12 @@
clk_ops_local_pll.enable = sr_pll_clk_enable_9625;
- vdd_dig_reg = regulator_get(NULL, "vdd_dig");
- if (IS_ERR(vdd_dig_reg))
+ vdd_dig.regulator[0] = regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-9625: Unable to get the vdd_dig regulator!");
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig_reg);
+ regulator_enable(vdd_dig.regulator[0]);
enable_rpm_scaling();
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index a173ba9..5da1663 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -560,7 +560,11 @@
return to_rcg_clk(c)->enabled;
}
-/* Return a supported rate that's at least the specified rate. */
+/*
+ * Return a supported rate that's at least the specified rate or
+ * the max supported rate if the specified rate is larger than the
+ * max supported rate.
+ */
static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *rcg = to_rcg_clk(c);
@@ -570,7 +574,8 @@
if (f->freq_hz >= rate)
return f->freq_hz;
- return -EPERM;
+ f--;
+ return f->freq_hz;
}
/* Return the nth supported frequency for a given clock. */
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index c3b4ca7..8bdc496 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -32,7 +32,7 @@
* When enabling/disabling a clock, check the halt bit up to this number
* number of times (with a 1 us delay in between) before continuing.
*/
-#define HALT_CHECK_MAX_LOOPS 200
+#define HALT_CHECK_MAX_LOOPS 500
/* For clock without halt checking, wait this long after enables/disables. */
#define HALT_CHECK_DELAY_US 10
@@ -40,7 +40,7 @@
* When updating an RCG configuration, check the update bit up to this number
* number of times (with a 1 us delay in between) before continuing.
*/
-#define UPDATE_CHECK_MAX_LOOPS 200
+#define UPDATE_CHECK_MAX_LOOPS 500
DEFINE_SPINLOCK(local_clock_reg_lock);
struct clk_freq_tbl rcg_dummy_freq = F_END;
@@ -211,7 +211,11 @@
return 0;
}
-/* Return a supported rate that's at least the specified rate. */
+/*
+ * Return a supported rate that's at least the specified rate or
+ * the max supported rate if the specified rate is larger than the
+ * max supported rate.
+ */
static long rcg_clk_round_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *rcg = to_rcg_clk(c);
@@ -221,7 +225,8 @@
if (f->freq_hz >= rate)
return f->freq_hz;
- return -EPERM;
+ f--;
+ return f->freq_hz;
}
/* Return the nth supported frequency for a given clock. */
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 51d895a..13041b1 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -80,12 +80,14 @@
struct clk *parent;
struct clk_voter *v = to_clk_voter(clk);
- if (v->is_branch)
- return 0;
-
mutex_lock(&voter_clk_lock);
parent = clk->parent;
+ if (v->is_branch) {
+ v->enabled = true;
+ goto out;
+ }
+
/*
* Increase the rate if this clock is voting for a higher rate
* than the current rate.
@@ -109,8 +111,6 @@
struct clk *parent;
struct clk_voter *v = to_clk_voter(clk);
- if (v->is_branch)
- return;
mutex_lock(&voter_clk_lock);
parent = clk->parent;
@@ -120,12 +120,16 @@
* the highest rate.
*/
v->enabled = false;
+ if (v->is_branch)
+ goto out;
+
new_rate = voter_clk_aggregate_rate(parent);
cur_rate = max(new_rate, clk->rate);
if (new_rate < cur_rate)
clk_set_rate(parent, new_rate);
+out:
mutex_unlock(&voter_clk_lock);
}
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index e0ee084..ecd25fc 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -22,6 +22,7 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/list.h>
+#include <linux/regulator/consumer.h>
#include <trace/events/power.h>
#include <mach/clk-provider.h>
#include "clock.h"
@@ -53,20 +54,39 @@
/* Update voltage level given the current votes. */
static int update_vdd(struct clk_vdd_class *vdd_class)
{
- int level, rc;
+ int level, rc = 0, i;
+ struct regulator **r = vdd_class->regulator;
+ const int **vdd_uv = vdd_class->vdd_uv;
+ int max_level = vdd_class->num_levels - 1;
- for (level = vdd_class->num_levels-1; level > 0; level--)
+ for (level = max_level; level > 0; level--)
if (vdd_class->level_votes[level])
break;
if (level == vdd_class->cur_level)
return 0;
- rc = vdd_class->set_vdd(vdd_class, level);
+ for (i = 0; i < vdd_class->num_regulators; i++) {
+ rc = regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+ if (rc)
+ goto set_voltage_fail;
+ }
+ if (vdd_class->set_vdd && !vdd_class->num_regulators)
+ rc = vdd_class->set_vdd(vdd_class, level);
+
if (!rc)
vdd_class->cur_level = level;
return rc;
+
+set_voltage_fail:
+ level = vdd_class->cur_level;
+ for (i--; i >= 0; i--)
+ regulator_set_voltage(r[i], vdd_uv[level][i],
+ vdd_uv[max_level][i]);
+
+ return rc;
}
/* Vote for a voltage level. */
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
new file mode 100644
index 0000000..4e95e4e
--- /dev/null
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/cpr-regulator.h>
+
+struct cpr_regulator {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+ bool enabled;
+ int corner;
+
+ /* Process voltage parameters */
+ phys_addr_t efuse_phys;
+ u32 num_efuse_bits;
+ u32 efuse_bit_pos[CPR_PVS_EFUSE_BITS_MAX];
+ u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
+ u32 pvs_corner_ceiling[NUM_APC_PVS][CPR_CORNER_MAX];
+ /* Process voltage variables */
+ u32 pvs_bin;
+ u32 pvs_process;
+ u32 *process_vmax;
+
+ /* APC voltage regulator */
+ struct regulator *vdd_apc;
+};
+
+static int cpr_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
+
+ return cpr_vreg->enabled;
+}
+
+static int cpr_regulator_enable(struct regulator_dev *rdev)
+{
+ struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = regulator_enable(cpr_vreg->vdd_apc);
+ if (!rc)
+ cpr_vreg->enabled = true;
+ return rc;
+}
+
+static int cpr_regulator_disable(struct regulator_dev *rdev)
+{
+ struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = regulator_disable(cpr_vreg->vdd_apc);
+ if (!rc)
+ cpr_vreg->enabled = false;
+ return rc;
+}
+
+static int cpr_regulator_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
+ int rc;
+ int vdd_apc_min, vdd_apc_max;
+
+ vdd_apc_min = cpr_vreg->process_vmax[min_uV];
+ vdd_apc_max = cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO];
+ rc = regulator_set_voltage(cpr_vreg->vdd_apc,
+ vdd_apc_min, vdd_apc_max);
+ if (!rc)
+ cpr_vreg->corner = min_uV;
+
+ pr_debug("set [corner:%d] = %d uV: rc=%d\n", min_uV, vdd_apc_min, rc);
+ return rc;
+}
+
+static int cpr_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
+
+ return cpr_vreg->corner;
+}
+
+static struct regulator_ops cpr_corner_ops = {
+ .enable = cpr_regulator_enable,
+ .disable = cpr_regulator_disable,
+ .is_enabled = cpr_regulator_is_enabled,
+ .set_voltage = cpr_regulator_set_voltage,
+ .get_voltage = cpr_regulator_get_voltage,
+};
+
+static int __init cpr_regulator_pvs_init(struct cpr_regulator *cpr_vreg)
+{
+ void __iomem *efuse_base;
+ u32 efuse_bits;
+ int i, bit_pos;
+ u32 vmax;
+
+ efuse_base = ioremap(cpr_vreg->efuse_phys, 4);
+ if (!efuse_base) {
+ pr_err("Unable to map efuse_phys 0x%x\n",
+ cpr_vreg->efuse_phys);
+ return -EINVAL;
+ }
+
+ efuse_bits = readl_relaxed(efuse_base);
+
+ /* Construct PVS process # from the efuse bits */
+ for (i = 0; i < cpr_vreg->num_efuse_bits; i++) {
+ bit_pos = cpr_vreg->efuse_bit_pos[i];
+ cpr_vreg->pvs_bin |= (efuse_bits & BIT(bit_pos)) ? BIT(i) : 0;
+ }
+
+ cpr_vreg->pvs_process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
+ if (cpr_vreg->pvs_process >= NUM_APC_PVS)
+ cpr_vreg->pvs_process = APC_PVS_NO;
+
+ /* Use ceiling voltage of Turbo@Slow for all corners of APC_PVS_NO
+ but use SuperTurbo@Slow for its SuperTurbo */
+ vmax = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_TURBO];
+ for (i = CPR_CORNER_SVS; i <= CPR_CORNER_TURBO; i++)
+ cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][i] = vmax;
+ cpr_vreg->pvs_corner_ceiling[APC_PVS_NO][CPR_CORNER_SUPER_TURBO]
+ = cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW]
+ [CPR_CORNER_SUPER_TURBO];
+
+ cpr_vreg->process_vmax =
+ cpr_vreg->pvs_corner_ceiling[cpr_vreg->pvs_process];
+
+ iounmap(efuse_base);
+
+ pr_info("PVS Info: efuse_phys=0x%08X, n_bits=%d\n",
+ cpr_vreg->efuse_phys, cpr_vreg->num_efuse_bits);
+ pr_info("PVS Info: efuse=0x%08X, bin=%d, process=%d\n",
+ efuse_bits, cpr_vreg->pvs_bin, cpr_vreg->pvs_process);
+
+ return 0;
+}
+
+static int __init cpr_regulator_apc_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev, "vdd-apc");
+ if (IS_ERR_OR_NULL(cpr_vreg->vdd_apc)) {
+ pr_err("devm_regulator_get: rc=%d\n",
+ (int)PTR_ERR(cpr_vreg->vdd_apc));
+ }
+
+ return PTR_RET(cpr_vreg->vdd_apc);
+}
+
+static void cpr_regulator_apc_exit(struct cpr_regulator *cpr_vreg)
+{
+ if (cpr_vreg->enabled)
+ regulator_disable(cpr_vreg->vdd_apc);
+}
+
+static int __init cpr_regulator_parse_dt(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct device_node *of_node = pdev->dev.of_node;
+ struct resource *res;
+ int rc;
+ size_t pvs_bins;
+
+ /* Parse process voltage parameters */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "efuse_phys");
+ if (!res || !res->start) {
+ pr_err("efuse_phys missing: res=%p\n", res);
+ return -EINVAL;
+ }
+ cpr_vreg->efuse_phys = res->start;
+
+ rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
+ &cpr_vreg->num_efuse_bits);
+ if (rc < 0) {
+ pr_err("num-efuse-bits missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ if (cpr_vreg->num_efuse_bits == 0 ||
+ cpr_vreg->num_efuse_bits > CPR_PVS_EFUSE_BITS_MAX) {
+ pr_err("invalid num-efuse-bits : %d\n",
+ cpr_vreg->num_efuse_bits);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,efuse-bit-pos",
+ cpr_vreg->efuse_bit_pos,
+ cpr_vreg->num_efuse_bits);
+ if (rc < 0) {
+ pr_err("efuse-bit-pos missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ pvs_bins = 1 << cpr_vreg->num_efuse_bits;
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
+ cpr_vreg->pvs_bin_process,
+ pvs_bins);
+ if (rc < 0) {
+ pr_err("pvs-bin-process missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,pvs-corner-ceiling-slow",
+ &cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW][CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("pvs-corner-ceiling-slow missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,pvs-corner-ceiling-nom",
+ &cpr_vreg->pvs_corner_ceiling[APC_PVS_NOM][CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("pvs-corner-ceiling-norm missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,pvs-corner-ceiling-fast",
+ &cpr_vreg->pvs_corner_ceiling[APC_PVS_FAST][CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("pvs-corner-ceiling-fast missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int __devinit cpr_regulator_probe(struct platform_device *pdev)
+{
+ struct cpr_regulator *cpr_vreg;
+ struct regulator_desc *rdesc;
+ struct regulator_init_data *init_data = pdev->dev.platform_data;
+ int rc;
+
+ if (!pdev->dev.of_node) {
+ pr_err("Device tree node is missing\n");
+ return -EINVAL;
+ }
+
+ init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+ if (!init_data) {
+ pr_err("regulator init data is missing\n");
+ return -EINVAL;
+ } else {
+ init_data->constraints.input_uV
+ = init_data->constraints.max_uV;
+ init_data->constraints.valid_ops_mask
+ |= REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS;
+ }
+
+ cpr_vreg = devm_kzalloc(&pdev->dev, sizeof(struct cpr_regulator),
+ GFP_KERNEL);
+ if (!cpr_vreg) {
+ pr_err("Can't allocate cpr_regulator memory\n");
+ return -ENOMEM;
+ }
+
+ rc = cpr_regulator_parse_dt(pdev, cpr_vreg);
+ if (rc) {
+ pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = cpr_regulator_pvs_init(cpr_vreg);
+ if (rc) {
+ pr_err("Initialize PVS wrong: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = cpr_regulator_apc_init(pdev, cpr_vreg);
+ if (rc) {
+ if (rc != -EPROBE_DEFER)
+ pr_err("Initialize APC wrong: rc=%d\n", rc);
+ return rc;
+ }
+
+ rdesc = &cpr_vreg->rdesc;
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+ rdesc->ops = &cpr_corner_ops;
+ rdesc->name = init_data->constraints.name;
+
+ cpr_vreg->rdev = regulator_register(rdesc, &pdev->dev, init_data,
+ cpr_vreg, pdev->dev.of_node);
+ if (IS_ERR(cpr_vreg->rdev)) {
+ rc = PTR_ERR(cpr_vreg->rdev);
+ pr_err("regulator_register failed: rc=%d\n", rc);
+
+ cpr_regulator_apc_exit(cpr_vreg);
+ return rc;
+ }
+
+ platform_set_drvdata(pdev, cpr_vreg);
+
+ pr_info("PVS [%d %d %d %d] uV\n",
+ cpr_vreg->process_vmax[CPR_CORNER_SVS],
+ cpr_vreg->process_vmax[CPR_CORNER_NORMAL],
+ cpr_vreg->process_vmax[CPR_CORNER_TURBO],
+ cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO]);
+
+ return 0;
+}
+
+static int __devexit cpr_regulator_remove(struct platform_device *pdev)
+{
+ struct cpr_regulator *cpr_vreg;
+
+ cpr_vreg = platform_get_drvdata(pdev);
+ if (cpr_vreg) {
+ cpr_regulator_apc_exit(cpr_vreg);
+ regulator_unregister(cpr_vreg->rdev);
+ }
+
+ return 0;
+}
+
+static struct of_device_id cpr_regulator_match_table[] = {
+ { .compatible = CPR_REGULATOR_DRIVER_NAME, },
+ {}
+};
+
+static struct platform_driver cpr_regulator_driver = {
+ .driver = {
+ .name = CPR_REGULATOR_DRIVER_NAME,
+ .of_match_table = cpr_regulator_match_table,
+ .owner = THIS_MODULE,
+ },
+ .probe = cpr_regulator_probe,
+ .remove = __devexit_p(cpr_regulator_remove),
+};
+
+/**
+ * cpr_regulator_init() - register cpr-regulator driver
+ *
+ * This initialization function should be called in systems in which driver
+ * registration ordering must be controlled precisely.
+ */
+int __init cpr_regulator_init(void)
+{
+ static bool initialized;
+
+ if (initialized)
+ return 0;
+ else
+ initialized = true;
+
+ return platform_driver_register(&cpr_regulator_driver);
+}
+EXPORT_SYMBOL(cpr_regulator_init);
+
+static void __exit cpr_regulator_exit(void)
+{
+ platform_driver_unregister(&cpr_regulator_driver);
+}
+
+MODULE_DESCRIPTION("CPR regulator driver");
+MODULE_LICENSE("GPL v2");
+
+arch_initcall(cpr_regulator_init);
+module_exit(cpr_regulator_exit);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index b7707d7..656c3f4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -3154,6 +3154,7 @@
static struct resource coresight_funnel_resources[] = {
{
+ .name = "funnel-base",
.start = CORESIGHT_FUNNEL_PHYS_BASE,
.end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -3186,6 +3187,7 @@
static struct resource coresight_etm2_resources[] = {
{
+ .name = "etm-base",
.start = CORESIGHT_ETM2_PHYS_BASE,
.end = CORESIGHT_ETM2_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -3218,6 +3220,7 @@
static struct resource coresight_etm3_resources[] = {
{
+ .name = "etm-base",
.start = CORESIGHT_ETM3_PHYS_BASE,
.end = CORESIGHT_ETM3_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 2bd9dfe..d4c33e3 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -21,7 +21,6 @@
#include <asm/clkdev.h>
#include <mach/gpio.h>
#include <mach/kgsl.h>
-#include <linux/android_pmem.h>
#include <mach/irqs-8960.h>
#include <mach/dma.h>
#include <linux/dma-mapping.h>
@@ -4105,6 +4104,7 @@
static struct resource coresight_tpiu_resources[] = {
{
+ .name = "tpiu-base",
.start = CORESIGHT_TPIU_PHYS_BASE,
.end = CORESIGHT_TPIU_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -4130,6 +4130,7 @@
static struct resource coresight_etb_resources[] = {
{
+ .name = "etb-base",
.start = CORESIGHT_ETB_PHYS_BASE,
.end = CORESIGHT_ETB_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -4156,6 +4157,7 @@
static struct resource coresight_funnel_resources[] = {
{
+ .name = "funnel-base",
.start = CORESIGHT_FUNNEL_PHYS_BASE,
.end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -4188,11 +4190,13 @@
static struct resource coresight_stm_resources[] = {
{
+ .name = "stm-base",
.start = CORESIGHT_STM_PHYS_BASE,
.end = CORESIGHT_STM_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "stm-data-base",
.start = CORESIGHT_STM_CHANNEL_PHYS_BASE,
.end = CORESIGHT_STM_CHANNEL_PHYS_BASE + SZ_1M + SZ_512K - 1,
.flags = IORESOURCE_MEM,
@@ -4225,6 +4229,7 @@
static struct resource coresight_etm0_resources[] = {
{
+ .name = "etm-base",
.start = CORESIGHT_ETM0_PHYS_BASE,
.end = CORESIGHT_ETM0_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
@@ -4257,6 +4262,7 @@
static struct resource coresight_etm1_resources[] = {
{
+ .name = "etm-base",
.start = CORESIGHT_ETM1_PHYS_BASE,
.end = CORESIGHT_ETM1_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 5152918..397a9d4 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -18,7 +18,6 @@
#include <linux/msm_rotator.h>
#include <linux/dma-mapping.h>
#include <mach/kgsl.h>
-#include <linux/android_pmem.h>
#include <linux/regulator/machine.h>
#include <linux/init.h>
#include <mach/irqs.h>
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index f9e7863..91a7394 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -45,7 +45,6 @@
#ifdef CONFIG_MSM_DSPS
#include <mach/msm_dsps.h>
#endif
-#include <linux/android_pmem.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <mach/mdm.h>
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 53a6616..6240195 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -33,7 +33,7 @@
/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
#define EN_REST_WAIT_VAL (0x2 << 20)
-#define EN_FEW_WAIT_VAL (0x2 << 16)
+#define EN_FEW_WAIT_VAL (0x8 << 16)
#define CLK_DIS_WAIT_VAL (0x2 << 12)
#define TIMEOUT_US 10
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 4714210..1f7d56a 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -13,7 +13,9 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+#include <linux/io.h>
#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
struct msm_gpiomux_rec {
struct gpiomux_setting *sets[GPIOMUX_NSETTINGS];
@@ -121,6 +123,13 @@
}
EXPORT_SYMBOL(msm_gpiomux_put);
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val)
+{
+ writel_relaxed(val, MSM_TLMM_BASE + misc_reg);
+ /* ensure the write completes before returning */
+ mb();
+}
+
int msm_gpiomux_init(size_t ngpio)
{
if (!ngpio)
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 475b483..528e9d5 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -21,6 +21,7 @@
#include <linux/clkdev.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
#include <mach/clk.h>
/*
@@ -42,14 +43,23 @@
/**
* struct clk_vdd_class - Voltage scaling class
* @class_name: name of the class
- * @set_vdd: function to call when applying a new voltage setting
- * @level_votes: array of votes for each level
+ * @regulator: array of regulators.
+ * @num_regulators: size of regulator array. Standard regulator APIs will be
+ used if this field > 0.
+ * @set_vdd: function to call when applying a new voltage setting.
+ * @vdd_uv: sorted 2D array of legal voltage settings. Indexed by level, then
+ regulator.
+ * @level_votes: array of votes for each level.
+ * @num_levels: specifies the size of level_votes array.
* @cur_level: the currently set voltage level
* @lock: lock to protect this struct
*/
struct clk_vdd_class {
const char *class_name;
+ struct regulator **regulator;
+ int num_regulators;
int (*set_vdd)(struct clk_vdd_class *v_class, int level);
+ const int **vdd_uv;
int *level_votes;
int num_levels;
unsigned long cur_level;
@@ -66,6 +76,20 @@
.lock = __MUTEX_INITIALIZER(_name.lock) \
}
+#define DEFINE_VDD_REGULATORS(_name, _num_levels, _num_regulators, _vdd_uv) \
+ struct clk_vdd_class _name = { \
+ .class_name = #_name, \
+ .vdd_uv = _vdd_uv, \
+ .regulator = (struct regulator * [_num_regulators]) {}, \
+ .num_regulators = _num_regulators, \
+ .level_votes = (int [_num_levels]) {}, \
+ .num_levels = _num_levels, \
+ .cur_level = _num_levels, \
+ .lock = __MUTEX_INITIALIZER(_name.lock) \
+ }
+
+#define VDD_UV(...) ((int []){__VA_ARGS__})
+
enum handoff {
HANDOFF_ENABLED_CLK,
HANDOFF_DISABLED_CLK,
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index 5ffcabb..9aae3fb 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -109,6 +109,14 @@
size_t ncfg;
};
+/* Provide an enum and an API to write to misc TLMM registers */
+enum msm_tlmm_misc_reg {
+ TLMM_ETM_MODE_REG = 0x2014,
+ TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
+};
+
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
+
#ifdef CONFIG_MSM_GPIOMUX
/* Before using gpiomux, initialize the subsystem by telling it how many
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index d908a65..fec734a 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -76,6 +76,8 @@
#if defined(CONFIG_MSM_IOMMU)
+extern void msm_iommu_set_client_name(struct iommu_domain *domain,
+ char const *name);
extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
extern int msm_find_domain_no(const struct iommu_domain *domain);
@@ -121,6 +123,11 @@
extern int msm_register_domain(struct msm_iova_layout *layout);
#else
+static inline void msm_iommu_set_client_name(struct iommu_domain *domain,
+ char const *name)
+{
+}
+
static inline struct iommu_domain
*msm_get_iommu_domain(int subsys_id) { return NULL; }
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index fff7fa4..56c4afd 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -93,9 +93,9 @@
#endif
#define MAX_HOLE_ADDRESS (PHYS_OFFSET + 0x10000000)
-extern unsigned long memory_hole_offset;
-extern unsigned long memory_hole_start;
-extern unsigned long memory_hole_end;
+extern phys_addr_t memory_hole_offset;
+extern phys_addr_t memory_hole_start;
+extern phys_addr_t memory_hole_end;
extern unsigned long memory_hole_align;
extern unsigned long virtual_hole_start;
extern unsigned long virtual_hole_end;
@@ -107,11 +107,13 @@
memory_hole_align)
#define __phys_to_virt(phys) \
+ (unsigned long)\
((MEM_HOLE_END_PHYS_OFFSET && ((phys) >= MEM_HOLE_END_PHYS_OFFSET)) ? \
(phys) - MEM_HOLE_END_PHYS_OFFSET + MEM_HOLE_PAGE_OFFSET : \
(phys) - PHYS_OFFSET + PAGE_OFFSET)
#define __virt_to_phys(virt) \
+ (unsigned long)\
((MEM_HOLE_END_PHYS_OFFSET && ((virt) >= MEM_HOLE_PAGE_OFFSET)) ? \
(virt) - MEM_HOLE_PAGE_OFFSET + MEM_HOLE_END_PHYS_OFFSET : \
(virt) - PAGE_OFFSET + PHYS_OFFSET)
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index 8fd3cfc..ef835b8 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -102,9 +102,8 @@
int msm_bus_board_rpm_get_il_ids(uint16_t *id);
int msm_bus_board_get_iid(int id);
-#ifdef CONFIG_ARCH_MSM8226
-#define NFAB 6
-#endif
+#define NFAB_MSM8226 6
+#define NFAB_MSM8610 5
/*
* These macros specify the convention followed for allocating
@@ -302,6 +301,7 @@
MSM_BUS_MASTER_V_OCMEM_GFX3D,
MSM_BUS_MASTER_IPA,
MSM_BUS_MASTER_QPIC,
+ MSM_BUS_MASTER_MDPE,
MSM_BUS_MASTER_LAST,
@@ -459,6 +459,7 @@
MSM_BUS_SLAVE_SERVICE_CNOC,
MSM_BUS_SLAVE_IPS_CFG,
MSM_BUS_SLAVE_QPIC,
+ MSM_BUS_SLAVE_DSI_CFG,
MSM_BUS_SLAVE_LAST,
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index 2fdd99c..f460a4e 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,12 +28,6 @@
#define MPQ8092_QGIC_DIST_PHYS 0xF9000000
#define MPQ8092_QGIC_DIST_SIZE SZ_4K
-#define MPQ8092_QGIC_CPU_PHYS 0xF9002000
-#define MPQ8092_QGIC_CPU_SIZE SZ_4K
-
-#define MPQ8092_APCS_GCC_PHYS 0xF9011000
-#define MPQ8092_APCS_GCC_SIZE SZ_4K
-
#define MPQ8092_TLMM_PHYS 0xFD510000
#define MPQ8092_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 81b3c48..ac3e912 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,9 +28,6 @@
#define MSM8226_QGIC_DIST_PHYS 0xF9000000
#define MSM8226_QGIC_DIST_SIZE SZ_4K
-#define MSM8226_QGIC_CPU_PHYS 0xF9002000
-#define MSM8226_QGIC_CPU_SIZE SZ_4K
-
#define MSM8226_APCS_GCC_PHYS 0xF9011000
#define MSM8226_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 594b1cc..ec3c210 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,12 +28,6 @@
#define MSM8974_QGIC_DIST_PHYS 0xF9000000
#define MSM8974_QGIC_DIST_SIZE SZ_4K
-#define MSM8974_QGIC_CPU_PHYS 0xF9002000
-#define MSM8974_QGIC_CPU_SIZE SZ_4K
-
-#define MSM8974_APCS_GCC_PHYS 0xF9011000
-#define MSM8974_APCS_GCC_SIZE SZ_4K
-
#define MSM8974_TLMM_PHYS 0xFD510000
#define MSM8974_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 341bbe3..9a8bfc1 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,12 +28,6 @@
#define MSM9625_QGIC_DIST_PHYS 0xF9000000
#define MSM9625_QGIC_DIST_SIZE SZ_4K
-#define MSM9625_QGIC_CPU_PHYS 0xF9002000
-#define MSM9625_QGIC_CPU_SIZE SZ_4K
-
-#define MSM9625_APCS_GCC_PHYS 0xF9011000
-#define MSM9625_APCS_GCC_SIZE SZ_4K
-
#define MSM9625_TMR_PHYS 0xF9021000
#define MSM9625_TMR_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
index 8283622..0a33055 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-zinc.h
@@ -28,9 +28,6 @@
#define MSMZINC_QGIC_DIST_PHYS 0xF9000000
#define MSMZINC_QGIC_DIST_SIZE SZ_4K
-#define MSMZINC_QGIC_CPU_PHYS 0xF9002000
-#define MSMZINC_QGIC_CPU_SIZE SZ_4K
-
#define MSMZINC_TLMM_PHYS 0xFD510000
#define MSMZINC_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 9cf9517..d3706cd 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -47,15 +47,14 @@
#define MSM8625_WARM_BOOT_PHYS 0x0FD00000
-
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
- defined(CONFIG_ARCH_MSM8930) || defined(CONFIG_ARCH_MSM9615) || \
- defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MSM7X27) || \
- defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X01A) || \
- defined(CONFIG_ARCH_MSM8625) || defined(CONFIG_ARCH_MSM7X30) || \
- defined(CONFIG_ARCH_MSM9625) || defined(CONFIG_ARCH_MPQ8092) || \
- defined(CONFIG_ARCH_MSM8226) || defined(CONFIG_ARCH_MSM8610) || \
- defined(CONFIG_ARCH_MSMZINC)
+/* Legacy single-target iomap */
+#if defined(CONFIG_ARCH_QSD8X50)
+#include "msm_iomap-8x50.h"
+#elif defined(CONFIG_ARCH_MSM8X60)
+#include "msm_iomap-8x60.h"
+#elif defined(CONFIG_ARCH_FSM9XXX)
+#include "msm_iomap-fsm9xxx.h"
+#else
/* Unified iomap */
@@ -136,18 +135,6 @@
#include "msm_iomap-8226.h"
#include "msm_iomap-8610.h"
-#else
-/* Legacy single-target iomap */
-#if defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#elif defined(CONFIG_ARCH_MSM8X60)
-#include "msm_iomap-8x60.h"
-#elif defined(CONFIG_ARCH_FSM9XXX)
-#include "msm_iomap-fsm9xxx.h"
-#else
-#error "Target compiled without IO map\n"
-#endif
-
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iommu_priv.h b/arch/arm/mach-msm/include/mach/msm_iommu_priv.h
new file mode 100644
index 0000000..a2f4836
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iommu_priv.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_IOMMU_PRIV_H
+#define MSM_IOMMU_PRIV_H
+
+/**
+ * struct msm_iommu_pt - Container for first level page table and its
+ * attributes.
+ * fl_table: Pointer to the first level page table.
+ * redirect: Set to 1 if L2 redirect for page tables are enabled, 0 otherwise.
+ */
+struct msm_iommu_pt {
+ unsigned long *fl_table;
+ int redirect;
+};
+
+/**
+ * struct msm_iommu_priv - Container for page table attributes and other
+ * private iommu domain information.
+ * attributes.
+ * pt: Page table attribute structure
+ * list_attached: List of devices (contexts) attached to this domain.
+ * client_name: Name of the domain client.
+ */
+struct msm_iommu_priv {
+ struct msm_iommu_pt pt;
+ struct list_head list_attached;
+ const char *client_name;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 8a06fe3..0cc7bbf 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -21,7 +21,7 @@
#define SCM_SVC_SSD 0x7
#define SCM_SVC_FUSE 0x8
#define SCM_SVC_PWR 0x9
-#define SCM_SVC_CP 0xC
+#define SCM_SVC_MP 0xC
#define SCM_SVC_DCVS 0xD
#define SCM_SVC_TZSCHEDULER 0xFC
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index ff1b3c5..45f2646 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -74,6 +74,10 @@
of_machine_is_compatible("qcom,msm8610-sim")
#define machine_is_msm8610_rumi() \
of_machine_is_compatible("qcom,msm8610-rumi")
+#define machine_is_msm8610_mtp() \
+ of_machine_is_compatible("qcom,msm8610-mtp")
+#define machine_is_msm8610_cdp() \
+ of_machine_is_compatible("qcom,msm8610-cdp")
#define early_machine_is_msmzinc() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
#define machine_is_msmzinc_sim() \
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index c71a79a..19c7acd 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,8 +301,6 @@
#ifdef CONFIG_ARCH_MSM8974
static struct map_desc msm_8974_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
- MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
MSM_CHIP_DEVICE(TLMM, MSM8974),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
{
@@ -326,7 +324,6 @@
#ifdef CONFIG_ARCH_MSMZINC
static struct map_desc msm_zinc_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSMZINC),
- MSM_CHIP_DEVICE(QGIC_CPU, MSMZINC),
MSM_CHIP_DEVICE(TLMM, MSMZINC),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -488,9 +485,7 @@
#ifdef CONFIG_ARCH_MSM9625
static struct map_desc msm9625_io_desc[] __initdata = {
- MSM_CHIP_DEVICE(APCS_GCC, MSM9625),
MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -515,8 +510,6 @@
#ifdef CONFIG_ARCH_MPQ8092
static struct map_desc mpq8092_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
- MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
- MSM_CHIP_DEVICE(APCS_GCC, MPQ8092),
MSM_CHIP_DEVICE(TLMM, MPQ8092),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -538,7 +531,6 @@
#ifdef CONFIG_ARCH_MSM8226
static struct map_desc msm_8226_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
- MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
MSM_CHIP_DEVICE(TLMM, MSM8226),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 5228abc..a837ca1 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -25,6 +25,7 @@
#include <asm/page.h>
#include <mach/iommu.h>
#include <mach/iommu_domains.h>
+#include <mach/msm_iommu_priv.h>
#include <mach/socinfo.h>
#include <mach/msm_subsystem_map.h>
@@ -40,6 +41,12 @@
DEFINE_MUTEX(domain_mutex);
static atomic_t domain_nums = ATOMIC_INIT(-1);
+void msm_iommu_set_client_name(struct iommu_domain *domain, char const *name)
+{
+ struct msm_iommu_priv *priv = domain->priv;
+ priv->client_name = name;
+}
+
int msm_use_iommu()
{
return iommu_present(&platform_bus_type);
@@ -431,6 +438,10 @@
data->npools = layout->npartitions;
data->domain_num = atomic_inc_return(&domain_nums);
data->domain = iommu_domain_alloc(bus, layout->domain_flags);
+ if (!data->domain)
+ goto out;
+
+ msm_iommu_set_client_name(data->domain, layout->client_name);
add_domain(data);
@@ -479,7 +490,8 @@
}
static int create_and_add_domain(struct iommu_group *group,
- const struct device_node *node)
+ struct device_node const *node,
+ char const *name)
{
unsigned int ret_val = 0;
unsigned int i, j;
@@ -539,6 +551,7 @@
part[0].size = 0xFFFFFFFF;
}
+ l.client_name = name;
l.partitions = part;
secure_domain = of_property_read_bool(node, "qcom,secure-domain");
@@ -594,7 +607,7 @@
ret_val = -EINVAL;
goto free_group;
}
- ret_val = create_and_add_domain(group, node);
+ ret_val = create_and_add_domain(group, node, name);
if (ret_val) {
ret_val = -EINVAL;
goto free_group;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index ea874bd..d81dbb4 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -34,6 +34,7 @@
#include <mach/smem_log.h>
#include <mach/subsystem_notif.h>
#include <mach/msm_ipc_router.h>
+#include <mach/msm_ipc_logging.h>
#include "ipc_router.h"
#include "modem_notifier.h"
@@ -52,15 +53,21 @@
module_param_named(debug_mask, msm_ipc_router_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+static void *ipc_rtr_log_ctxt;
+#define IPC_RTR_LOG_PAGES 5
#define DIAG(x...) pr_info("[RR] ERROR " x)
#if defined(DEBUG)
#define D(x...) do { \
+if (ipc_rtr_log_ctxt) \
+ ipc_log_string(ipc_rtr_log_ctxt, x); \
if (msm_ipc_router_debug_mask & RTR_DBG) \
pr_info(x); \
} while (0)
#define RR(x...) do { \
+if (ipc_rtr_log_ctxt) \
+ ipc_log_string(ipc_rtr_log_ctxt, x); \
if (msm_ipc_router_debug_mask & R2R_MSG) \
pr_info("[RR] "x); \
} while (0)
@@ -1660,10 +1667,10 @@
}
hdr = (struct rr_header *)(head_skb->data);
- RR("- ver=%d type=%d src=%d:%08x crx=%d siz=%d dst=%d:%08x\n",
- hdr->version, hdr->type, hdr->src_node_id, hdr->src_port_id,
- hdr->confirm_rx, hdr->size, hdr->dst_node_id,
- hdr->dst_port_id);
+ RAW("ver=%d type=%d src=%d:%08x crx=%d siz=%d dst=%d:%08x\n",
+ hdr->version, hdr->type, hdr->src_node_id,
+ hdr->src_port_id, hdr->confirm_rx, hdr->size,
+ hdr->dst_node_id, hdr->dst_port_id);
if (hdr->version != IPC_ROUTER_VERSION) {
pr_err("version %d != %d\n",
@@ -2867,6 +2874,12 @@
struct msm_ipc_routing_table_entry *rt_entry;
msm_ipc_router_debug_mask |= SMEM_LOG;
+ ipc_rtr_log_ctxt = ipc_log_context_create(IPC_RTR_LOG_PAGES,
+ "ipc_router");
+ if (!ipc_rtr_log_ctxt)
+ pr_err("%s: Unable to create IPC logging for IPC RTR",
+ __func__);
+
msm_ipc_router_workqueue =
create_singlethread_workqueue("msm_ipc_router");
if (!msm_ipc_router_workqueue)
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a50a37d..cafcdd2 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -48,7 +48,7 @@
#define IPC_ROUTER_XPRT_EVENT_CLOSE 3
#define IPC_ROUTER_INFINITY -1
-#define DEFAULT_RCV_TIMEO IPC_ROUTER_INFINITY
+#define DEFAULT_RCV_TIMEO 0
#define ALIGN_SIZE(x) ((4 - ((x) & 3)) & 3)
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index 16b60a1..f40bd5d 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -414,7 +414,7 @@
}
if (timeout == 0)
- return -ETIMEDOUT;
+ return 0;
lock_sock(sk);
mutex_lock(&port_ptr->port_rx_q_lock);
}
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 9f06cf6..c8d6d5a 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -161,9 +161,11 @@
*/
pr_debug("%s: Pulling AP2MDM_KPDPWR gpio high\n", __func__);
gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 1);
+ gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
msleep(1000);
gpio_direction_output(mdm_drv->ap2mdm_kpdpwr_n_gpio, 0);
- }
+ } else
+ gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
if (!GPIO_IS_VALID(mdm_drv->mdm2ap_pblrdy))
goto start_mdm_peripheral;
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index 03d158e..de46be8 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -649,7 +649,7 @@
}
}
- gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 1);
+ gpio_direction_output(mdm_drv->ap2mdm_status_gpio, 0);
gpio_direction_output(mdm_drv->ap2mdm_errfatal_gpio, 0);
if (GPIO_IS_VALID(mdm_drv->ap2mdm_wakeup_gpio))
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 5f11806..edfb45b 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -34,7 +34,6 @@
#include <linux/completion.h>
#include <linux/err.h>
#endif
-#include <linux/android_pmem.h>
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <linux/sched.h>
@@ -191,6 +190,10 @@
BUG_ON(mr_candidate == NULL);
/* bump mt up against the top of the region */
mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+ ret = memblock_reserve(mt->start, mt->size);
+ BUG_ON(ret);
+ ret = memblock_free(mt->start, mt->size);
+ BUG_ON(ret);
ret = memblock_remove(mt->start, mt->size);
BUG_ON(ret);
}
diff --git a/arch/arm/mach-msm/msm_bus/Makefile b/arch/arm/mach-msm/msm_bus/Makefile
index 2ee07f3..ebc0c3a 100644
--- a/arch/arm/mach-msm/msm_bus/Makefile
+++ b/arch/arm/mach-msm/msm_bus/Makefile
@@ -15,4 +15,5 @@
obj-$(CONFIG_ARCH_MSM8974) += msm_bus_board_8974.o
obj-$(CONFIG_ARCH_MSM9625) += msm_bus_board_9625.o
obj-$(CONFIG_ARCH_MSM8226) += msm_bus_id.o
+obj-$(CONFIG_ARCH_MSM8610) += msm_bus_id.o
obj-$(CONFIG_DEBUG_FS) += msm_bus_dbg.o
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 4336945..4adfe4d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -562,7 +562,7 @@
int pnode, src, curr, ctx;
uint64_t req_clk, req_bw, curr_clk, curr_bw;
struct msm_bus_client *client = (struct msm_bus_client *)cl;
- if (IS_ERR(client)) {
+ if (IS_ERR_OR_NULL(client)) {
MSM_BUS_ERR("msm_bus_scale_client update req error %d\n",
(uint32_t)client);
return -ENXIO;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index 9201398..fd2dbb5 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -182,7 +182,7 @@
};
struct msm_bus_board_algorithm {
- const int board_nfab;
+ int board_nfab;
void (*assign_iids)(struct msm_bus_fabric_registration *fabreg,
int fabid);
int (*get_iid)(int id);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_id.c b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
index 693c51e..7e9883f 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_id.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_id.c
@@ -19,6 +19,7 @@
#include <mach/msm_bus_board.h>
#include <mach/board.h>
#include <mach/rpm.h>
+#include <mach/socinfo.h>
#include "msm_bus_core.h"
#include "msm_bus_noc.h"
#include "msm_bus_bimc.h"
@@ -67,7 +68,6 @@
static struct msm_bus_board_algorithm msm_bus_id_algo = {
- .board_nfab = NFAB,
.get_iid = msm_bus_get_iid,
.assign_iids = msm_bus_assign_iids,
};
@@ -79,5 +79,10 @@
void msm_bus_board_init(struct msm_bus_fabric_registration *pdata)
{
+ if (machine_is_msm8226())
+ msm_bus_id_algo.board_nfab = NFAB_MSM8226;
+ else if (machine_is_msm8610())
+ msm_bus_id_algo.board_nfab = NFAB_MSM8610;
+
pdata->board_algo = &msm_bus_id_algo;
}
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index 1589623..f70022e 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -213,7 +213,9 @@
switch (val) {
case PM_POST_HIBERNATION:
case PM_POST_SUSPEND:
+ case PM_POST_RESTORE:
rq_info.hotplug_disabled = 0;
+ break;
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
rq_info.hotplug_disabled = 1;
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ef10cdc..4778d5b 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -568,6 +568,6 @@
return platform_driver_register(&msm_watchdog_driver);
}
-late_initcall(init_watchdog);
+pure_initcall(init_watchdog);
MODULE_DESCRIPTION("MSM Watchdog Driver");
MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index dfbda74..ef13c34 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -114,6 +114,8 @@
pil_q6v5_shutdown(pil);
pil_lpass_disable_clks(drv);
+ writel_relaxed(1, drv->restart_reg);
+
drv->is_booted = false;
return 0;
@@ -125,6 +127,11 @@
unsigned long start_addr = pil_get_entry_addr(pil);
int ret;
+ /* Deassert reset to subsystem and wait for propagation */
+ writel_relaxed(0, drv->restart_reg);
+ mb();
+ udelay(2);
+
ret = pil_lpass_enable_clks(drv);
if (ret)
return ret;
@@ -385,6 +392,7 @@
struct lpass_data *drv;
struct q6v5_data *q6;
struct pil_desc *desc;
+ struct resource *res;
int ret;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -405,6 +413,11 @@
desc->owner = THIS_MODULE;
desc->proxy_timeout = PROXY_TIMEOUT_MS;
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
+ q6->restart_reg = devm_request_and_ioremap(&pdev->dev, res);
+ if (!q6->restart_reg)
+ return -ENOMEM;
+
q6->core_clk = devm_clk_get(&pdev->dev, "core_clk");
if (IS_ERR(q6->core_clk))
return PTR_ERR(q6->core_clk);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 1954ec3..06de8cc 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -24,6 +24,8 @@
#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
+#include <linux/dma-mapping.h>
#include <mach/subsystem_restart.h>
#include <mach/clk.h>
@@ -57,6 +59,7 @@
#define RMB_PMI_CODE_LENGTH 0x18
#define VDD_MSS_UV 1050000
+#define MAX_VDD_MSS_UV 1150000
#define MAX_VDD_MX_UV 1150000
#define PROXY_TIMEOUT_MS 10000
@@ -76,10 +79,8 @@
#define BHS_TIMEOUT_US 50
struct mba_data {
- void __iomem *metadata_base;
void __iomem *rmb_base;
void __iomem *io_clamp_reg;
- unsigned long metadata_phys;
struct pil_desc desc;
struct subsys_device *subsys;
struct subsys_desc subsys_desc;
@@ -92,6 +93,8 @@
bool crash_shutdown;
bool ignore_errors;
int is_loadable;
+ int err_fatal_irq;
+ int force_stop_gpio;
};
static int pbl_mba_boot_timeout_ms = 100;
@@ -360,18 +363,28 @@
const u8 *metadata, size_t size)
{
struct mba_data *drv = dev_get_drvdata(pil->dev);
+ void *mdata_virt;
+ dma_addr_t mdata_phys;
s32 status;
int ret;
- /* Copy metadata to assigned shared buffer location */
- memcpy(drv->metadata_base, metadata, size);
+ /* Make metadata physically contiguous and 4K aligned. */
+ mdata_virt = dma_alloc_coherent(pil->dev, size, &mdata_phys,
+ GFP_KERNEL);
+ if (!mdata_virt) {
+ dev_err(pil->dev, "MBA metadata buffer allocation failed\n");
+ return -ENOMEM;
+ }
+ memcpy(mdata_virt, metadata, size);
+ /* wmb() ensures copy completes prior to starting authentication. */
+ wmb();
/* Initialize length counter to 0 */
writel_relaxed(0, drv->rmb_base + RMB_PMI_CODE_LENGTH);
drv->img_length = 0;
/* Pass address of meta-data to the MBA and perform authentication */
- writel_relaxed(drv->metadata_phys, drv->rmb_base + RMB_PMI_META_DATA);
+ writel_relaxed(mdata_phys, drv->rmb_base + RMB_PMI_META_DATA);
writel_relaxed(CMD_META_DATA_READY, drv->rmb_base + RMB_MBA_COMMAND);
ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
@@ -384,6 +397,8 @@
ret = -EINVAL;
}
+ dma_free_coherent(pil->dev, size, mdata_virt, mdata_phys);
+
return ret;
}
@@ -470,18 +485,17 @@
subsystem_restart_dev(drv->subsys);
}
-static void smsm_state_cb(void *data, uint32_t old_state, uint32_t new_state)
+static irqreturn_t modem_err_fatal_intr_handler(int irq, void *dev_id)
{
- struct mba_data *drv = data;
+ struct mba_data *drv = dev_id;
- /* Ignore if we're the one that set SMSM_RESET */
+ /* Ignore if we're the one that set the force stop GPIO */
if (drv->crash_shutdown)
- return;
+ return IRQ_HANDLED;
- if (new_state & SMSM_RESET) {
- pr_err("Probable fatal error on the modem.\n");
- restart_modem(drv);
- }
+ pr_err("Fatal error on the modem.\n");
+ restart_modem(drv);
+ return IRQ_HANDLED;
}
static int modem_shutdown(const struct subsys_desc *subsys)
@@ -521,7 +535,7 @@
{
struct mba_data *drv = subsys_to_drv(subsys);
drv->crash_shutdown = true;
- smsm_reset_modem(SMSM_RESET);
+ gpio_set_value(drv->force_stop_gpio, 1);
}
static struct ramdump_segment smem_segments[] = {
@@ -658,10 +672,11 @@
goto err_irq;
}
- ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, drv);
+ ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
+ modem_err_fatal_intr_handler,
+ IRQF_TRIGGER_RISING, "pil-mss", drv);
if (ret < 0) {
- dev_err(&pdev->dev, "Unable to register SMSM callback!\n");
+ dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
goto err_irq;
}
@@ -671,14 +686,11 @@
ret = PTR_ERR(drv->adsp_state_notifier);
dev_err(&pdev->dev, "%s: Registration with the SSR notification driver failed (%d)",
__func__, ret);
- goto err_smsm;
+ goto err_irq;
}
return 0;
-err_smsm:
- smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET, smsm_state_cb,
- drv);
err_irq:
destroy_ramdump_device(drv->smem_ramdump_dev);
err_ramdump_smem:
@@ -715,15 +727,6 @@
drv->rmb_base = devm_request_and_ioremap(&pdev->dev, res);
if (!drv->rmb_base)
return -ENOMEM;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "metadata_base");
- if (res) {
- drv->metadata_base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!drv->metadata_base)
- return -ENOMEM;
- drv->metadata_phys = res->start;
- }
}
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "restart_reg");
@@ -739,7 +742,7 @@
if (IS_ERR(q6->vreg_mx))
return PTR_ERR(q6->vreg_mx);
- ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, VDD_MSS_UV);
+ ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, MAX_VDD_MSS_UV);
if (ret)
dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
@@ -794,7 +797,7 @@
static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
{
struct mba_data *drv;
- int ret;
+ int ret, err_fatal_gpio;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -809,6 +812,22 @@
return ret;
}
+ /* Get the IRQ from the GPIO for registering inbound handler */
+ err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-err-fatal", 0);
+ if (err_fatal_gpio < 0)
+ return err_fatal_gpio;
+
+ drv->err_fatal_irq = gpio_to_irq(err_fatal_gpio);
+ if (drv->err_fatal_irq < 0)
+ return drv->err_fatal_irq;
+
+ /* Get the GPIO pin for writing the outbound bits: add more as needed */
+ drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-force-stop", 0);
+ if (drv->force_stop_gpio < 0)
+ return drv->force_stop_gpio;
+
return pil_subsys_init(drv, pdev);
}
@@ -818,8 +837,6 @@
subsys_notif_unregister_notifier(drv->adsp_state_notifier,
&adsp_state_notifier_block);
- smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
- smsm_state_cb, drv);
subsys_unregister(drv->subsys);
destroy_ramdump_device(drv->smem_ramdump_dev);
destroy_ramdump_device(drv->ramdump_dev);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 717c057..3c50bc6 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -974,7 +974,7 @@
if (acc_sts & msm_pm_slp_sts[cpu].mask)
return 0;
- usleep(100);
+ udelay(100);
}
pr_info("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
@@ -1021,6 +1021,9 @@
*/
void msm_pm_enable_retention(bool enable)
{
+ if (enable == msm_pm_ldo_retention_enabled)
+ return;
+
msm_pm_ldo_retention_enabled = enable;
/*
* If retention is being disabled, wakeup all online core to ensure
diff --git a/arch/arm/mach-msm/qdsp5/adsp_driver.c b/arch/arm/mach-msm/qdsp5/adsp_driver.c
index d83a140..eb9c388 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_driver.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include "adsp.h"
#include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
#include <mach/debug_mm.h>
struct adsp_ion_info {
diff --git a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
index 4d03dca..62d6d58 100644
--- a/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
+++ b/arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
@@ -17,7 +17,6 @@
*/
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <mach/qdsp5/qdsp5vdeccmdi.h>
#include "adsp.h"
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
index 7819395..608f544 100644
--- a/arch/arm/mach-msm/qdsp5/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -16,7 +16,6 @@
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
@@ -110,7 +109,6 @@
audpp_cmd_cfg_object_params_eqalizer eq;
struct audrec_session_info session_info;
/*pmem info*/
- int pmem_fd;
unsigned long paddr;
unsigned long kvaddr;
unsigned long pmem_len;
@@ -1136,7 +1134,6 @@
{
int rc = 0;
unsigned long flags = 0;
- struct msm_audio_pmem_info info;
MM_DBG("%s\n", __func__);
@@ -1156,23 +1153,6 @@
MM_ERR("AUDPP returned err =%d\n", rc);
spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
break;
- case AUDIO_REGISTER_PMEM:
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info))) {
- MM_ERR("Cannot copy from user\n");
- return -EFAULT;
- }
- rc = get_pmem_file(info.fd, &acdb_data.paddr,
- &acdb_data.kvaddr,
- &acdb_data.pmem_len,
- &acdb_data.file);
- if (rc == 0)
- acdb_data.pmem_fd = info.fd;
- break;
- case AUDIO_DEREGISTER_PMEM:
- if (acdb_data.pmem_fd)
- put_pmem_file(acdb_data.file);
- break;
case AUDIO_SET_ACDB_BLK:
MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
index 7249bb1..ad74ca3 100644
--- a/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
+++ b/arch/arm/mach-msm/qdsp5v2/adsp_driver.c
@@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/msm_adsp.h>
-#include <linux/android_pmem.h>
#include <linux/export.h>
#include "adsp.h"
#include <mach/debug_mm.h>
@@ -87,71 +86,6 @@
res; \
})
-static int adsp_pmem_check(struct msm_adsp_module *module,
- void *vaddr, unsigned long len)
-{
- struct adsp_pmem_region *region_elt;
- struct hlist_node *node;
- struct adsp_pmem_region t = { .vaddr = vaddr, .len = len };
-
- hlist_for_each_entry(region_elt, node, &module->pmem_regions, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("module %s:"
- " region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- module->name,
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int adsp_pmem_add(struct msm_adsp_module *module,
- struct adsp_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct adsp_pmem_region *region;
- int rc = -EINVAL;
-
- mutex_lock(&module->pmem_regions_lock);
- region = kmalloc(sizeof(*region), GFP_KERNEL);
- if (!region) {
- rc = -ENOMEM;
- goto end;
- }
- INIT_HLIST_NODE(®ion->list);
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
- }
-
- rc = adsp_pmem_check(module, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
- }
-
- region->vaddr = info->vaddr;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
-
- hlist_add_head(®ion->list, &module->pmem_regions);
-end:
- mutex_unlock(&module->pmem_regions_lock);
- return rc;
-}
-
static int adsp_pmem_lookup_vaddr(struct msm_adsp_module *module, void **addr,
unsigned long len, struct adsp_pmem_region **region)
{
@@ -417,24 +351,6 @@
return rc;
}
-static int adsp_pmem_del(struct msm_adsp_module *module)
-{
- struct hlist_node *node, *tmp;
- struct adsp_pmem_region *region;
-
- mutex_lock(&module->pmem_regions_lock);
- hlist_for_each_safe(node, tmp, &module->pmem_regions) {
- region = hlist_entry(node, struct adsp_pmem_region, list);
- hlist_del(node);
- put_pmem_file(region->file);
- kfree(region);
- }
- mutex_unlock(&module->pmem_regions_lock);
- BUG_ON(!hlist_empty(&module->pmem_regions));
-
- return 0;
-}
-
static long adsp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct adsp_device *adev = filp->private_data;
@@ -466,21 +382,11 @@
return adsp_set_clkrate(adev->module, clk_rate);
}
- case ADSP_IOCTL_REGISTER_PMEM: {
- struct adsp_pmem_info info;
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- return -EFAULT;
- return adsp_pmem_add(adev->module, &info);
- }
-
case ADSP_IOCTL_ABORT_EVENT_READ:
adev->abort = 1;
wake_up(&adev->event_wait);
break;
- case ADSP_IOCTL_UNREGISTER_PMEM:
- return adsp_pmem_del(adev->module);
-
default:
break;
}
@@ -498,8 +404,6 @@
/* clear module before putting it to avoid race with open() */
adev->module = NULL;
- rc = adsp_pmem_del(module);
-
msm_adsp_put(module);
return rc;
}
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac.c b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
index 883da2b..fbce5d6 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio_aac.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
index a878e12..cf1f58d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_aac_in.c
@@ -26,7 +26,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_aac.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <mach/msm_memtypes.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
index 5d7cfd7..85378be 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_acdb.c
@@ -16,7 +16,6 @@
#include <linux/wait.h>
#include <linux/mutex.h>
#include <linux/io.h>
-#include <linux/android_pmem.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/uaccess.h>
@@ -1287,7 +1286,6 @@
{
int rc = 0;
unsigned long flags = 0;
- struct msm_audio_pmem_info info;
MM_DBG("%s\n", __func__);
@@ -1308,23 +1306,6 @@
MM_ERR("AUDPP returned err =%d\n", rc);
spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
break;
- case AUDIO_REGISTER_PMEM:
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info))) {
- MM_ERR("Cannot copy from user\n");
- return -EFAULT;
- }
- rc = get_pmem_file(info.fd, &acdb_data.paddr,
- &acdb_data.kvaddr,
- &acdb_data.pmem_len,
- &acdb_data.file);
- if (rc == 0)
- acdb_data.pmem_fd = info.fd;
- break;
- case AUDIO_DEREGISTER_PMEM:
- if (acdb_data.pmem_fd)
- put_pmem_file(acdb_data.file);
- break;
case AUDIO_SET_ACDB_BLK:
MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
rc = acdb_set_calibration_blk(arg);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
index 7cc3e29..632aa0d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_adpcm.c
@@ -34,7 +34,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
index c8b4171..bd4f6e1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb.c
@@ -37,7 +37,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
index 66d0a9e..e5706c7 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrwb.c
@@ -37,7 +37,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
index 2d9327e..ed946f9 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_evrc.c
@@ -32,7 +32,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_fm.c b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
index cffa7e7..27548ac 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_fm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_fm.c
@@ -29,7 +29,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
index 0390edf..bda2e4d 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_mp3.c
@@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
@@ -1095,103 +1094,6 @@
return rc;
}
-static int audmp3_pmem_check(struct audio *audio,
- void *vaddr, unsigned long len)
-{
- struct audmp3_pmem_region *region_elt;
- struct audmp3_pmem_region t = { .vaddr = vaddr, .len = len };
-
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int audmp3_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audmp3_pmem_region *region;
- int rc = -EINVAL;
-
- MM_DBG("\n"); /* Macro prints the file name and function */
- region = kmalloc(sizeof(*region), GFP_KERNEL);
-
- if (!region) {
- rc = -ENOMEM;
- goto end;
- }
-
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- goto end;
- }
-
- rc = audmp3_pmem_check(audio, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- goto end;
- }
-
- region->vaddr = info->vaddr;
- region->fd = info->fd;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
- region->ref_cnt = 0;
- MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
- region->vaddr, region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
-end:
- return rc;
-}
-
-static int audmp3_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- struct audmp3_pmem_region *region;
- struct list_head *ptr, *next;
- int rc = -EINVAL;
-
- MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audmp3_pmem_region, list);
-
- if ((region->fd == info->fd) &&
- (region->vaddr == info->vaddr)) {
- if (region->ref_cnt) {
- MM_DBG("region %p in use ref_cnt %d\n",
- region, region->ref_cnt);
- break;
- }
- MM_DBG("remove region fd %d vaddr %p \n",
- info->fd, info->vaddr);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
static int audmp3_pmem_lookup_vaddr(struct audio *audio, void *addr,
unsigned long len, struct audmp3_pmem_region **region)
{
@@ -1688,25 +1590,6 @@
break;
}
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audmp3_pmem_add(audio, &info);
- break;
- }
-
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_DEREGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audmp3_pmem_remove(audio, &info);
- break;
- }
case AUDIO_ASYNC_WRITE:
if (audio->drv_status & ADRV_STATUS_FSYNC)
rc = -EBUSY;
@@ -2105,21 +1988,6 @@
return rc;
}
-static void audmp3_reset_pmem_region(struct audio *audio)
-{
- struct audmp3_pmem_region *region;
- struct list_head *ptr, *next;
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audmp3_pmem_region, list);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- }
-
- return;
-}
-
static int audio_release(struct inode *inode, struct file *file)
{
struct audio *audio = file->private_data;
@@ -2130,7 +1998,6 @@
audio_disable(audio);
audio->drv_ops.out_flush(audio);
audio->drv_ops.in_flush(audio);
- audmp3_reset_pmem_region(audio);
msm_adsp_put(audio->audplay);
audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_out.c b/arch/arm/mach-msm/qdsp5v2/audio_out.c
index e5c59ba..712c9f3 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_out.c
@@ -30,7 +30,6 @@
#include <linux/wakelock.h>
#include <linux/memory_alloc.h>
#include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
#include <linux/pm_qos.h>
#include <mach/msm_adsp.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
index ea8fc83..cbd2913 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_pcm.c
@@ -30,7 +30,6 @@
#include <linux/delay.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/memory_alloc.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
@@ -743,99 +742,6 @@
return rc;
}
-static int audpcm_pmem_check(struct audio *audio,
- void *vaddr, unsigned long len)
-{
- struct audpcm_pmem_region *region_elt;
- struct audpcm_pmem_region t = { .vaddr = vaddr, .len = len };
-
- list_for_each_entry(region_elt, &audio->pmem_region_queue, list) {
- if (CONTAINS(region_elt, &t) || CONTAINS(&t, region_elt) ||
- OVERLAPS(region_elt, &t)) {
- MM_ERR("region (vaddr %p len %ld)"
- " clashes with registered region"
- " (vaddr %p paddr %p len %ld)\n",
- vaddr, len,
- region_elt->vaddr,
- (void *)region_elt->paddr,
- region_elt->len);
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int audpcm_pmem_add(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- unsigned long paddr, kvaddr, len;
- struct file *file;
- struct audpcm_pmem_region *region;
- int rc = -EINVAL;
-
- MM_DBG("\n"); /* Macro prints the file name and function */
- region = kmalloc(sizeof(*region), GFP_KERNEL);
- if (!region)
- return -ENOMEM;
-
- if (get_pmem_file(info->fd, &paddr, &kvaddr, &len, &file)) {
- kfree(region);
- return -EINVAL;
- }
-
- rc = audpcm_pmem_check(audio, info->vaddr, len);
- if (rc < 0) {
- put_pmem_file(file);
- kfree(region);
- return rc;
- }
-
- region->vaddr = info->vaddr;
- region->fd = info->fd;
- region->paddr = paddr;
- region->kvaddr = kvaddr;
- region->len = len;
- region->file = file;
- region->ref_cnt = 0;
- MM_DBG("add region paddr %lx vaddr %p, len %lu\n", region->paddr,
- region->vaddr, region->len);
- list_add_tail(®ion->list, &audio->pmem_region_queue);
- return rc;
-}
-
-static int audpcm_pmem_remove(struct audio *audio,
- struct msm_audio_pmem_info *info)
-{
- struct audpcm_pmem_region *region;
- struct list_head *ptr, *next;
- int rc = -EINVAL;
-
- MM_DBG("info fd %d vaddr %p\n", info->fd, info->vaddr);
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audpcm_pmem_region, list);
-
- if ((region->fd == info->fd) &&
- (region->vaddr == info->vaddr)) {
- if (region->ref_cnt) {
- MM_DBG("region %p in use ref_cnt %d\n", region,
- region->ref_cnt);
- break;
- }
- MM_DBG("remove region fd %d vaddr %p \n", info->fd,
- info->vaddr);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- rc = 0;
- break;
- }
- }
-
- return rc;
-}
-
static int audpcm_pmem_lookup_vaddr(struct audio *audio, void *addr,
unsigned long len, struct audpcm_pmem_region **region)
{
@@ -1124,26 +1030,6 @@
rc = audpp_pause(audio->dec_id, (int) arg);
break;
- case AUDIO_REGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_REGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audpcm_pmem_add(audio, &info);
- break;
- }
-
- case AUDIO_DEREGISTER_PMEM: {
- struct msm_audio_pmem_info info;
- MM_DBG("AUDIO_DEREGISTER_PMEM\n");
- if (copy_from_user(&info, (void *) arg, sizeof(info)))
- rc = -EFAULT;
- else
- rc = audpcm_pmem_remove(audio, &info);
- break;
- }
-
case AUDIO_ASYNC_WRITE:
if (audio->drv_status & ADRV_STATUS_FSYNC)
rc = -EBUSY;
@@ -1344,21 +1230,6 @@
return rc;
}
-static void audpcm_reset_pmem_region(struct audio *audio)
-{
- struct audpcm_pmem_region *region;
- struct list_head *ptr, *next;
-
- list_for_each_safe(ptr, next, &audio->pmem_region_queue) {
- region = list_entry(ptr, struct audpcm_pmem_region, list);
- list_del(®ion->list);
- put_pmem_file(region->file);
- kfree(region);
- }
-
- return;
-}
-
static int audio_release(struct inode *inode, struct file *file)
{
struct audio *audio = file->private_data;
@@ -1369,7 +1240,6 @@
auddev_unregister_evt_listner(AUDDEV_CLNT_DEC, audio->dec_id);
audio_disable(audio);
audio->drv_ops.out_flush(audio);
- audpcm_reset_pmem_region(audio);
msm_adsp_put(audio->audplay);
audpp_adec_free(audio->dec_id);
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
index bb360be..33ca7a1 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp.c
@@ -33,7 +33,6 @@
#include <linux/debugfs.h>
#include <linux/earlysuspend.h>
#include <linux/list.h>
-#include <linux/android_pmem.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
#include <linux/memory_alloc.h>
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
index 84cfed6..44fc10f 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_wmapro.c
@@ -35,7 +35,6 @@
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/earlysuspend.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <linux/slab.h>
#include <linux/msm_audio_wmapro.h>
diff --git a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
index 5895867..9143b5a 100644
--- a/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/audiov2/q6audio.c
@@ -23,7 +23,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/gpio.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
index 24d2117..1cb9775 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6vdec.c
@@ -32,7 +32,6 @@
#include <linux/wakelock.h>
#include <linux/pm_qos.h>
-#include <linux/android_pmem.h>
#include <linux/msm_q6vdec.h>
#include <mach/cpuidle.h>
diff --git a/arch/arm/mach-msm/qdsp6/msm_q6venc.c b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
index 4704ae7..a2b4b6e 100644
--- a/arch/arm/mach-msm/qdsp6/msm_q6venc.c
+++ b/arch/arm/mach-msm/qdsp6/msm_q6venc.c
@@ -22,7 +22,6 @@
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/msm_q6venc.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6/q6audio.c b/arch/arm/mach-msm/qdsp6/q6audio.c
index f660bdc..9404c3d 100644
--- a/arch/arm/mach-msm/qdsp6/q6audio.c
+++ b/arch/arm/mach-msm/qdsp6/q6audio.c
@@ -22,7 +22,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/wakelock.h>
-#include <linux/android_pmem.h>
#include <linux/firmware.h>
#include <linux/miscdevice.h>
#include <linux/pm_qos.h>
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 34d336e..88de98b 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -24,7 +24,7 @@
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_evrc.o audio_qcelp.o amrwb_in.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
obj-$(CONFIG_MSM_ULTRASOUND_B) += ultrasound/version_b/
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index 7472b46..e74fdf9 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -56,9 +56,6 @@
goto fail;
}
- /* Query the DSP to check if resources are available */
- msleep(Q6_PIL_GET_DELAY_MS);
-
/* Set the state of the ADSP in APR driver */
apr_set_q6_state(APR_SUBSYS_LOADED);
} else if (adsp_state == APR_SUBSYS_LOADED) {
diff --git a/arch/arm/mach-msm/qdsp6v2/fm.c b/arch/arm/mach-msm/qdsp6v2/fm.c
index 3d72b97..23bb716 100644
--- a/arch/arm/mach-msm/qdsp6v2/fm.c
+++ b/arch/arm/mach-msm/qdsp6v2/fm.c
@@ -30,7 +30,6 @@
#include <linux/wait.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/android_pmem.h>
#include <linux/msm_audio.h>
#include <asm/atomic.h>
#include <asm/ioctls.h>
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 8c96b1a..55ce4b1 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,7 @@
RPM_REGULATOR_PARAM_FREQ_REASON,
RPM_REGULATOR_PARAM_CORNER,
RPM_REGULATOR_PARAM_BYPASS,
+ RPM_REGULATOR_PARAM_FLOOR_CORNER,
RPM_REGULATOR_PARAM_MAX,
};
@@ -108,12 +109,13 @@
PARAM(MODE_SMPS, 0, 1, 0, 0, "ssmd", 0, 2, "qcom,init-smps-mode"),
PARAM(PIN_CTRL_ENABLE, 1, 1, 1, 0, "pcen", 0, 0xF, "qcom,init-pin-ctrl-enable"),
PARAM(PIN_CTRL_MODE, 1, 1, 1, 0, "pcmd", 0, 0x1F, "qcom,init-pin-ctrl-mode"),
- PARAM(FREQUENCY, 0, 1, 0, 1, "freq", 0, 16, "qcom,init-frequency"),
+ PARAM(FREQUENCY, 0, 1, 0, 1, "freq", 0, 31, "qcom,init-frequency"),
PARAM(HEAD_ROOM, 1, 0, 0, 1, "hr", 0, 0x7FFFFFFF, "qcom,init-head-room"),
PARAM(QUIET_MODE, 0, 1, 0, 0, "qm", 0, 2, "qcom,init-quiet-mode"),
PARAM(FREQ_REASON, 0, 1, 0, 1, "resn", 0, 8, "qcom,init-freq-reason"),
PARAM(CORNER, 1, 1, 0, 0, "corn", 0, 6, "qcom,init-voltage-corner"),
PARAM(BYPASS, 1, 0, 0, 0, "bypa", 0, 1, "qcom,init-disallow-bypass"),
+ PARAM(FLOOR_CORNER, 1, 1, 0, 0, "vfc", 0, 6, "qcom,init-voltage-floor-corner"),
};
struct rpm_vreg_request {
@@ -147,6 +149,8 @@
struct list_head list;
bool set_active;
bool set_sleep;
+ bool always_send_voltage;
+ bool always_send_current;
struct rpm_vreg_request req;
int system_load;
int min_uV;
@@ -390,6 +394,13 @@
return rc;
}
+#define RPM_VREG_AGGR_MIN(_idx, _param_aggr, _param_reg) \
+{ \
+ _param_aggr[RPM_REGULATOR_PARAM_##_idx] \
+ = min(_param_aggr[RPM_REGULATOR_PARAM_##_idx], \
+ _param_reg[RPM_REGULATOR_PARAM_##_idx]); \
+}
+
#define RPM_VREG_AGGR_MAX(_idx, _param_aggr, _param_reg) \
{ \
_param_aggr[RPM_REGULATOR_PARAM_##_idx] \
@@ -410,20 +421,6 @@
}
/*
- * The RPM treats freq=0 as a special value meaning that this consumer does not
- * care what the SMPS switching freqency is.
- */
-#define RPM_REGULATOR_FREQ_DONT_CARE 0
-
-static inline void rpm_vreg_freqency_aggr(u32 *freq, u32 consumer_freq)
-{
- if (consumer_freq != RPM_REGULATOR_FREQ_DONT_CARE
- && (consumer_freq < *freq
- || *freq == RPM_REGULATOR_FREQ_DONT_CARE))
- *freq = consumer_freq;
-}
-
-/*
* Aggregation is performed on each parameter based on the way that the RPM
* aggregates that type internally between RPM masters.
*/
@@ -436,13 +433,13 @@
RPM_VREG_AGGR_MAX(MODE_SMPS, param_aggr, param_reg);
RPM_VREG_AGGR_OR(PIN_CTRL_ENABLE, param_aggr, param_reg);
RPM_VREG_AGGR_OR(PIN_CTRL_MODE, param_aggr, param_reg);
- rpm_vreg_freqency_aggr(¶m_aggr[RPM_REGULATOR_PARAM_FREQUENCY],
- param_reg[RPM_REGULATOR_PARAM_FREQUENCY]);
+ RPM_VREG_AGGR_MIN(FREQUENCY, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(HEAD_ROOM, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(QUIET_MODE, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(FREQ_REASON, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(CORNER, param_aggr, param_reg);
RPM_VREG_AGGR_MAX(BYPASS, param_aggr, param_reg);
+ RPM_VREG_AGGR_MAX(FLOOR_CORNER, param_aggr, param_reg);
}
static int rpm_vreg_aggregate_requests(struct rpm_regulator *regulator)
@@ -633,8 +630,12 @@
prev_voltage = reg->req.param[RPM_REGULATOR_PARAM_VOLTAGE];
RPM_VREG_SET_PARAM(reg, VOLTAGE, min_uV);
- /* Only send a new voltage if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new voltage if the regulator is currently enabled or
+ * if the regulator has been configured to always send voltage updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -687,8 +688,13 @@
prev_corner = reg->req.param[RPM_REGULATOR_PARAM_CORNER];
RPM_VREG_SET_PARAM(reg, CORNER, corner);
- /* Only send a new voltage if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new voltage corner if the regulator is currently enabled
+ * or if the regulator has been configured to always send voltage
+ * updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -709,6 +715,61 @@
+ RPM_REGULATOR_CORNER_NONE;
}
+static int rpm_vreg_set_voltage_floor_corner(struct regulator_dev *rdev,
+ int min_uV, int max_uV, unsigned *selector)
+{
+ struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+ int rc = 0;
+ int corner;
+ u32 prev_corner;
+
+ /*
+ * Translate from values which work as inputs in the
+ * regulator_set_voltage function to the actual corner values
+ * sent to the RPM.
+ */
+ corner = min_uV - RPM_REGULATOR_CORNER_NONE;
+
+ if (corner < params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min
+ || corner > params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max) {
+ vreg_err(reg, "corner=%d is not within allowed range: [%u, %u]\n",
+ corner, params[RPM_REGULATOR_PARAM_FLOOR_CORNER].min,
+ params[RPM_REGULATOR_PARAM_FLOOR_CORNER].max);
+ return -EINVAL;
+ }
+
+ rpm_vreg_lock(reg->rpm_vreg);
+
+ prev_corner = reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER];
+ RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, corner);
+
+ /*
+ * Only send a new voltage floor corner if the regulator is currently
+ * enabled or if the regulator has been configured to always send
+ * voltage updates.
+ */
+ if (reg->always_send_voltage
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ rc = rpm_vreg_aggregate_requests(reg);
+
+ if (rc) {
+ vreg_err(reg, "set voltage corner failed, rc=%d", rc);
+ RPM_VREG_SET_PARAM(reg, FLOOR_CORNER, prev_corner);
+ }
+
+ rpm_vreg_unlock(reg->rpm_vreg);
+
+ return rc;
+}
+
+static int rpm_vreg_get_voltage_floor_corner(struct regulator_dev *rdev)
+{
+ struct rpm_regulator *reg = rdev_get_drvdata(rdev);
+
+ return reg->req.param[RPM_REGULATOR_PARAM_FLOOR_CORNER]
+ + RPM_REGULATOR_CORNER_NONE;
+}
+
static int rpm_vreg_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct rpm_regulator *reg = rdev_get_drvdata(rdev);
@@ -737,8 +798,13 @@
return -EINVAL;
}
- /* Only send a new mode value if the regulator is currently enabled. */
- if (rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+ /*
+ * Only send a new load current value if the regulator is currently
+ * enabled or if the regulator has been configured to always send
+ * current updates.
+ */
+ if (reg->always_send_current
+ || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
rc = rpm_vreg_aggregate_requests(reg);
if (rc) {
@@ -1035,6 +1101,18 @@
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops ldo_floor_corner_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage_floor_corner,
+ .get_voltage = rpm_vreg_get_voltage_floor_corner,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops smps_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1059,6 +1137,18 @@
.enable_time = rpm_vreg_enable_time,
};
+static struct regulator_ops smps_floor_corner_ops = {
+ .enable = rpm_vreg_enable,
+ .disable = rpm_vreg_disable,
+ .is_enabled = rpm_vreg_is_enabled,
+ .set_voltage = rpm_vreg_set_voltage_floor_corner,
+ .get_voltage = rpm_vreg_get_voltage_floor_corner,
+ .set_mode = rpm_vreg_set_mode,
+ .get_mode = rpm_vreg_get_mode,
+ .get_optimum_mode = rpm_vreg_get_optimum_mode,
+ .enable_time = rpm_vreg_enable_time,
+};
+
static struct regulator_ops switch_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
@@ -1192,12 +1282,30 @@
* is specified in the device node (SMPS and LDO only).
*/
if (of_property_read_bool(node, "qcom,use-voltage-corner")) {
+ if (of_property_read_bool(node,
+ "qcom,use-voltage-floor-corner")) {
+ dev_err(dev, "%s: invalid properties: both qcom,use-voltage-corner and qcom,use-voltage-floor-corner specified\n",
+ __func__);
+ goto fail_free_reg;
+ }
+
if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
reg->rdesc.ops = &smps_corner_ops;
else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
reg->rdesc.ops = &ldo_corner_ops;
+ } else if (of_property_read_bool(node,
+ "qcom,use-voltage-floor-corner")) {
+ if (regulator_type == RPM_REGULATOR_SMD_TYPE_SMPS)
+ reg->rdesc.ops = &smps_floor_corner_ops;
+ else if (regulator_type == RPM_REGULATOR_SMD_TYPE_LDO)
+ reg->rdesc.ops = &ldo_floor_corner_ops;
}
+ reg->always_send_voltage
+ = of_property_read_bool(node, "qcom,always-send-voltage");
+ reg->always_send_current
+ = of_property_read_bool(node, "qcom,always-send-current");
+
if (regulator_type == RPM_REGULATOR_SMD_TYPE_VS)
reg->rdesc.n_voltages = 0;
else
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index f73055e..b7271bb 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,23 @@
#define PAS_SHUTDOWN_CMD 6
#define PAS_IS_SUPPORTED_CMD 7
+enum scm_clock_ids {
+ BUS_CLK = 0,
+ CORE_CLK,
+ IFACE_CLK,
+ CORE_CLK_SRC,
+ NUM_CLKS
+};
+
+static const char * const scm_clock_names[NUM_CLKS] = {
+ [BUS_CLK] = "bus_clk",
+ [CORE_CLK] = "core_clk",
+ [IFACE_CLK] = "iface_clk",
+ [CORE_CLK_SRC] = "core_clk_src",
+};
+
+static struct clk *scm_clocks[NUM_CLKS];
+
int pas_init_image(enum pas_id id, const u8 *metadata, size_t size)
{
int ret;
@@ -108,14 +125,13 @@
};
static uint32_t scm_perf_client;
-static struct clk *scm_bus_clk;
static DEFINE_MUTEX(scm_pas_bw_mutex);
static int scm_pas_bw_count;
static int scm_pas_enable_bw(void)
{
- int ret = 0;
+ int ret = 0, i;
if (!scm_perf_client)
return -EINVAL;
@@ -123,30 +139,40 @@
mutex_lock(&scm_pas_bw_mutex);
if (!scm_pas_bw_count) {
ret = msm_bus_scale_client_update_request(scm_perf_client, 1);
- if (ret) {
- pr_err("bandwidth request failed (%d)\n", ret);
- } else if (scm_bus_clk) {
- ret = clk_prepare_enable(scm_bus_clk);
- if (ret)
- pr_err("clock enable failed\n");
- }
- }
- if (ret)
- msm_bus_scale_client_update_request(scm_perf_client, 0);
- else
+ if (ret)
+ goto err_bus;
scm_pas_bw_count++;
+ }
+ for (i = 0; i < NUM_CLKS; i++)
+ if (clk_prepare_enable(scm_clocks[i]))
+ goto err_clk;
+
+ mutex_unlock(&scm_pas_bw_mutex);
+ return ret;
+
+err_clk:
+ pr_err("clk prepare_enable failed (%s)\n", scm_clock_names[i]);
+ for (i--; i >= 0; i--)
+ clk_disable_unprepare(scm_clocks[i]);
+
+err_bus:
+ pr_err("bandwidth request failed (%d)\n", ret);
+ msm_bus_scale_client_update_request(scm_perf_client, 0);
+
mutex_unlock(&scm_pas_bw_mutex);
return ret;
}
static void scm_pas_disable_bw(void)
{
+ int i;
mutex_lock(&scm_pas_bw_mutex);
if (scm_pas_bw_count-- == 1) {
msm_bus_scale_client_update_request(scm_perf_client, 0);
- if (scm_bus_clk)
- clk_disable_unprepare(scm_bus_clk);
}
+ for (i = NUM_CLKS - 1; i >= 0; i--)
+ clk_disable_unprepare(scm_clocks[i]);
+
mutex_unlock(&scm_pas_bw_mutex);
}
@@ -214,17 +240,25 @@
static int __init scm_pas_init(void)
{
- if (cpu_is_msm8974()) {
+ int i, rate;
+ for (i = 0; i < NUM_CLKS; i++) {
+ scm_clocks[i] = clk_get_sys("scm", scm_clock_names[i]);
+ if (IS_ERR(scm_clocks[i]))
+ scm_clocks[i] = NULL;
+ }
+
+ /* Fail silently if this clock is not supported */
+ rate = clk_round_rate(scm_clocks[CORE_CLK_SRC], 1);
+ clk_set_rate(scm_clocks[CORE_CLK_SRC], rate);
+
+ if (cpu_is_msm8974() || cpu_is_msm8226()) {
scm_pas_bw_tbl[0].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
scm_pas_bw_tbl[1].vectors[0].src = MSM_BUS_MASTER_CRYPTO_CORE0;
} else {
- scm_bus_clk = clk_get_sys("scm", "bus_clk");
- if (!IS_ERR(scm_bus_clk)) {
- clk_set_rate(scm_bus_clk, 64000000);
- } else {
- scm_bus_clk = NULL;
+ if (!IS_ERR(scm_clocks[BUS_CLK]))
+ clk_set_rate(scm_clocks[BUS_CLK], 64000000);
+ else
pr_warn("unable to get bus clock\n");
- }
}
scm_perf_client = msm_bus_scale_register_client(&scm_pas_bus_pdata);
diff --git a/arch/arm/mach-msm/scm-xpu.c b/arch/arm/mach-msm/scm-xpu.c
new file mode 100644
index 0000000..0c38842
--- /dev/null
+++ b/arch/arm/mach-msm/scm-xpu.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <mach/scm.h>
+
+#define ERR_FATAL_ENABLE 0x0
+#define ERR_FATAL_DISABLE 0x1
+#define ERR_FATAL_READ 0x2
+#define XPU_ERR_FATAL 0xe
+
+static int __init xpu_err_fatal_init(void)
+{
+ int ret, response;
+ struct {
+ unsigned int config;
+ unsigned int spare;
+ } cmd;
+ cmd.config = ERR_FATAL_ENABLE;
+ cmd.spare = 0;
+
+ ret = scm_call(SCM_SVC_MP, XPU_ERR_FATAL, &cmd, sizeof(cmd), &response,
+ sizeof(response));
+
+ if (ret != 0)
+ pr_warn("Failed to set XPU violations as fatal errors: %d\n",
+ ret);
+ else
+ pr_info("Configuring XPU violations to be fatal errors\n");
+
+ return ret;
+}
+early_initcall(xpu_err_fatal_init);
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index 8066005..7bdcce9 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -1599,8 +1599,8 @@
*/
static int __devinit msm_smp2p_probe(struct platform_device *pdev)
{
- struct resource *irq_out_base;
- struct resource *irq_offset;
+ struct resource *r;
+ void *irq_out_ptr;
char *key;
uint32_t edge;
int ret;
@@ -1617,15 +1617,18 @@
goto fail;
}
- key = "irq-reg-base";
- irq_out_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
- if (!irq_out_base)
- goto missing_key;
-
- key = "irq-reg-offset";
- irq_offset = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
- if (!irq_offset)
- goto missing_key;
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ SMP2P_ERR("%s: failed gathering irq-reg resource for edge %d\n"
+ , __func__, edge);
+ goto fail;
+ }
+ irq_out_ptr = ioremap_nocache(r->start, resource_size(r));
+ if (!irq_out_ptr) {
+ SMP2P_ERR("%s: failed remap from phys to virt for edge %d\n",
+ __func__, edge);
+ return -ENOMEM;
+ }
key = "qcom,irq-bitmask";
ret = of_property_read_u32(node, key, &irq_bitmask);
@@ -1656,9 +1659,7 @@
*/
smp2p_int_cfgs[edge].in_int_id = irq_line;
smp2p_int_cfgs[edge].out_int_mask = irq_bitmask;
- smp2p_int_cfgs[edge].out_int_ptr =
- (uint32_t *)((uint32_t)irq_out_base->start +
- (uint32_t)irq_offset->start);
+ smp2p_int_cfgs[edge].out_int_ptr = irq_out_ptr;
smp2p_int_cfgs[edge].is_configured = true;
return 0;
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index efbd8c6..1f0fa85 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -44,6 +44,7 @@
HW_PLATFORM_LIQUID = 9,
/* Dragonboard platform id is assigned as 10 in CDT */
HW_PLATFORM_DRAGON = 10,
+ HW_PLATFORM_QRD = 11,
HW_PLATFORM_HRD = 13,
HW_PLATFORM_DTV = 14,
HW_PLATFORM_INVALID
@@ -59,6 +60,7 @@
[HW_PLATFORM_MTP] = "MTP",
[HW_PLATFORM_LIQUID] = "Liquid",
[HW_PLATFORM_DRAGON] = "Dragon",
+ [HW_PLATFORM_QRD] = "QRD",
[HW_PLATFORM_HRD] = "HRD",
[HW_PLATFORM_DTV] = "DTV",
};
@@ -249,6 +251,7 @@
[105] = MSM_CPU_9615,
[106] = MSM_CPU_9615,
[107] = MSM_CPU_9615,
+ [171] = MSM_CPU_9615,
/* 8064 IDs */
[109] = MSM_CPU_8064,
@@ -275,6 +278,7 @@
/* 8974 IDs */
[126] = MSM_CPU_8974,
+ [184] = MSM_CPU_8974,
/* 8625 IDs */
[127] = MSM_CPU_8625,
diff --git a/arch/arm/mach-msm/spm-regulator.c b/arch/arm/mach-msm/spm-regulator.c
new file mode 100644
index 0000000..00817c0
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.c
@@ -0,0 +1,405 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include "spm.h"
+#include "spm-regulator.h"
+
+#define SPM_REGULATOR_DRIVER_NAME "qcom,spm-regulator"
+
+struct voltage_range {
+ int min_uV;
+ int set_point_min_uV;
+ int max_uV;
+ int step_uV;
+};
+
+/* Properties for FTS2 type QPNP PMIC regulators. */
+
+static const struct voltage_range fts2_range0 = {0, 350000, 1275000, 5000};
+static const struct voltage_range fts2_range1 = {0, 700000, 2040000, 10000};
+
+/* Specifies the PMIC internal slew rate in uV/us. */
+#define QPNP_FTS2_SLEW_RATE 6000
+
+#define QPNP_FTS2_REG_TYPE 0x04
+#define QPNP_FTS2_REG_SUBTYPE 0x05
+#define QPNP_FTS2_REG_VOLTAGE_RANGE 0x40
+#define QPNP_FTS2_REG_VOLTAGE_SETPOINT 0x41
+
+#define QPNP_FTS2_TYPE 0x1C
+#define QPNP_FTS2_SUBTYPE 0x08
+
+struct spm_vreg {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+ struct spmi_device *spmi_dev;
+ const struct voltage_range *range;
+ int uV;
+ int last_set_uV;
+ unsigned vlevel;
+ unsigned last_set_vlevel;
+ bool online;
+ u16 spmi_base_addr;
+};
+
+static int _spm_regulator_set_voltage(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ if (vreg->vlevel == vreg->last_set_vlevel)
+ return 0;
+
+ rc = msm_spm_apcs_set_vdd(vreg->vlevel);
+ if (rc) {
+ pr_err("%s: msm_spm_set_vdd failed %d\n", vreg->rdesc.name, rc);
+ return rc;
+ }
+
+ if (vreg->uV > vreg->last_set_uV) {
+ /* Wait for voltage to stabalize. */
+ udelay(DIV_ROUND_UP(vreg->uV - vreg->last_set_uV,
+ QPNP_FTS2_SLEW_RATE));
+ }
+ vreg->last_set_uV = vreg->uV;
+ vreg->last_set_vlevel = vreg->vlevel;
+
+ return rc;
+}
+
+static int spm_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ const struct voltage_range *range = vreg->range;
+ int uV = min_uV;
+ unsigned vlevel;
+
+ if (uV < range->set_point_min_uV && max_uV >= range->set_point_min_uV)
+ uV = range->set_point_min_uV;
+
+ if (uV < range->set_point_min_uV || uV > range->max_uV) {
+ pr_err("%s: request v=[%d, %d] is outside possible v=[%d, %d]\n",
+ vreg->rdesc.name, min_uV, max_uV,
+ range->set_point_min_uV, range->max_uV);
+ return -EINVAL;
+ }
+
+ vlevel = DIV_ROUND_UP(uV - range->min_uV, range->step_uV);
+ uV = vlevel * range->step_uV + range->min_uV;
+
+ if (uV > max_uV) {
+ pr_err("%s: request v=[%d, %d] cannot be met by any set point\n",
+ vreg->rdesc.name, min_uV, max_uV);
+ return -EINVAL;
+ }
+
+ vreg->vlevel = vlevel;
+ vreg->uV = uV;
+ *selector = vlevel -
+ (vreg->range->set_point_min_uV - vreg->range->min_uV)
+ / vreg->range->step_uV;
+
+ if (!vreg->online)
+ return 0;
+
+ return _spm_regulator_set_voltage(rdev);
+}
+
+static int spm_regulator_get_voltage(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->uV;
+}
+
+static int spm_regulator_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ if (selector >= vreg->rdesc.n_voltages)
+ return 0;
+
+ return selector * vreg->range->step_uV + vreg->range->set_point_min_uV;
+}
+
+static int spm_regulator_enable(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+ int rc;
+
+ rc = _spm_regulator_set_voltage(rdev);
+
+ if (!rc)
+ vreg->online = true;
+
+ return rc;
+}
+
+static int spm_regulator_disable(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ vreg->online = false;
+
+ return 0;
+}
+
+static int spm_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct spm_vreg *vreg = rdev_get_drvdata(rdev);
+
+ return vreg->online;
+}
+
+static struct regulator_ops spm_regulator_ops = {
+ .get_voltage = spm_regulator_get_voltage,
+ .set_voltage = spm_regulator_set_voltage,
+ .list_voltage = spm_regulator_list_voltage,
+ .enable = spm_regulator_enable,
+ .disable = spm_regulator_disable,
+ .is_enabled = spm_regulator_is_enabled,
+};
+
+static int qpnp_fts2_check_type(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 type[2];
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_TYPE, type, 2);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (type[0] != QPNP_FTS2_TYPE || type[1] != QPNP_FTS2_SUBTYPE) {
+ dev_err(&vreg->spmi_dev->dev, "%s: invalid type=0x%02X or subtype=0x%02X register value\n",
+ __func__, type[0], type[1]);
+ return -ENODEV;
+ }
+
+ return rc;
+}
+
+static int qpnp_fts2_init_range(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 reg = 0;
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_RANGE, ®, 1);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage range register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ if (reg == 0x00) {
+ vreg->range = &fts2_range0;
+ } else if (reg == 0x01) {
+ vreg->range = &fts2_range1;
+ } else {
+ dev_err(&vreg->spmi_dev->dev, "%s: voltage range=%d is invalid\n",
+ __func__, reg);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static int qpnp_fts2_init_voltage(struct spm_vreg *vreg)
+{
+ int rc;
+ u8 reg = 0;
+
+ rc = spmi_ext_register_readl(vreg->spmi_dev->ctrl, vreg->spmi_dev->sid,
+ vreg->spmi_base_addr + QPNP_FTS2_REG_VOLTAGE_SETPOINT, ®, 1);
+ if (rc) {
+ dev_err(&vreg->spmi_dev->dev, "%s: could not read voltage setpoint register, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vreg->vlevel = reg;
+ vreg->uV = vreg->vlevel * vreg->range->step_uV + vreg->range->min_uV;
+ vreg->last_set_uV = vreg->uV;
+
+ return rc;
+}
+
+static int __devinit spm_regulator_probe(struct spmi_device *spmi)
+{
+ struct device_node *node = spmi->dev.of_node;
+ struct regulator_init_data *init_data;
+ struct spm_vreg *vreg;
+ struct resource *res;
+ int rc;
+
+ if (!node) {
+ dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+ return -ENODEV;
+ }
+
+ vreg = devm_kzalloc(&spmi->dev, sizeof(*vreg), GFP_KERNEL);
+ if (!vreg) {
+ pr_err("allocation failed.\n");
+ return -ENOMEM;
+ }
+ vreg->spmi_dev = spmi;
+
+ res = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&spmi->dev, "%s: node is missing base address\n",
+ __func__);
+ return -EINVAL;
+ }
+ vreg->spmi_base_addr = res->start;
+
+ rc = qpnp_fts2_check_type(vreg);
+ if (rc)
+ return rc;
+
+ /*
+ * The FTS2 regulator must be initialized to range 0 or range 1 during
+ * PMIC power on sequence. Once it is set, it cannot be changed
+ * dynamically.
+ */
+ rc = qpnp_fts2_init_range(vreg);
+ if (rc)
+ return rc;
+
+ rc = qpnp_fts2_init_voltage(vreg);
+ if (rc)
+ return rc;
+
+ init_data = of_get_regulator_init_data(&spmi->dev, node);
+ if (!init_data) {
+ dev_err(&spmi->dev, "%s: unable to allocate memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ init_data->constraints.input_uV = init_data->constraints.max_uV;
+ init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_STATUS
+ | REGULATOR_CHANGE_VOLTAGE;
+
+ if (!init_data->constraints.name) {
+ dev_err(&spmi->dev, "%s: node is missing regulator name\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ vreg->rdesc.name = init_data->constraints.name;
+ vreg->rdesc.type = REGULATOR_VOLTAGE;
+ vreg->rdesc.owner = THIS_MODULE;
+ vreg->rdesc.ops = &spm_regulator_ops;
+ vreg->rdesc.n_voltages
+ = (vreg->range->max_uV - vreg->range->set_point_min_uV)
+ / vreg->range->step_uV + 1;
+
+ vreg->rdev = regulator_register(&vreg->rdesc, &spmi->dev,
+ init_data, vreg, node);
+ if (IS_ERR(vreg->rdev)) {
+ rc = PTR_ERR(vreg->rdev);
+ dev_err(&spmi->dev, "%s: regulator_register failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ dev_set_drvdata(&spmi->dev, vreg);
+
+ pr_info("name=%s, range=%d\n", vreg->rdesc.name,
+ (vreg->range == &fts2_range0) ? 0 : 1);
+
+ return rc;
+}
+
+static int __devexit spm_regulator_remove(struct spmi_device *spmi)
+{
+ struct spm_vreg *vreg = dev_get_drvdata(&spmi->dev);
+
+ regulator_unregister(vreg->rdev);
+
+ return 0;
+}
+
+static struct of_device_id spm_regulator_match_table[] = {
+ { .compatible = SPM_REGULATOR_DRIVER_NAME, },
+ {}
+};
+
+static const struct spmi_device_id spm_regulator_id[] = {
+ { SPM_REGULATOR_DRIVER_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(spmi, spm_regulator_id);
+
+static struct spmi_driver spm_regulator_driver = {
+ .driver = {
+ .name = SPM_REGULATOR_DRIVER_NAME,
+ .of_match_table = spm_regulator_match_table,
+ .owner = THIS_MODULE,
+ },
+ .probe = spm_regulator_probe,
+ .remove = __devexit_p(spm_regulator_remove),
+ .id_table = spm_regulator_id,
+};
+
+/**
+ * spm_regulator_init() - register spmi driver for spm-regulator
+ *
+ * This initialization function should be called in systems in which driver
+ * registration ordering must be controlled precisely.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init spm_regulator_init(void)
+{
+ static bool has_registered;
+
+ if (has_registered)
+ return 0;
+ else
+ has_registered = true;
+
+ return spmi_driver_register(&spm_regulator_driver);
+}
+EXPORT_SYMBOL(spm_regulator_init);
+
+static void __exit spm_regulator_exit(void)
+{
+ spmi_driver_unregister(&spm_regulator_driver);
+}
+
+arch_initcall(spm_regulator_init);
+module_exit(spm_regulator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("SPM regulator driver");
+MODULE_ALIAS("platform:spm-regulator");
diff --git a/arch/arm/mach-msm/spm-regulator.h b/arch/arm/mach-msm/spm-regulator.h
new file mode 100644
index 0000000..394aecc
--- /dev/null
+++ b/arch/arm/mach-msm/spm-regulator.h
@@ -0,0 +1,25 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+#define _ARCH_ARM_MACH_MSM_SPM_REGULATOR_H
+
+#include <linux/err.h>
+#include <linux/init.h>
+
+#ifdef CONFIG_MSM_SPM_REGULATOR
+int __init spm_regulator_init(void);
+#else
+static inline int __init spm_regulator_init(void) { return -ENODEV; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index c8e2dd3..233c5a5 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -33,6 +33,7 @@
};
struct msm_spm_device {
+ bool initialized;
struct msm_spm_driver_data reg_data;
struct msm_spm_power_modes *modes;
uint32_t num_modes;
@@ -55,6 +56,8 @@
struct msm_spm_vdd_info *info = (struct msm_spm_vdd_info *)data;
dev = &per_cpu(msm_cpu_spm_device, info->cpu);
+ if (!dev->initialized)
+ return;
dev->cpu_vdd = info->vlevel;
info->err = msm_spm_drv_set_vdd(&dev->reg_data, info->vlevel);
}
@@ -119,6 +122,9 @@
uint32_t start_addr = 0;
int ret = -EINVAL;
+ if (!dev->initialized)
+ return -ENXIO;
+
if (mode == MSM_SPM_MODE_DISABLED) {
ret = msm_spm_drv_set_spm_enable(&dev->reg_data, false);
} else if (!msm_spm_drv_set_spm_enable(&dev->reg_data, true)) {
@@ -170,6 +176,7 @@
dev->modes[i].notify_rpm = data->modes[i].notify_rpm;
}
msm_spm_drv_flush_seq_entry(&dev->reg_data);
+ dev->initialized = true;
return 0;
spm_failed_init:
@@ -278,6 +285,8 @@
void msm_spm_l2_reinit(void)
{
+ if (!msm_spm_l2_device.initialized)
+ return;
msm_spm_drv_reinit(&msm_spm_l2_device.reg_data);
}
EXPORT_SYMBOL(msm_spm_l2_reinit);
@@ -288,6 +297,8 @@
*/
int msm_spm_apcs_set_vdd(unsigned int vlevel)
{
+ if (!msm_spm_l2_device.initialized)
+ return -ENXIO;
return msm_spm_drv_set_vdd(&msm_spm_l2_device.reg_data, vlevel);
}
EXPORT_SYMBOL(msm_spm_apcs_set_vdd);
@@ -298,6 +309,8 @@
*/
int msm_spm_apcs_set_phase(unsigned int phase_cnt)
{
+ if (!msm_spm_l2_device.initialized)
+ return -ENXIO;
return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
MSM_SPM_PMIC_PHASE_PORT, phase_cnt);
}
@@ -309,6 +322,8 @@
*/
int msm_spm_enable_fts_lpm(uint32_t mode)
{
+ if (!msm_spm_l2_device.initialized)
+ return -ENXIO;
return msm_spm_drv_set_pmic_data(&msm_spm_l2_device.reg_data,
MSM_SPM_PMIC_PFM_PORT, mode);
}
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
index 11dc436..84e8df5 100644
--- a/arch/arm/mach-msm/tz_log.c
+++ b/arch/arm/mach-msm/tz_log.c
@@ -708,23 +708,18 @@
*/
tzdiag_phy_iobase = readl_relaxed(virt_iobase);
- if (!pdev->dev.of_node) {
+ /*
+ * Map the 4KB diagnostic information area
+ */
+ tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+ tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
- /*
- * Map the 4KB diagnostic information area
- */
- tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
- tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
-
- if (!tzdbg.virt_iobase) {
- dev_err(&pdev->dev,
- "%s: ERROR could not ioremap: start=%p, len=%u\n",
- __func__, (void *) tzdiag_phy_iobase,
- DEBUG_MAX_RW_BUF);
- return -ENXIO;
- }
- } else {
- tzdbg.virt_iobase = virt_iobase;
+ if (!tzdbg.virt_iobase) {
+ dev_err(&pdev->dev,
+ "%s: ERROR could not ioremap: start=%p, len=%u\n",
+ __func__, (void *) tzdiag_phy_iobase,
+ DEBUG_MAX_RW_BUF);
+ return -ENXIO;
}
ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 56a9a4a..1c8a25d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -22,6 +22,7 @@
#include <linux/memblock.h>
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <linux/io.h>
#include <linux/vmalloc.h>
#include <asm/memory.h>
@@ -230,116 +231,73 @@
}
#ifdef CONFIG_MMU
-
-#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
-#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT)
-
-/*
- * These are the page tables (2MB each) covering uncached, DMA consistent allocations
- */
-static pte_t **consistent_pte;
-
-#define DEFAULT_CONSISTENT_DMA_SIZE (7*SZ_2M)
-
-static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
-
-void __init init_consistent_dma_size(unsigned long size)
-{
- unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
-
- BUG_ON(consistent_pte); /* Check we're called before DMA region init */
- BUG_ON(base < VMALLOC_END);
-
- /* Grow region to accommodate specified size */
- if (base < consistent_base)
- consistent_base = base;
-}
-
-#include "vmregion.h"
-
-static struct arm_vmregion_head consistent_head = {
- .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
- .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
- .vm_end = CONSISTENT_END,
-};
-
#ifdef CONFIG_HUGETLB_PAGE
#error ARM Coherent DMA allocator does not (yet) support huge TLB
#endif
-/*
- * Initialise the consistent memory allocation.
- */
-static int __init consistent_init(void)
+static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
+ pgprot_t prot, struct page **ret_page,
+ const void *caller);
+
+static void *
+__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
+ const void *caller)
{
- int ret = 0;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- int i = 0;
- unsigned long base = consistent_base;
- unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
+ struct vm_struct *area;
+ unsigned long addr;
- if (IS_ENABLED(CONFIG_CMA) && !IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
- return 0;
+ /*
+ * DMA allocation can be mapped to user space, so lets
+ * set VM_USERMAP flags too.
+ */
+ area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
+ caller);
+ if (!area)
+ return NULL;
+ addr = (unsigned long)area->addr;
+ area->phys_addr = __pfn_to_phys(page_to_pfn(page));
- consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
- if (!consistent_pte) {
- pr_err("%s: no memory\n", __func__);
- return -ENOMEM;
+ if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
+ vunmap((void *)addr);
+ return NULL;
}
-
- pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
- consistent_head.vm_start = base;
-
- do {
- pgd = pgd_offset(&init_mm, base);
-
- pud = pud_alloc(&init_mm, pgd, base);
- if (!pud) {
- pr_err("%s: no pud tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
-
- pmd = pmd_alloc(&init_mm, pud, base);
- if (!pmd) {
- pr_err("%s: no pmd tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
- WARN_ON(!pmd_none(*pmd));
-
- pte = pte_alloc_kernel(pmd, base);
- if (!pte) {
- pr_err("%s: no pte tables\n", __func__);
- ret = -ENOMEM;
- break;
- }
-
- consistent_pte[i++] = pte;
- base += PMD_SIZE;
- } while (base < CONSISTENT_END);
-
- return ret;
+ return (void *)addr;
}
-core_initcall(consistent_init);
+
+static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
+{
+ unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
+ struct vm_struct *area = find_vm_area(cpu_addr);
+ if (!area || (area->flags & flags) != flags) {
+ if (!no_warn)
+ WARN(1, "trying to free invalid coherent area: %p\n",
+ cpu_addr);
+ return;
+ }
+ unmap_kernel_range((unsigned long)cpu_addr, size);
+ vunmap(cpu_addr);
+}
static void *__alloc_from_contiguous(struct device *dev, size_t size,
pgprot_t prot, struct page **ret_page,
bool no_kernel_mapping, const void *caller);
-static struct arm_vmregion_head coherent_head = {
- .vm_lock = __SPIN_LOCK_UNLOCKED(&coherent_head.vm_lock),
- .vm_list = LIST_HEAD_INIT(coherent_head.vm_list),
+struct dma_pool {
+ size_t size;
+ spinlock_t lock;
+ unsigned long *bitmap;
+ unsigned long nr_pages;
+ void *vaddr;
+ struct page *page;
};
-static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
+static struct dma_pool atomic_pool = {
+ .size = SZ_256K,
+};
static int __init early_coherent_pool(char *p)
{
- coherent_pool_size = memparse(p, &p);
+ atomic_pool.size = memparse(p, &p);
return 0;
}
early_param("coherent_pool", early_coherent_pool);
@@ -347,33 +305,46 @@
/*
* Initialise the coherent pool for atomic allocations.
*/
-static int __init coherent_init(void)
+static int __init atomic_pool_init(void)
{
+ struct dma_pool *pool = &atomic_pool;
pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
- size_t size = coherent_pool_size;
+ unsigned long nr_pages = pool->size >> PAGE_SHIFT;
+ unsigned long *bitmap;
struct page *page;
void *ptr;
+ int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
- if (!IS_ENABLED(CONFIG_CMA))
- return 0;
+ bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!bitmap)
+ goto no_bitmap;
- ptr = __alloc_from_contiguous(NULL, size, prot, &page, false,
- coherent_init);
+ if (IS_ENABLED(CONFIG_CMA))
+ ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
+ false, atomic_pool_init);
+ else
+ ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
+ &page, NULL);
if (ptr) {
- coherent_head.vm_start = (unsigned long) ptr;
- coherent_head.vm_end = (unsigned long) ptr + size;
- printk(KERN_INFO "DMA: preallocated %u KiB pool for atomic coherent allocations\n",
- (unsigned)size / 1024);
+ spin_lock_init(&pool->lock);
+ pool->vaddr = ptr;
+ pool->page = page;
+ pool->bitmap = bitmap;
+ pool->nr_pages = nr_pages;
+ pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
+ (unsigned)pool->size / 1024);
return 0;
}
- printk(KERN_ERR "DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
- (unsigned)size / 1024);
+ kfree(bitmap);
+no_bitmap:
+ pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
+ (unsigned)pool->size / 1024);
return -ENOMEM;
}
/*
* CMA is activated by core_initcall, so we must be called after it.
*/
-postcore_initcall(coherent_init);
+postcore_initcall(atomic_pool_init);
struct dma_contig_early_reserve {
phys_addr_t base;
@@ -421,114 +392,6 @@
}
}
-static void *
-__dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
- const void *caller)
-{
- struct arm_vmregion *c;
- size_t align;
- int bit;
-
- if (!consistent_pte) {
- pr_err("%s: not initialised\n", __func__);
- dump_stack();
- return NULL;
- }
-
- /*
- * Align the virtual region allocation - maximum alignment is
- * a section size, minimum is a page size. This helps reduce
- * fragmentation of the DMA space, and also prevents allocations
- * smaller than a section from crossing a section boundary.
- */
- bit = fls(size - 1);
- if (bit > SECTION_SHIFT)
- bit = SECTION_SHIFT;
- align = 1 << bit;
-
- /*
- * Allocate a virtual address in the consistent mapping region.
- */
- c = arm_vmregion_alloc(&consistent_head, align, size,
- gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller);
- if (c) {
- pte_t *pte;
- int idx = CONSISTENT_PTE_INDEX(c->vm_start);
- u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
-
- pte = consistent_pte[idx] + off;
- c->priv = page;
-
- do {
- BUG_ON(!pte_none(*pte));
-
- set_pte_ext(pte, mk_pte(page, prot), 0);
- page++;
- pte++;
- off++;
- if (off >= PTRS_PER_PTE) {
- off = 0;
- pte = consistent_pte[++idx];
- }
- } while (size -= PAGE_SIZE);
-
- dsb();
-
- return (void *)c->vm_start;
- }
- return NULL;
-}
-
-static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
-{
- struct arm_vmregion *c;
- unsigned long addr;
- pte_t *ptep;
- int idx;
- u32 off;
-
- c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr);
- if (!c) {
- if (!no_warn) {
- pr_err("%s: trying to free invalid coherent area: %p\n",
- __func__, cpu_addr);
- dump_stack();
- }
- return;
- }
-
- if ((c->vm_end - c->vm_start) != size) {
- pr_err("%s: freeing wrong coherent size (%ld != %d)\n",
- __func__, c->vm_end - c->vm_start, size);
- dump_stack();
- size = c->vm_end - c->vm_start;
- }
-
- idx = CONSISTENT_PTE_INDEX(c->vm_start);
- off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
- ptep = consistent_pte[idx] + off;
- addr = c->vm_start;
- do {
- pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
-
- ptep++;
- addr += PAGE_SIZE;
- off++;
- if (off >= PTRS_PER_PTE) {
- off = 0;
- ptep = consistent_pte[++idx];
- }
-
- if (pte_none(pte) || !pte_present(pte))
- pr_crit("%s: bad page in kernel page table\n",
- __func__);
- } while (size -= PAGE_SIZE);
-
- flush_tlb_kernel_range(c->vm_start, c->vm_end);
-
- arm_vmregion_free(&consistent_head, c);
-}
-
static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr,
void *data)
{
@@ -584,16 +447,17 @@
return ptr;
}
-static void *__alloc_from_pool(struct device *dev, size_t size,
- struct page **ret_page, const void *caller)
+static void *__alloc_from_pool(size_t size, struct page **ret_page)
{
- struct arm_vmregion *c;
+ struct dma_pool *pool = &atomic_pool;
+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ unsigned int pageno;
+ unsigned long flags;
+ void *ptr = NULL;
size_t align;
- if (!coherent_head.vm_start) {
- printk(KERN_ERR "%s: coherent pool not initialised!\n",
- __func__);
- dump_stack();
+ if (!pool->vaddr) {
+ WARN(1, "coherent pool not initialised!\n");
return NULL;
}
@@ -603,35 +467,41 @@
* size. This helps reduce fragmentation of the DMA space.
*/
align = PAGE_SIZE << get_order(size);
- c = arm_vmregion_alloc(&coherent_head, align, size, 0, caller);
- if (c) {
- void *ptr = (void *)c->vm_start;
- struct page *page = virt_to_page(ptr);
- *ret_page = page;
- return ptr;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ pageno = bitmap_find_next_zero_area(pool->bitmap, pool->nr_pages,
+ 0, count, (1 << align) - 1);
+ if (pageno < pool->nr_pages) {
+ bitmap_set(pool->bitmap, pageno, count);
+ ptr = pool->vaddr + PAGE_SIZE * pageno;
+ *ret_page = pool->page + pageno;
}
- return NULL;
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ return ptr;
}
-static int __free_from_pool(void *cpu_addr, size_t size)
+static int __free_from_pool(void *start, size_t size)
{
- unsigned long start = (unsigned long)cpu_addr;
- unsigned long end = start + size;
- struct arm_vmregion *c;
+ struct dma_pool *pool = &atomic_pool;
+ unsigned long pageno, count;
+ unsigned long flags;
- if (start < coherent_head.vm_start || end > coherent_head.vm_end)
+ if (start < pool->vaddr || start > pool->vaddr + pool->size)
return 0;
- c = arm_vmregion_find_remove(&coherent_head, (unsigned long)start);
-
- if ((c->vm_end - c->vm_start) != size) {
- printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
- __func__, c->vm_end - c->vm_start, size);
- dump_stack();
- size = c->vm_end - c->vm_start;
+ if (start + size > pool->vaddr + pool->size) {
+ WARN(1, "freeing wrong coherent size from pool\n");
+ return 0;
}
- arm_vmregion_free(&coherent_head, c);
+ pageno = (start - pool->vaddr) >> PAGE_SHIFT;
+ count = size >> PAGE_SHIFT;
+
+ spin_lock_irqsave(&pool->lock, flags);
+ bitmap_clear(pool->bitmap, pageno, count);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
return 1;
}
@@ -766,10 +636,10 @@
if (arch_is_coherent() || nommu())
addr = __alloc_simple_buffer(dev, size, gfp, &page);
+ else if (gfp & GFP_ATOMIC)
+ addr = __alloc_from_pool(size, &page);
else if (!IS_ENABLED(CONFIG_CMA))
addr = __alloc_remap_buffer(dev, size, gfp, prot, &page, caller);
- else if (gfp & GFP_ATOMIC)
- addr = __alloc_from_pool(dev, size, &page, caller);
else
addr = __alloc_from_contiguous(dev, size, prot, &page,
no_kernel_mapping, caller);
@@ -838,12 +708,12 @@
if (arch_is_coherent() || nommu()) {
__dma_free_buffer(page, size);
+ } else if (__free_from_pool(cpu_addr, size)) {
+ return;
} else if (!IS_ENABLED(CONFIG_CMA)) {
__dma_free_remap(cpu_addr, size, false);
__dma_free_buffer(page, size);
} else {
- if (__free_from_pool(cpu_addr, size))
- return;
/*
* Non-atomic allocations cannot be freed with IRQs disabled
*/
@@ -1067,9 +937,6 @@
static int __init dma_debug_do_init(void)
{
-#ifdef CONFIG_MMU
- arm_vmregion_create_proc("dma-mappings", &consistent_head);
-#endif
dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
return 0;
}
@@ -1186,61 +1053,32 @@
* Create a CPU mapping for a specified pages
*/
static void *
-__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot)
+__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot,
+ const void *caller)
{
- struct arm_vmregion *c;
- size_t align;
- size_t count = size >> PAGE_SHIFT;
- int bit;
+ unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ struct vm_struct *area;
+ unsigned long p;
- if (!consistent_pte[0]) {
- pr_err("%s: not initialised\n", __func__);
- dump_stack();
+ area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
+ caller);
+ if (!area)
return NULL;
+
+ area->pages = pages;
+ area->nr_pages = nr_pages;
+ p = (unsigned long)area->addr;
+
+ for (i = 0; i < nr_pages; i++) {
+ phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i]));
+ if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot))
+ goto err;
+ p += PAGE_SIZE;
}
-
- /*
- * Align the virtual region allocation - maximum alignment is
- * a section size, minimum is a page size. This helps reduce
- * fragmentation of the DMA space, and also prevents allocations
- * smaller than a section from crossing a section boundary.
- */
- bit = fls(size - 1);
- if (bit > SECTION_SHIFT)
- bit = SECTION_SHIFT;
- align = 1 << bit;
-
- /*
- * Allocate a virtual address in the consistent mapping region.
- */
- c = arm_vmregion_alloc(&consistent_head, align, size,
- gfp & ~(__GFP_DMA | __GFP_HIGHMEM), NULL);
- if (c) {
- pte_t *pte;
- int idx = CONSISTENT_PTE_INDEX(c->vm_start);
- int i = 0;
- u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
-
- pte = consistent_pte[idx] + off;
- c->priv = pages;
-
- do {
- BUG_ON(!pte_none(*pte));
-
- set_pte_ext(pte, mk_pte(pages[i], prot), 0);
- pte++;
- off++;
- i++;
- if (off >= PTRS_PER_PTE) {
- off = 0;
- pte = consistent_pte[++idx];
- }
- } while (i < count);
-
- dsb();
-
- return (void *)c->vm_start;
- }
+ return area->addr;
+err:
+ unmap_kernel_range((unsigned long)area->addr, size);
+ vunmap(area->addr);
return NULL;
}
@@ -1299,6 +1137,16 @@
return 0;
}
+static struct page **__iommu_get_pages(void *cpu_addr)
+{
+ struct vm_struct *area;
+
+ area = find_vm_area(cpu_addr);
+ if (area && (area->flags & VM_ARM_DMA_CONSISTENT))
+ return area->pages;
+ return NULL;
+}
+
static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
{
@@ -1317,7 +1165,8 @@
if (*handle == DMA_ERROR_CODE)
goto err_buffer;
- addr = __iommu_alloc_remap(pages, size, gfp, prot);
+ addr = __iommu_alloc_remap(pages, size, gfp, prot,
+ __builtin_return_address(0));
if (!addr)
goto err_mapping;
@@ -1334,31 +1183,25 @@
void *cpu_addr, dma_addr_t dma_addr, size_t size,
struct dma_attrs *attrs)
{
- struct arm_vmregion *c;
+ unsigned long uaddr = vma->vm_start;
+ unsigned long usize = vma->vm_end - vma->vm_start;
+ struct page **pages = __iommu_get_pages(cpu_addr);
vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
- c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
- if (c) {
- struct page **pages = c->priv;
+ if (!pages)
+ return -ENXIO;
- unsigned long uaddr = vma->vm_start;
- unsigned long usize = vma->vm_end - vma->vm_start;
- int i = 0;
+ do {
+ int ret = vm_insert_page(vma, uaddr, *pages++);
+ if (ret) {
+ pr_err("Remapping memory failed: %d\n", ret);
+ return ret;
+ }
+ uaddr += PAGE_SIZE;
+ usize -= PAGE_SIZE;
+ } while (usize > 0);
- do {
- int ret;
-
- ret = vm_insert_page(vma, uaddr, pages[i++]);
- if (ret) {
- pr_err("Remapping memory, error: %d\n", ret);
- return ret;
- }
-
- uaddr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- } while (usize > 0);
- }
return 0;
}
@@ -1369,16 +1212,19 @@
void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t handle, struct dma_attrs *attrs)
{
- struct arm_vmregion *c;
+ struct page **pages = __iommu_get_pages(cpu_addr);
size = PAGE_ALIGN(size);
- c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
- if (c) {
- struct page **pages = c->priv;
- __dma_free_remap(cpu_addr, size, false);
- __iommu_remove_mapping(dev, handle, size);
- __iommu_free_buffer(dev, pages, size);
+ if (!pages) {
+ WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
+ return;
}
+
+ unmap_kernel_range((unsigned long)cpu_addr, size);
+ vunmap(cpu_addr);
+
+ __iommu_remove_mapping(dev, handle, size);
+ __iommu_free_buffer(dev, pages, size);
}
/*
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index f16f700..66567bb 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -375,11 +375,11 @@
return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
}
-unsigned long memory_hole_offset;
+phys_addr_t memory_hole_offset;
EXPORT_SYMBOL(memory_hole_offset);
-unsigned long memory_hole_start;
+phys_addr_t memory_hole_start;
EXPORT_SYMBOL(memory_hole_start);
-unsigned long memory_hole_end;
+phys_addr_t memory_hole_end;
EXPORT_SYMBOL(memory_hole_end);
unsigned long memory_hole_align;
EXPORT_SYMBOL(memory_hole_align);
@@ -390,8 +390,8 @@
void find_memory_hole(void)
{
int i;
- unsigned long hole_start;
- unsigned long hole_size;
+ phys_addr_t hole_start;
+ phys_addr_t hole_size;
unsigned long hole_end_virt;
/*
@@ -428,13 +428,13 @@
memory_hole_offset = memory_hole_start - PHYS_OFFSET;
if (!IS_ALIGNED(memory_hole_start, SECTION_SIZE)) {
- pr_err("memory_hole_start %lx is not aligned to %lx\n",
- memory_hole_start, SECTION_SIZE);
+ pr_err("memory_hole_start %pa is not aligned to %lx\n",
+ &memory_hole_start, SECTION_SIZE);
BUG();
}
if (!IS_ALIGNED(memory_hole_end, SECTION_SIZE)) {
- pr_err("memory_hole_end %lx is not aligned to %lx\n",
- memory_hole_end, SECTION_SIZE);
+ pr_err("memory_hole_end %pa is not aligned to %lx\n",
+ &memory_hole_end, SECTION_SIZE);
BUG();
}
@@ -444,8 +444,9 @@
IS_ALIGNED(memory_hole_end, PMD_SIZE)) ||
(IS_ALIGNED(hole_end_virt, PMD_SIZE) &&
!IS_ALIGNED(memory_hole_end, PMD_SIZE))) {
- memory_hole_align = max(hole_end_virt & ~PMD_MASK,
- memory_hole_end & ~PMD_MASK);
+ memory_hole_align = !IS_ALIGNED(hole_end_virt, PMD_SIZE) ?
+ hole_end_virt & ~PMD_MASK :
+ memory_hole_end & ~PMD_MASK;
virtual_hole_start = hole_end_virt;
virtual_hole_end = hole_end_virt + memory_hole_align;
pr_info("Physical memory hole is not aligned. There will be a virtual memory hole from %lx to %lx\n",
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index 87fa3f2..a8ee92d 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -62,6 +62,9 @@
#define VM_ARM_MTYPE(mt) ((mt) << 20)
#define VM_ARM_MTYPE_MASK (0x1f << 20)
+/* consistent regions used by dma_alloc_attrs() */
+#define VM_ARM_DMA_CONSISTENT 0x20000000
+
#endif
#ifdef CONFIG_ZONE_DMA
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 0e31910..266be05 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -625,39 +625,60 @@
} while (pte++, addr += PAGE_SIZE, addr != end);
}
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+ unsigned long end, phys_addr_t phys,
+ const struct mem_type *type)
+{
+#ifndef CONFIG_ARM_LPAE
+ /*
+ * In classic MMU format, puds and pmds are folded in to
+ * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+ * group of L1 entries making up one logical pointer to
+ * an L2 table (2MB), where as PMDs refer to the individual
+ * L1 entries (1MB). Hence increment to get the correct
+ * offset for odd 1MB sections.
+ * (See arch/arm/include/asm/pgtable-2level.h)
+ */
+ if (addr & SECTION_SIZE)
+ pmd++;
+#endif
+ do {
+ *pmd = __pmd(phys | type->prot_sect);
+ phys += SECTION_SIZE;
+ } while (pmd++, addr += SECTION_SIZE, addr != end);
+
+ flush_pmd_entry(pmd);
+}
+
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
unsigned long end, phys_addr_t phys,
const struct mem_type *type)
{
pmd_t *pmd = pmd_offset(pud, addr);
+ unsigned long next;
- /*
- * Try a section mapping - end, addr and phys must all be aligned
- * to a section boundary. Note that PMDs refer to the individual
- * L1 entries, whereas PGDs refer to a group of L1 entries making
- * up one logical pointer to an L2 table.
- */
- if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
- pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
- if (addr & SECTION_SIZE)
- pmd++;
-#endif
-
- do {
- *pmd = __pmd(phys | type->prot_sect);
- phys += SECTION_SIZE;
- } while (pmd++, addr += SECTION_SIZE, addr != end);
-
- flush_pmd_entry(p);
- } else {
+ do {
/*
- * No need to loop; pte's aren't interested in the
- * individual L1 entries.
+ * With LPAE, we must loop over to map
+ * all the pmds for the given range.
*/
- alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
- }
+ next = pmd_addr_end(addr, end);
+
+ /*
+ * Try a section mapping - addr, next and phys must all be
+ * aligned to a section boundary.
+ */
+ if (type->prot_sect &&
+ ((addr | next | phys) & ~SECTION_MASK) == 0) {
+ map_init_section(pmd, addr, next, phys, type);
+ } else {
+ alloc_init_pte(pmd, addr, next,
+ __phys_to_pfn(phys), type);
+ }
+
+ phys += next - addr;
+
+ } while (pmd++, addr = next, addr != end);
}
static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -668,7 +689,7 @@
do {
next = pud_addr_end(addr, end);
- alloc_init_section(pud, addr, next, phys, type);
+ alloc_init_pmd(pud, addr, next, phys, type);
phys += next - addr;
} while (pud++, addr = next, addr != end);
}
diff --git a/block/blk-core.c b/block/blk-core.c
index 04604cf..bd50c8e 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -29,6 +29,7 @@
#include <linux/fault-inject.h>
#include <linux/list_sort.h>
#include <linux/delay.h>
+#include <linux/ratelimit.h>
#define CREATE_TRACE_POINTS
#include <trace/events/block.h>
@@ -2203,9 +2204,11 @@
error_type = "I/O";
break;
}
- printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
- error_type, req->rq_disk ? req->rq_disk->disk_name : "?",
- (unsigned long long)blk_rq_pos(req));
+ printk_ratelimited(
+ KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
+ error_type,
+ req->rq_disk ? req->rq_disk->disk_name : "?",
+ (unsigned long long)blk_rq_pos(req));
}
blk_account_io_completion(req, nr_bytes);
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index ed91480..45c9023 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -227,7 +227,7 @@
pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
(unsigned long)base, (unsigned long)size / SZ_1M);
- dma_contiguous_reserve_area(size, &base, 0, name);
+ dma_contiguous_reserve_area(size, &base, MEMBLOCK_ALLOC_ANYWHERE, name);
return 0;
}
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index ac993ea..50b2831 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -22,6 +22,8 @@
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/opp.h>
+#include <linux/of.h>
+#include <linux/export.h>
/*
* Internal data structure organization with the OPP layer library is as
@@ -64,6 +66,7 @@
unsigned long u_volt;
struct device_opp *dev_opp;
+ struct rcu_head head;
};
/**
@@ -159,6 +162,7 @@
return v;
}
+EXPORT_SYMBOL(opp_get_voltage);
/**
* opp_get_freq() - Gets the frequency corresponding to an available opp
@@ -188,6 +192,7 @@
return f;
}
+EXPORT_SYMBOL(opp_get_freq);
/**
* opp_get_opp_count() - Get number of opps available in the opp list
@@ -220,6 +225,7 @@
return count;
}
+EXPORT_SYMBOL(opp_get_opp_count);
/**
* opp_find_freq_exact() - search for an exact frequency
@@ -229,7 +235,10 @@
*
* Searches for exact match in the opp list and returns pointer to the matching
* opp if found, else returns ERR_PTR in case of error and should be handled
- * using IS_ERR.
+ * using IS_ERR. Error return values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Note: available is a modifier for the search. if available=true, then the
* match is for exact matching frequency and is available in the stored OPP
@@ -248,7 +257,7 @@
bool available)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp)) {
@@ -267,6 +276,7 @@
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_exact);
/**
* opp_find_freq_ceil() - Search for an rounded ceil freq
@@ -277,7 +287,11 @@
* for a device.
*
* Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. The reason for the same is that the opp pointer which is
@@ -288,7 +302,7 @@
struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
if (!dev || !freq) {
dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -297,7 +311,7 @@
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp))
- return opp;
+ return ERR_CAST(dev_opp);
list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
if (temp_opp->available && temp_opp->rate >= *freq) {
@@ -309,6 +323,7 @@
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_ceil);
/**
* opp_find_freq_floor() - Search for a rounded floor freq
@@ -319,7 +334,11 @@
* for a device.
*
* Returns matching *opp and refreshes *freq accordingly, else returns
- * ERR_PTR in case of error and should be handled using IS_ERR.
+ * ERR_PTR in case of error and should be handled using IS_ERR. Error return
+ * values can be:
+ * EINVAL: for bad pointer
+ * ERANGE: no match found for search
+ * ENODEV: if device not found in list of registered devices
*
* Locking: This function must be called under rcu_read_lock(). opp is a rcu
* protected pointer. The reason for the same is that the opp pointer which is
@@ -330,7 +349,7 @@
struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
{
struct device_opp *dev_opp;
- struct opp *temp_opp, *opp = ERR_PTR(-ENODEV);
+ struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
if (!dev || !freq) {
dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -339,7 +358,7 @@
dev_opp = find_device_opp(dev);
if (IS_ERR(dev_opp))
- return opp;
+ return ERR_CAST(dev_opp);
list_for_each_entry_rcu(temp_opp, &dev_opp->opp_list, node) {
if (temp_opp->available) {
@@ -355,6 +374,7 @@
return opp;
}
+EXPORT_SYMBOL(opp_find_freq_floor);
/**
* opp_add() - Add an OPP table from a table definitions
@@ -511,7 +531,7 @@
list_replace_rcu(&opp->node, &new_opp->node);
mutex_unlock(&dev_opp_list_lock);
- synchronize_rcu();
+ kfree_rcu(opp, head);
/* Notify the change of the OPP availability */
if (availability_req)
@@ -521,13 +541,10 @@
srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_DISABLE,
new_opp);
- /* clean up old opp */
- new_opp = opp;
- goto out;
+ return 0;
unlock:
mutex_unlock(&dev_opp_list_lock);
-out:
kfree(new_opp);
return r;
}
@@ -551,6 +568,7 @@
{
return opp_set_availability(dev, freq, true);
}
+EXPORT_SYMBOL(opp_enable);
/**
* opp_disable() - Disable a specific OPP
@@ -572,6 +590,7 @@
{
return opp_set_availability(dev, freq, false);
}
+EXPORT_SYMBOL(opp_disable);
#ifdef CONFIG_CPU_FREQ
/**
@@ -674,3 +693,49 @@
return &dev_opp->head;
}
+
+#ifdef CONFIG_OF
+/**
+ * of_init_opp_table() - Initialize opp table from device tree
+ * @dev: device pointer used to lookup device OPPs.
+ *
+ * Register the initial OPP table with the OPP library for given device.
+ */
+int of_init_opp_table(struct device *dev)
+{
+ const struct property *prop;
+ const __be32 *val;
+ int nr;
+
+ prop = of_find_property(dev->of_node, "operating-points", NULL);
+ if (!prop)
+ return -ENODEV;
+ if (!prop->value)
+ return -ENODATA;
+
+ /*
+ * Each OPP is a set of tuples consisting of frequency and
+ * voltage like <freq-kHz vol-uV>.
+ */
+ nr = prop->length / sizeof(u32);
+ if (nr % 2) {
+ dev_err(dev, "%s: Invalid OPP list\n", __func__);
+ return -EINVAL;
+ }
+
+ val = prop->value;
+ while (nr) {
+ unsigned long freq = be32_to_cpup(val++) * 1000;
+ unsigned long volt = be32_to_cpup(val++);
+
+ if (opp_add(dev, freq, volt)) {
+ dev_warn(dev, "%s: Failed to add OPP %ld\n",
+ __func__, freq);
+ continue;
+ }
+ nr -= 2;
+ }
+
+ return 0;
+}
+#endif
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index b6d90d4..2557983 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -5,7 +5,7 @@
* power management protocol extension to H4 to support AR300x Bluetooth Chip.
*
* Copyright (c) 2009-2010 Atheros Communications Inc.
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
*
* Acknowledgements:
* This file is based on hci_h4.c, which was written
@@ -38,7 +38,7 @@
#include <linux/skbuff.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
-
+#include <linux/of_gpio.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -52,6 +52,13 @@
/*
* Global variables
*/
+
+/** Device table */
+static struct of_device_id bluesleep_match_table[] = {
+ { .compatible = "qca,ar3002_bluesleep" },
+ {}
+};
+
/** Global state flags */
static unsigned long flags;
@@ -436,10 +443,59 @@
.flush = ath_flush,
};
-static int __init bluesleep_probe(struct platform_device *pdev)
+
+static int bluesleep_populate_dt_pinfo(struct platform_device *pdev)
+{
+ BT_DBG("");
+
+ if (!bsi)
+ return -ENOMEM;
+
+ bsi->host_wake = of_get_named_gpio(pdev->dev.of_node,
+ "host-wake-gpio", 0);
+ if (bsi->host_wake < 0) {
+ BT_ERR("couldn't find host_wake gpio\n");
+ return -ENODEV;
+ }
+
+ bsi->ext_wake = of_get_named_gpio(pdev->dev.of_node,
+ "ext-wake-gpio", 0);
+ if (bsi->ext_wake < 0) {
+ BT_ERR("couldn't find ext_wake gpio\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int bluesleep_populate_pinfo(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ BT_DBG("");
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "gpio_host_wake");
+ if (!res) {
+ BT_ERR("couldn't find host_wake gpio\n");
+ return -ENODEV;
+ }
+ bsi->host_wake = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "gpio_ext_wake");
+ if (!res) {
+ BT_ERR("couldn't find ext_wake gpio\n");
+ return -ENODEV;
+ }
+ bsi->ext_wake = res->start;
+
+ return 0;
+}
+
+static int __devinit bluesleep_probe(struct platform_device *pdev)
{
int ret;
- struct resource *res;
BT_DBG("");
@@ -449,23 +505,22 @@
goto failed;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_IO,
- "gpio_host_wake");
- if (!res) {
- BT_ERR("couldn't find host_wake gpio\n");
- ret = -ENODEV;
- goto free_bsi;
+ if (pdev->dev.of_node) {
+ ret = bluesleep_populate_dt_pinfo(pdev);
+ if (ret < 0) {
+ BT_ERR("Failed to populate device tree info");
+ goto free_bsi;
+ }
+ } else {
+ ret = bluesleep_populate_pinfo(pdev);
+ if (ret < 0) {
+ BT_ERR("Failed to populate device info");
+ goto free_bsi;
+ }
}
- bsi->host_wake = res->start;
- res = platform_get_resource_byname(pdev, IORESOURCE_IO,
- "gpio_ext_wake");
- if (!res) {
- BT_ERR("couldn't find ext_wake gpio\n");
- ret = -ENODEV;
- goto free_bsi;
- }
- bsi->ext_wake = res->start;
+ BT_DBG("host_wake_gpio: %d ext_wake_gpio: %d",
+ bsi->host_wake, bsi->ext_wake);
bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
if (bsi->host_wake_irq < 0) {
@@ -492,10 +547,12 @@
}
static struct platform_driver bluesleep_driver = {
+ .probe = bluesleep_probe,
.remove = bluesleep_remove,
.driver = {
.name = "bluesleep",
.owner = THIS_MODULE,
+ .of_match_table = bluesleep_match_table,
},
};
@@ -511,9 +568,13 @@
BT_ERR("HCIATH3K protocol registration failed");
return ret;
}
- ret = platform_driver_probe(&bluesleep_driver, bluesleep_probe);
- if (ret)
+
+ ret = platform_driver_register(&bluesleep_driver);
+ if (ret) {
+ BT_ERR("Failed to register bluesleep driver");
return ret;
+ }
+
return 0;
}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 0b3ffef..e2864ec 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -633,7 +633,7 @@
config MSM_ROTATOR
tristate "MSM Offline Image Rotator Driver"
- depends on (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM8960) && ANDROID_PMEM
+ depends on (ARCH_MSM7X30 || ARCH_MSM8X60 || ARCH_MSM8960)
default y
help
This driver provides support for the image rotator HW block in the
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 0f4d613..d78327f 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -138,6 +138,15 @@
struct hlist_head htbl[RPC_HASH_SZ];
};
+struct fastrpc_mmap {
+ struct hlist_node hn;
+ struct ion_handle *handle;
+ void *virt;
+ uint32_t vaddrin;
+ uint32_t vaddrout;
+ int size;
+};
+
struct fastrpc_buf {
struct ion_handle *handle;
void *virt;
@@ -146,6 +155,11 @@
int used;
};
+struct file_data {
+ spinlock_t hlock;
+ struct hlist_head hlst;
+};
+
struct fastrpc_device {
uint32_t tgid;
struct hlist_node hn;
@@ -168,18 +182,31 @@
}
}
+static void free_map(struct fastrpc_mmap *map)
+{
+ struct fastrpc_apps *me = &gfa;
+ if (map->handle) {
+ if (map->virt) {
+ ion_unmap_kernel(me->iclient, map->handle);
+ map->virt = 0;
+ }
+ ion_free(me->iclient, map->handle);
+ }
+ map->handle = 0;
+}
+
static int alloc_mem(struct fastrpc_buf *buf)
{
struct ion_client *clnt = gfa.iclient;
struct sg_table *sg;
int err = 0;
-
+ buf->handle = 0;
+ buf->virt = 0;
buf->handle = ion_alloc(clnt, buf->size, SZ_4K,
ION_HEAP(ION_AUDIO_HEAP_ID), 0);
VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
if (err)
goto bail;
- buf->virt = 0;
VERIFY(err, 0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
if (err)
goto bail;
@@ -211,7 +238,6 @@
static void context_list_dtor(struct smq_context_list *me)
{
kfree(me->ls);
- me->ls = 0;
}
static void context_list_alloc_ctx(struct smq_context_list *me,
@@ -277,7 +303,6 @@
if (rlen < 0) {
rlen = ((uint32_t)pages - (uint32_t)obuf->virt) - obuf->size;
obuf->size += buf_page_size(rlen);
- obuf->handle = 0;
VERIFY(err, 0 == alloc_mem(obuf));
if (err)
goto bail;
@@ -314,7 +339,6 @@
if (obuf->handle != ibuf->handle)
free_mem(obuf);
obuf->size += buf_page_size(sizeof(*pages));
- obuf->handle = 0;
VERIFY(err, 0 == alloc_mem(obuf));
if (err)
goto bail;
@@ -430,10 +454,15 @@
outbufs = REMOTE_SCALARS_OUTBUFS(sc);
for (i = inbufs; i < inbufs + outbufs; ++i) {
if (rpra[i].buf.pv != pra[i].buf.pv) {
- VERIFY(err, 0 == copy_to_user(pra[i].buf.pv,
+ if (!kernel) {
+ VERIFY(err, 0 == copy_to_user(pra[i].buf.pv,
rpra[i].buf.pv, rpra[i].buf.len));
- if (err)
- goto bail;
+ if (err)
+ goto bail;
+ } else {
+ memmove(pra[i].buf.pv, rpra[i].buf.pv,
+ rpra[i].buf.len);
+ }
}
}
size = sizeof(*rpra) * REMOTE_SCALARS_OUTHANDLES(sc);
@@ -471,15 +500,17 @@
dmac_inv_range(rpra, (char *)rpra + used);
}
-static int fastrpc_invoke_send(struct fastrpc_apps *me, uint32_t handle,
+static int fastrpc_invoke_send(struct fastrpc_apps *me,
+ uint32_t kernel, uint32_t handle,
uint32_t sc, struct smq_invoke_ctx *ctx,
struct fastrpc_buf *buf)
{
struct smq_msg msg;
int err = 0, len;
-
msg.pid = current->tgid;
msg.tid = current->pid;
+ if (kernel)
+ msg.pid = 0;
msg.invoke.header.ctx = ctx;
msg.invoke.header.handle = handle;
msg.invoke.header.sc = sc;
@@ -595,12 +626,15 @@
VERIFY(err, 0 != (fd = kzalloc(sizeof(*fd), GFP_KERNEL)));
if (err)
goto bail;
+
+ INIT_HLIST_NODE(&fd->hn);
+
fd->buf.size = PAGE_SIZE;
VERIFY(err, 0 == alloc_mem(&fd->buf));
if (err)
goto bail;
fd->tgid = current->tgid;
- INIT_HLIST_NODE(&fd->hn);
+
*dev = fd;
bail:
if (err)
@@ -681,8 +715,8 @@
}
context_list_alloc_ctx(&me->clst, &ctx);
- VERIFY(err, 0 == fastrpc_invoke_send(me, invoke->handle, sc, ctx,
- &obuf));
+ VERIFY(err, 0 == fastrpc_invoke_send(me, kernel, invoke->handle, sc,
+ ctx, &obuf));
if (err)
goto bail;
inv_args(sc, rpra, obuf.used);
@@ -730,7 +764,7 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(0, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
return err;
}
@@ -748,7 +782,155 @@
ioctl.handle = 1;
ioctl.sc = REMOTE_SCALARS_MAKE(1, 1, 0);
ioctl.pra = ra;
- VERIFY(err, 0 == fastrpc_internal_invoke(me, 1, &ioctl, ra));
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ return err;
+}
+
+static int fastrpc_mmap_on_dsp(struct fastrpc_apps *me,
+ struct fastrpc_ioctl_mmap *mmap,
+ struct smq_phy_page *pages,
+ int num)
+{
+ struct fastrpc_ioctl_invoke ioctl;
+ remote_arg_t ra[3];
+ int err = 0;
+ struct {
+ int pid;
+ uint32_t flags;
+ uint32_t vaddrin;
+ int num;
+ } inargs;
+
+ struct {
+ uint32_t vaddrout;
+ } routargs;
+ inargs.pid = current->tgid;
+ inargs.vaddrin = mmap->vaddrin;
+ inargs.flags = mmap->flags;
+ inargs.num = num;
+ ra[0].buf.pv = &inargs;
+ ra[0].buf.len = sizeof(inargs);
+
+ ra[1].buf.pv = pages;
+ ra[1].buf.len = num * sizeof(*pages);
+
+ ra[2].buf.pv = &routargs;
+ ra[2].buf.len = sizeof(routargs);
+
+ ioctl.handle = 1;
+ ioctl.sc = REMOTE_SCALARS_MAKE(2, 2, 1);
+ ioctl.pra = ra;
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ mmap->vaddrout = routargs.vaddrout;
+ if (err)
+ goto bail;
+bail:
+ return err;
+}
+
+static int fastrpc_munmap_on_dsp(struct fastrpc_apps *me,
+ struct fastrpc_ioctl_munmap *munmap)
+{
+ struct fastrpc_ioctl_invoke ioctl;
+ remote_arg_t ra[1];
+ int err = 0;
+ struct {
+ int pid;
+ uint32_t vaddrout;
+ int size;
+ } inargs;
+
+ inargs.pid = current->tgid;
+ inargs.size = munmap->size;
+ inargs.vaddrout = munmap->vaddrout;
+ ra[0].buf.pv = &inargs;
+ ra[0].buf.len = sizeof(inargs);
+
+ ioctl.handle = 1;
+ ioctl.sc = REMOTE_SCALARS_MAKE(3, 1, 0);
+ ioctl.pra = ra;
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(me, 1, &ioctl, ra)));
+ return err;
+}
+
+static int fastrpc_internal_munmap(struct fastrpc_apps *me,
+ struct file_data *fdata,
+ struct fastrpc_ioctl_munmap *munmap)
+{
+ int err = 0;
+ struct fastrpc_mmap *map = 0, *mapfree = 0;
+ struct hlist_node *pos, *n;
+ VERIFY(err, 0 == (err = fastrpc_munmap_on_dsp(me, munmap)));
+ if (err)
+ goto bail;
+ spin_lock(&fdata->hlock);
+ hlist_for_each_entry_safe(map, pos, n, &fdata->hlst, hn) {
+ if (map->vaddrout == munmap->vaddrout &&
+ map->size == munmap->size) {
+ hlist_del(&map->hn);
+ mapfree = map;
+ map = 0;
+ break;
+ }
+ }
+ spin_unlock(&fdata->hlock);
+bail:
+ if (mapfree) {
+ free_map(mapfree);
+ kfree(mapfree);
+ }
+ return err;
+}
+
+
+static int fastrpc_internal_mmap(struct fastrpc_apps *me,
+ struct file_data *fdata,
+ struct fastrpc_ioctl_mmap *mmap)
+{
+ struct ion_client *clnt = gfa.iclient;
+ struct fastrpc_mmap *map = 0;
+ struct smq_phy_page *pages = 0;
+ void *buf;
+ int len;
+ int num;
+ int err = 0;
+
+ VERIFY(err, 0 != (map = kzalloc(sizeof(*map), GFP_KERNEL)));
+ if (err)
+ goto bail;
+ map->handle = ion_import_dma_buf(clnt, mmap->fd);
+ VERIFY(err, 0 == IS_ERR_OR_NULL(map->handle));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 != (map->virt = ion_map_kernel(clnt, map->handle)));
+ if (err)
+ goto bail;
+ buf = (void *)mmap->vaddrin;
+ len = mmap->size;
+ num = buf_num_pages(buf, len);
+ VERIFY(err, 0 != (pages = kzalloc(num * sizeof(*pages), GFP_KERNEL)));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 < (num = buf_get_pages(buf, len, num, 1, pages, num)));
+ if (err)
+ goto bail;
+
+ VERIFY(err, 0 == fastrpc_mmap_on_dsp(me, mmap, pages, num));
+ if (err)
+ goto bail;
+ map->vaddrin = mmap->vaddrin;
+ map->vaddrout = mmap->vaddrout;
+ map->size = mmap->size;
+ INIT_HLIST_NODE(&map->hn);
+ spin_lock(&fdata->hlock);
+ hlist_add_head(&map->hn, &fdata->hlst);
+ spin_unlock(&fdata->hlock);
+ bail:
+ if (err && map) {
+ free_map(map);
+ kfree(map);
+ }
+ kfree(pages);
return err;
}
@@ -781,22 +963,48 @@
static int fastrpc_device_release(struct inode *inode, struct file *file)
{
+ struct file_data *fdata = (struct file_data *)file->private_data;
(void)fastrpc_release_current_dsp_process();
cleanup_current_dev();
+ if (fdata) {
+ struct fastrpc_mmap *map;
+ struct hlist_node *n, *pos;
+ file->private_data = 0;
+ hlist_for_each_entry_safe(map, pos, n, &fdata->hlst, hn) {
+ hlist_del(&map->hn);
+ free_map(map);
+ kfree(map);
+ }
+ kfree(fdata);
+ }
return 0;
}
static int fastrpc_device_open(struct inode *inode, struct file *filp)
{
int err = 0;
-
+ filp->private_data = 0;
if (0 != try_module_get(THIS_MODULE)) {
+ struct file_data *fdata = 0;
/* This call will cause a dev to be created
* which will addref this module
*/
+ VERIFY(err, 0 != (fdata = kzalloc(sizeof(*fdata), GFP_KERNEL)));
+ if (err)
+ goto bail;
+
+ spin_lock_init(&fdata->hlock);
+ INIT_HLIST_HEAD(&fdata->hlst);
+
VERIFY(err, 0 == fastrpc_create_current_dsp_process());
if (err)
+ goto bail;
+ filp->private_data = fdata;
+bail:
+ if (err) {
cleanup_current_dev();
+ kfree(fdata);
+ }
module_put(THIS_MODULE);
}
return err;
@@ -808,8 +1016,11 @@
{
struct fastrpc_apps *me = &gfa;
struct fastrpc_ioctl_invoke invoke;
+ struct fastrpc_ioctl_mmap mmap;
+ struct fastrpc_ioctl_munmap munmap;
remote_arg_t *pra = 0;
void *param = (char *)ioctl_param;
+ struct file_data *fdata = (struct file_data *)file->private_data;
int bufs, err = 0;
switch (ioctl_num) {
@@ -834,6 +1045,29 @@
if (err)
goto bail;
break;
+ case FASTRPC_IOCTL_MMAP:
+ VERIFY(err, 0 == copy_from_user(&mmap, param,
+ sizeof(mmap)));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == (err = fastrpc_internal_mmap(me, fdata,
+ &mmap)));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == copy_to_user(param, &mmap, sizeof(mmap)));
+ if (err)
+ goto bail;
+ break;
+ case FASTRPC_IOCTL_MUNMAP:
+ VERIFY(err, 0 == copy_from_user(&munmap, param,
+ sizeof(munmap)));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == (err = fastrpc_internal_munmap(me, fdata,
+ &munmap)));
+ if (err)
+ goto bail;
+ break;
default:
err = -ENOTTY;
break;
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 8932d3c..f2804ad 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -16,7 +16,9 @@
#include <linux/types.h>
-#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
+#define FASTRPC_IOCTL_INVOKE _IOWR('R', 1, struct fastrpc_ioctl_invoke)
+#define FASTRPC_IOCTL_MMAP _IOWR('R', 2, struct fastrpc_ioctl_mmap)
+#define FASTRPC_IOCTL_MUNMAP _IOWR('R', 3, struct fastrpc_ioctl_munmap)
#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
#define DEVICE_NAME "adsprpc-smd"
@@ -92,6 +94,20 @@
remote_arg_t *pra; /* remote arguments list */
};
+struct fastrpc_ioctl_munmap {
+ uint32_t vaddrout; /* address to unmap */
+ int size; /* size */
+};
+
+
+struct fastrpc_ioctl_mmap {
+ int fd; /* ion fd */
+ uint32_t flags; /* flags for dsp to map with */
+ uint32_t vaddrin; /* optional virtual address */
+ int size; /* size */
+ uint32_t vaddrout; /* dsps virtual address */
+};
+
struct smq_null_invoke {
struct smq_invoke_ctx *ctx; /* invoke caller context */
uint32_t handle; /* handle to invoke */
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 0c93101..9e36e1e 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -314,6 +314,9 @@
diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
diag_send_feature_mask_update(smd_info->ch, smd_info->peripheral);
+ if (smd_info->notify_context == SMD_EVENT_OPEN)
+ diag_send_diag_mode_update_by_smd(smd_info, MODE_REALTIME);
+
smd_info->notify_context = 0;
}
@@ -734,8 +737,8 @@
(driver->log_on_demand_support)) {
driver->apps_rsp_buf[0] = 0x78;
/* Copy log code received */
- *(uint16_t *)(driver->apps_rsp_buf+1) =
- *(uint16_t *)buf;
+ *(uint16_t *)(driver->apps_rsp_buf + 1) =
+ *(uint16_t *)(buf + 1);
driver->apps_rsp_buf[3] = 0x1;/* Unknown */
encode_rsp_and_send(3);
}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index a4eea54..555ffa0 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -20,6 +20,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
+#include <linux/wakelock.h>
#include <mach/msm_smd.h>
#include <asm/atomic.h>
#include <asm/mach-types.h>
@@ -76,6 +77,9 @@
#define DIAG_STATUS_OPEN (0x00010000) /* DCI channel open status mask */
#define DIAG_STATUS_CLOSED (0x00020000) /* DCI channel closed status mask */
+#define MODE_REALTIME 1
+#define MODE_NONREALTIME 0
+
#define NUM_SMD_DATA_CHANNELS 3
#define NUM_SMD_CONTROL_CHANNELS 3
#define NUM_SMD_DCI_CHANNELS 1
@@ -143,6 +147,14 @@
int pid;
};
+struct diag_nrt_wake_lock {
+ int enabled;
+ int ref_count;
+ int copy_count;
+ struct wake_lock read_lock;
+ spinlock_t read_spinlock;
+};
+
/* This structure is defined in USB header file */
#ifndef CONFIG_DIAG_OVER_USB
struct diag_request {
@@ -162,6 +174,8 @@
smd_channel_t *ch;
smd_channel_t *ch_save;
+ struct mutex smd_ch_mutex;
+
int in_busy_1;
int in_busy_2;
@@ -171,6 +185,8 @@
struct diag_request *write_ptr_1;
struct diag_request *write_ptr_2;
+ struct diag_nrt_wake_lock nrt_lock;
+
struct work_struct diag_read_smd_work;
struct work_struct diag_notify_update_smd_work;
int notify_context;
@@ -237,6 +253,7 @@
struct diag_ctrl_msg_mask *msg_mask;
struct diag_ctrl_feature_mask *feature_mask;
/* State for diag forwarding */
+ int real_time_mode;
struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
@@ -249,6 +266,7 @@
unsigned char *buf_event_mask_update;
unsigned char *buf_feature_mask_update;
int read_len_legacy;
+ struct mutex diag_hdlc_mutex;
unsigned char *hdlc_buf;
unsigned hdlc_count;
unsigned hdlc_escape;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 65fc89f..fb8efe4 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -20,6 +20,7 @@
#include <linux/diagchar.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
+#include <linux/ratelimit.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <mach/usbdiag.h>
#endif
@@ -278,10 +279,11 @@
/* If the SD logging process exits, change logging to USB mode */
if (driver->logging_process_id == current->tgid) {
driver->logging_mode = USB_MODE;
+ diag_send_diag_mode_update(MODE_REALTIME);
diagfwd_connect();
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diag_clear_hsic_tbl();
- diagfwd_cancel_hsic();
+ diagfwd_cancel_hsic(REOPEN_HSIC);
diagfwd_connect_bridge(0);
#endif
}
@@ -707,6 +709,11 @@
diag_clear_hsic_tbl();
} else if (old_mode == NO_LOGGING_MODE && new_mode
== MEMORY_DEVICE_MODE) {
+ int i;
+ for (i = 0; i < MAX_HSIC_CH; i++)
+ if (diag_hsic[i].hsic_inited)
+ diag_hsic[i].hsic_data_requested =
+ driver->real_time_mode ? 1 : 0;
diagfwd_connect_bridge(0);
} else if (old_mode == USB_MODE && new_mode
== NO_LOGGING_MODE) {
@@ -716,12 +723,15 @@
diagfwd_connect_bridge(0);
} else if (old_mode == USB_MODE && new_mode
== MEMORY_DEVICE_MODE) {
- diagfwd_cancel_hsic();
+ if (driver->real_time_mode)
+ diagfwd_cancel_hsic(REOPEN_HSIC);
+ else
+ diagfwd_cancel_hsic(DONT_REOPEN_HSIC);
diagfwd_connect_bridge(0);
} else if (old_mode == MEMORY_DEVICE_MODE && new_mode
== USB_MODE) {
diag_clear_hsic_tbl();
- diagfwd_cancel_hsic();
+ diagfwd_cancel_hsic(REOPEN_HSIC);
diagfwd_connect_bridge(0);
}
}
@@ -770,12 +780,25 @@
int diag_switch_logging(unsigned long ioarg)
{
int i, temp, success = -EINVAL, status;
+ int temp_realtime_mode = driver->real_time_mode;
+
mutex_lock(&driver->diagchar_mutex);
temp = driver->logging_mode;
driver->logging_mode = (int)ioarg;
+
+ if (driver->logging_mode == MEMORY_DEVICE_MODE_NRT) {
+ diag_send_diag_mode_update(MODE_NONREALTIME);
+ driver->logging_mode = MEMORY_DEVICE_MODE;
+ } else {
+ diag_send_diag_mode_update(MODE_REALTIME);
+ }
+
if (temp == driver->logging_mode) {
mutex_unlock(&driver->diagchar_mutex);
- pr_err("diag: forbidden logging change requested\n");
+ if (driver->logging_mode != MEMORY_DEVICE_MODE ||
+ temp_realtime_mode)
+ pr_info_ratelimited("diag: Already in logging mode change requested, mode: %d\n",
+ driver->logging_mode);
return 0;
}
@@ -1097,6 +1120,7 @@
int num_data = 0, data_type;
int remote_token;
int exit_stat;
+ int clear_read_wakelock;
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == current->tgid)
@@ -1111,6 +1135,7 @@
driver->data_ready[index]);
mutex_lock(&driver->diagchar_mutex);
+ clear_read_wakelock = 0;
if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) && (driver->
logging_mode == MEMORY_DEVICE_MODE)) {
remote_token = 0;
@@ -1172,6 +1197,10 @@
COPY_USER_SPACE_OR_EXIT(buf+ret,
*(data->buf_in_1),
data->write_ptr_1->length);
+ if (!driver->real_time_mode) {
+ process_lock_on_copy(&data->nrt_lock);
+ clear_read_wakelock++;
+ }
data->in_busy_1 = 0;
}
if (data->in_busy_2 == 1) {
@@ -1183,6 +1212,10 @@
COPY_USER_SPACE_OR_EXIT(buf+ret,
*(data->buf_in_2),
data->write_ptr_2->length);
+ if (!driver->real_time_mode) {
+ process_lock_on_copy(&data->nrt_lock);
+ clear_read_wakelock++;
+ }
data->in_busy_2 = 0;
}
}
@@ -1308,6 +1341,11 @@
goto exit;
}
exit:
+ if (clear_read_wakelock) {
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
+ process_lock_on_copy_complete(
+ &driver->smd_data[i].nrt_lock);
+ }
mutex_unlock(&driver->diagchar_mutex);
return ret;
}
@@ -1405,9 +1443,19 @@
#endif
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
/* send masks to All 9k */
- if ((remote_proc >= MDM) && (remote_proc <= MDM4)) {
+ if ((remote_proc >= MDM) && (remote_proc <= MDM4) &&
+ (payload_size > 0)) {
index = remote_proc - MDM;
- if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
+ /*
+ * If hsic data is being requested for this remote
+ * processor and its hsic in not open
+ */
+ if (!diag_hsic[index].hsic_device_opened) {
+ diag_hsic[index].hsic_data_requested = 1;
+ connect_bridge(0, index);
+ }
+
+ if (diag_hsic[index].hsic_ch) {
/* wait sending mask updates
* if HSIC ch not ready */
if (diag_hsic[index].in_busy_hsic_write)
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6a14143..bb74370 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -227,6 +227,93 @@
}
}
+void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time)
+{
+ unsigned long read_lock_flags;
+
+ spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+ if (real_time)
+ lock->enabled = 0;
+ else
+ lock->enabled = 1;
+ lock->ref_count = 0;
+ lock->copy_count = 0;
+ wake_unlock(&lock->read_lock);
+ spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_notify(struct diag_nrt_wake_lock *lock)
+{
+ unsigned long read_lock_flags;
+
+ spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+ /*
+ * Do not work with ref_count here in case
+ * of spurious interrupt
+ */
+ if (lock->enabled)
+ wake_lock(&lock->read_lock);
+ spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len)
+{
+ unsigned long read_lock_flags;
+
+ spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+ if (lock->enabled) {
+ if (pkt_len > 0) {
+ /*
+ * We have an data that is read that
+ * needs to be processed, make sure the
+ * processor does not go to sleep
+ */
+ lock->ref_count++;
+ if (!wake_lock_active(&lock->read_lock))
+ wake_lock(&lock->read_lock);
+ } else {
+ /*
+ * There was no data associated with the
+ * read from the smd, unlock the wake lock
+ * if it is not needed.
+ */
+ if (lock->ref_count < 1) {
+ if (wake_lock_active(&lock->read_lock))
+ wake_unlock(&lock->read_lock);
+ lock->ref_count = 0;
+ lock->copy_count = 0;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_copy(struct diag_nrt_wake_lock *lock)
+{
+ unsigned long read_lock_flags;
+
+ spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+ if (lock->enabled)
+ lock->copy_count++;
+ spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
+void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock)
+{
+ unsigned long read_lock_flags;
+
+ spin_lock_irqsave(&lock->read_spinlock, read_lock_flags);
+ if (lock->enabled) {
+ lock->ref_count -= lock->copy_count;
+ if (lock->ref_count < 1) {
+ wake_unlock(&lock->read_lock);
+ lock->ref_count = 0;
+ }
+ lock->copy_count = 0;
+ }
+ spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags);
+}
+
/* Process the data read from the smd data channel */
int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf,
int total_recd)
@@ -324,6 +411,8 @@
smd_read(smd_info->ch, temp_buf, r);
temp_buf += r;
}
+ if (!driver->real_time_mode && smd_info->type == SMD_DATA_TYPE)
+ process_lock_on_read(&smd_info->nrt_lock, pkt_len);
if (total_recd > 0) {
if (!buf) {
@@ -611,8 +700,12 @@
diag_check_mode_reset(buf)) {
return;
}
+ mutex_lock(&driver->smd_data[index].
+ smd_ch_mutex);
smd_write(driver->smd_data[index].ch,
buf, len);
+ mutex_unlock(&driver->smd_data[index].
+ smd_ch_mutex);
} else {
pr_err("diag: In %s, smd channel %d not open\n",
__func__, index);
@@ -1003,6 +1096,9 @@
{
struct diag_hdlc_decode_type hdlc;
int ret, type = 0;
+
+ mutex_lock(&driver->diag_hdlc_mutex);
+
pr_debug("diag: HDLC decode fn, len of data %d\n", len);
hdlc.dest_ptr = driver->hdlc_buf;
hdlc.dest_size = USB_MAX_OUT_BUF;
@@ -1023,14 +1119,17 @@
if (hdlc.dest_idx < 4) {
pr_err_ratelimited("diag: In %s, message is too short, len: %d, dest len: %d\n",
__func__, len, hdlc.dest_idx);
+ mutex_unlock(&driver->diag_hdlc_mutex);
return;
}
if (ret) {
type = diag_process_apps_pkt(driver->hdlc_buf,
hdlc.dest_idx - 3);
- if (type < 0)
+ if (type < 0) {
+ mutex_unlock(&driver->diag_hdlc_mutex);
return;
+ }
} else if (driver->debug_flag) {
printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
" errors or partial packet received, packet"
@@ -1049,10 +1148,15 @@
if (chk_apps_only()) {
diag_send_error_rsp(hdlc.dest_idx);
} else { /* APQ 8060, Let Q6 respond */
- if (driver->smd_data[LPASS_DATA].ch)
+ if (driver->smd_data[LPASS_DATA].ch) {
+ mutex_lock(&driver->smd_data[LPASS_DATA].
+ smd_ch_mutex);
smd_write(driver->smd_data[LPASS_DATA].ch,
driver->hdlc_buf,
hdlc.dest_idx - 3);
+ mutex_unlock(&driver->smd_data[LPASS_DATA].
+ smd_ch_mutex);
+ }
}
type = 0;
}
@@ -1067,8 +1171,10 @@
if ((driver->smd_data[MODEM_DATA].ch) && (ret) && (type) &&
(hdlc.dest_idx > 3)) {
APPEND_DEBUG('g');
+ mutex_lock(&driver->smd_data[MODEM_DATA].smd_ch_mutex);
smd_write(driver->smd_data[MODEM_DATA].ch,
driver->hdlc_buf, hdlc.dest_idx - 3);
+ mutex_unlock(&driver->smd_data[MODEM_DATA].smd_ch_mutex);
APPEND_DEBUG('h');
#ifdef DIAG_DEBUG
printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
@@ -1076,6 +1182,7 @@
1, DUMP_PREFIX_ADDRESS, data, len, 1);
#endif /* DIAG DEBUG */
}
+ mutex_unlock(&driver->diag_hdlc_mutex);
}
#ifdef CONFIG_DIAG_OVER_USB
@@ -1303,6 +1410,9 @@
diag_dci_notify_client(smd_info->peripheral_mask,
DIAG_STATUS_OPEN);
}
+ } else if (event == SMD_EVENT_DATA && !driver->real_time_mode &&
+ smd_info->type == SMD_DATA_TYPE) {
+ process_lock_on_notify(&smd_info->nrt_lock);
}
wake_up(&driver->smd_wait_q);
@@ -1395,6 +1505,9 @@
void diag_smd_destructor(struct diag_smd_info *smd_info)
{
+ if (smd_info->type == SMD_DATA_TYPE)
+ wake_lock_destroy(&smd_info->nrt_lock.read_lock);
+
if (smd_info->ch)
smd_close(smd_info->ch);
@@ -1411,6 +1524,7 @@
{
smd_info->peripheral = peripheral;
smd_info->type = type;
+ mutex_init(&smd_info->smd_ch_mutex);
switch (peripheral) {
case MODEM_DATA:
@@ -1505,6 +1619,30 @@
goto err;
}
+ smd_info->nrt_lock.enabled = 0;
+ smd_info->nrt_lock.ref_count = 0;
+ smd_info->nrt_lock.copy_count = 0;
+ if (type == SMD_DATA_TYPE) {
+ spin_lock_init(&smd_info->nrt_lock.read_spinlock);
+
+ switch (peripheral) {
+ case MODEM_DATA:
+ wake_lock_init(&smd_info->nrt_lock.read_lock,
+ WAKE_LOCK_SUSPEND, "diag_nrt_modem_read");
+ break;
+ case LPASS_DATA:
+ wake_lock_init(&smd_info->nrt_lock.read_lock,
+ WAKE_LOCK_SUSPEND, "diag_nrt_lpass_read");
+ break;
+ case WCNSS_DATA:
+ wake_lock_init(&smd_info->nrt_lock.read_lock,
+ WAKE_LOCK_SUSPEND, "diag_nrt_wcnss_read");
+ break;
+ default:
+ break;
+ }
+ }
+
return 1;
err:
kfree(smd_info->buf_in_1);
@@ -1525,6 +1663,8 @@
diag_debug_buf_idx = 0;
driver->read_len_legacy = 0;
driver->use_device_tree = has_device_tree();
+ driver->real_time_mode = 1;
+ mutex_init(&driver->diag_hdlc_mutex);
mutex_init(&driver->diag_cntl_mutex);
success = diag_smd_constructor(&driver->smd_data[MODEM_DATA],
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index afbe4be..8cf15de 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -23,6 +23,11 @@
void diagfwd_exit(void);
void diag_process_hdlc(void *data, unsigned len);
void diag_smd_send_req(struct diag_smd_info *smd_info);
+void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time);
+void process_lock_on_notify(struct diag_nrt_wake_lock *lock);
+void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len);
+void process_lock_on_copy(struct diag_nrt_wake_lock *lock);
+void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock);
void diag_usb_legacy_notifier(void *, unsigned, struct diag_request *);
long diagchar_ioctl(struct file *, unsigned int, unsigned long);
int diag_device_write(void *, int, struct diag_request *);
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
index b934805..475f5ba 100644
--- a/drivers/char/diag/diagfwd_bridge.c
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -65,7 +65,9 @@
driver->in_busy_smux = 0;
diagfwd_connect_smux();
} else {
- if (diag_hsic[index].hsic_device_enabled) {
+ if (diag_hsic[index].hsic_device_enabled &&
+ (driver->logging_mode != MEMORY_DEVICE_MODE ||
+ diag_hsic[index].hsic_data_requested)) {
diag_hsic[index].in_busy_hsic_read_on_device = 0;
diag_hsic[index].in_busy_hsic_write = 0;
/* If the HSIC (diag_bridge) platform
@@ -126,20 +128,24 @@
usb_diag_free_req(diag_bridge[i].ch);
}
- if (i == SMUX && driver->diag_smux_enabled &&
+ if (i == SMUX) {
+ if (driver->diag_smux_enabled &&
driver->logging_mode == USB_MODE) {
- driver->in_busy_smux = 1;
- driver->lcid = LCID_INVALID;
- driver->smux_connected = 0;
- /* Turn off communication over usb and smux */
- msm_smux_close(LCID_VALID);
+ driver->in_busy_smux = 1;
+ driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
+ /*
+ * Turn off communication over usb
+ * and smux
+ */
+ msm_smux_close(LCID_VALID);
+ }
} else {
if (diag_hsic[i].hsic_device_enabled &&
- driver->logging_mode !=
- MEMORY_DEVICE_MODE) {
+ (driver->logging_mode != MEMORY_DEVICE_MODE
+ || !diag_hsic[i].hsic_data_requested)) {
diag_hsic[i].
- in_busy_hsic_read_on_device
- = 1;
+ in_busy_hsic_read_on_device = 1;
diag_hsic[i].in_busy_hsic_write = 1;
/* Turn off communication over usb
* and HSIC */
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 7e58249..4ddd78a 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
#include <linux/diagchar.h>
#include <linux/platform_device.h>
#include <linux/kmemleak.h>
+#include <linux/delay.h>
#include "diagchar.h"
#include "diagfwd.h"
#include "diagfwd_cntl.h"
@@ -131,6 +132,83 @@
return flag;
}
+void diag_send_diag_mode_update(int real_time)
+{
+ int i;
+
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+ diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
+ real_time);
+}
+
+void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
+ int real_time)
+{
+ struct diag_ctrl_msg_diagmode diagmode;
+ char buf[sizeof(struct diag_ctrl_msg_diagmode)];
+ int msg_size = sizeof(struct diag_ctrl_msg_diagmode);
+ int wr_size = -ENOMEM, retry_count = 0, timer;
+
+ /* For now only allow the modem to receive the message */
+ if (!smd_info || smd_info->type != SMD_CNTL_TYPE ||
+ (smd_info->peripheral != MODEM_DATA))
+ return;
+
+ mutex_lock(&driver->diag_cntl_mutex);
+ diagmode.ctrl_pkt_id = DIAG_CTRL_MSG_DIAGMODE;
+ diagmode.ctrl_pkt_data_len = 36;
+ diagmode.version = 1;
+ diagmode.sleep_vote = real_time ? 1 : 0;
+ /*
+ * 0 - Disables real-time logging (to prevent
+ * frequent APPS wake-ups, etc.).
+ * 1 - Enable real-time logging
+ */
+ diagmode.real_time = real_time;
+ diagmode.use_nrt_values = 0;
+ diagmode.commit_threshold = 0;
+ diagmode.sleep_threshold = 0;
+ diagmode.sleep_time = 0;
+ diagmode.drain_timer_val = 0;
+ diagmode.event_stale_timer_val = 0;
+
+ memcpy(buf, &diagmode, msg_size);
+
+ if (smd_info->ch) {
+ while (retry_count < 3) {
+ wr_size = smd_write(smd_info->ch, buf, msg_size);
+ if (wr_size == -ENOMEM) {
+ /*
+ * The smd channel is full. Delay while
+ * smd processes existing data and smd
+ * has memory become available. The delay
+ * of 2000 was determined empirically as
+ * best value to use.
+ */
+ retry_count++;
+ for (timer = 0; timer < 5; timer++)
+ udelay(2000);
+ } else {
+ struct diag_smd_info *data =
+ &driver->smd_data[smd_info->peripheral];
+ driver->real_time_mode = real_time;
+ process_lock_enabling(&data->nrt_lock,
+ real_time);
+ break;
+ }
+ }
+ if (wr_size != msg_size)
+ pr_err("diag: proc %d fail feature update %d, tried %d",
+ smd_info->peripheral,
+ wr_size, msg_size);
+ } else {
+ pr_err("diag: ch invalid, feature update on proc %d\n",
+ smd_info->peripheral);
+ }
+
+ mutex_unlock(&driver->diag_cntl_mutex);
+}
+
static int diag_smd_cntl_probe(struct platform_device *pdev)
{
int r = 0;
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index c28b06d..7cd1866 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -84,11 +84,28 @@
/* Copy feature mask here */
} __packed;
+struct diag_ctrl_msg_diagmode {
+ uint32_t ctrl_pkt_id;
+ uint32_t ctrl_pkt_data_len;
+ uint32_t version;
+ uint32_t sleep_vote;
+ uint32_t real_time;
+ uint32_t use_nrt_values;
+ uint32_t commit_threshold;
+ uint32_t sleep_threshold;
+ uint32_t sleep_time;
+ uint32_t drain_timer_val;
+ uint32_t event_stale_timer_val;
+} __packed;
+
void diagfwd_cntl_init(void);
void diagfwd_cntl_exit(void);
void diag_read_smd_cntl_work_fn(struct work_struct *);
void diag_clean_reg_fn(struct work_struct *work);
int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
int total_recd);
+void diag_send_diag_mode_update(int real_time);
+void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
+ int real_time);
#endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 616c498..fa46aab 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -227,8 +227,12 @@
if (diag_hsic[index].in_busy_hsic_write)
return -EBUSY;
- /* Don't allow suspend if in MEMORY_DEVICE_MODE */
- if (driver->logging_mode == MEMORY_DEVICE_MODE)
+ /*
+ * Don't allow suspend if in MEMORY_DEVICE_MODE and if there
+ * has been hsic data requested
+ */
+ if (driver->logging_mode == MEMORY_DEVICE_MODE &&
+ diag_hsic[index].hsic_ch)
return -EBUSY;
diag_hsic[index].hsic_suspend = 1;
@@ -288,7 +292,7 @@
}
/* diagfwd_cancel_hsic is called to cancel outstanding read/writes */
-int diagfwd_cancel_hsic(void)
+int diagfwd_cancel_hsic(int reopen)
{
int err, i;
@@ -302,17 +306,24 @@
diag_hsic[i].hsic_ch = 0;
diag_hsic[i].hsic_device_opened = 0;
diag_bridge_close(i);
- hsic_diag_bridge_ops[i].ctxt = (void *)(i);
- err = diag_bridge_open(i,
- &hsic_diag_bridge_ops[i]);
- if (err) {
- pr_err("diag: HSIC %d channel open error: %d\n",
- i, err);
+ if (reopen) {
+ hsic_diag_bridge_ops[i].ctxt =
+ (void *)(i);
+ err = diag_bridge_open(i,
+ &hsic_diag_bridge_ops[i]);
+ if (err) {
+ pr_err("diag: HSIC %d channel open error: %d\n",
+ i, err);
+ } else {
+ pr_debug("diag: opened HSIC channel: %d\n",
+ i);
+ diag_hsic[i].
+ hsic_device_opened = 1;
+ diag_hsic[i].hsic_ch = 1;
+ }
+ diag_hsic[i].hsic_data_requested = 1;
} else {
- pr_debug("diag: opened HSIC channel: %d\n",
- i);
- diag_hsic[i].hsic_device_opened = 1;
- diag_hsic[i].hsic_ch = 1;
+ diag_hsic[i].hsic_data_requested = 0;
}
}
}
@@ -428,15 +439,20 @@
diagmem_hsic_init(pdev->id);
INIT_WORK(&(diag_hsic[pdev->id].diag_read_hsic_work),
diag_read_hsic_work_fn);
+ diag_hsic[pdev->id].hsic_data_requested =
+ (driver->logging_mode == MEMORY_DEVICE_MODE) ? 0 : 1;
diag_hsic[pdev->id].hsic_inited = 1;
}
/*
* The probe function was called after the usb was connected
- * on the legacy channel OR ODL is turned on. Communication over usb
- * mdm and HSIC needs to be turned on.
+ * on the legacy channel OR ODL is turned on and hsic data is
+ * requested. Communication over usb mdm and HSIC needs to be
+ * turned on.
*/
- if (diag_bridge[pdev->id].usb_connected || (driver->logging_mode ==
- MEMORY_DEVICE_MODE)) {
+ if ((diag_bridge[pdev->id].usb_connected &&
+ (driver->logging_mode != MEMORY_DEVICE_MODE)) ||
+ ((driver->logging_mode == MEMORY_DEVICE_MODE) &&
+ diag_hsic[pdev->id].hsic_data_requested)) {
if (diag_hsic[pdev->id].hsic_device_opened) {
/* should not happen. close it before re-opening */
pr_warn("diag: HSIC channel already opened in probe\n");
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index d171efa..64556f2 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -19,8 +19,10 @@
#define N_MDM_READ 1
#define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
#define MAX_HSIC_CH 4
+#define REOPEN_HSIC 1
+#define DONT_REOPEN_HSIC 0
int diagfwd_write_complete_hsic(struct diag_request *, int index);
-int diagfwd_cancel_hsic(void);
+int diagfwd_cancel_hsic(int reopen);
void diag_read_usb_hsic_work_fn(struct work_struct *work);
void diag_usb_read_complete_hsic_fn(struct work_struct *w);
extern struct diag_bridge_ops hsic_diag_bridge_ops[MAX_HSIC_CH];
@@ -37,6 +39,7 @@
int hsic_device_enabled;
int hsic_device_opened;
int hsic_suspend;
+ int hsic_data_requested;
int in_busy_hsic_read_on_device;
int in_busy_hsic_write;
struct work_struct diag_read_hsic_work;
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 2f87803..b0fb9d8 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -19,7 +19,6 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/clk.h>
-#include <linux/android_pmem.h>
#include <linux/msm_rotator.h>
#include <linux/io.h>
#include <mach/msm_rotator_imem.h>
@@ -856,10 +855,6 @@
struct file *file = NULL;
int put_needed, fb_num;
#endif
-#ifdef CONFIG_ANDROID_PMEM
- unsigned long vstart;
-#endif
-
*p_need = 0;
#ifdef CONFIG_FB
@@ -890,27 +885,14 @@
}
#endif
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
return msm_rotator_iommu_map_buf(fbd->memory_id, domain, start,
len, p_ihdl, secure);
-#endif
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(fbd->memory_id, start, &vstart, len, p_file))
- return 0;
- else
- return -ENOMEM;
-#endif
}
static void put_img(struct file *p_file, struct ion_handle *p_ihdl,
int domain, unsigned int secure)
{
-#ifdef CONFIG_ANDROID_PMEM
- if (p_file != NULL)
- put_pmem_file(p_file);
-#endif
-
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
if (!IS_ERR_OR_NULL(p_ihdl)) {
pr_debug("%s(): p_ihdl %p\n", __func__, p_ihdl);
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 4774c76..988d1c9 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -158,7 +158,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-cti.c b/drivers/coresight/coresight-cti.c
index e077edf..6a8d412 100644
--- a/drivers/coresight/coresight-cti.c
+++ b/drivers/coresight/coresight-cti.c
@@ -402,7 +402,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cti-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index d52ab28..31f85dc 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -375,7 +375,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "etb-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index 1033233..2777769 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -2090,7 +2090,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "etm-base");
if (!res)
return -ENODEV;
reg_size = resource_size(res);
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 7f39a3e..625f481 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -187,7 +187,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "funnel-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
index fe37e5e..d4afa42 100644
--- a/drivers/coresight/coresight-replicator.c
+++ b/drivers/coresight/coresight-replicator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -139,7 +139,8 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "replicator-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 1db499b..87cf63a 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -806,7 +806,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "stm-base");
if (!res)
return -ENODEV;
@@ -814,7 +814,8 @@
if (!drvdata->base)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "stm-data-base");
if (!res)
return -ENODEV;
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 86276b7..4a9a97a 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1090,7 +1090,7 @@
return -ENOMEM;
drvdata->bamdata = bamdata;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bam-base");
if (!res)
return -ENODEV;
@@ -1147,7 +1147,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tmc-base");
if (!res)
return -ENODEV;
reg_size = resource_size(res);
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index 3726a0d..7ea71d3 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,9 +18,15 @@
#include <linux/io.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/of_coresight.h>
#include <linux/coresight.h>
+#include <linux/regulator/consumer.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <mach/gpiomux.h>
#include "coresight-priv.h"
@@ -58,20 +64,194 @@
#define TPIU_ITATBCTR1 (0xEF4)
#define TPIU_ITATBCTR0 (0xEF8)
+enum tpiu_out_mode {
+ TPIU_OUT_MODE_NONE,
+ TPIU_OUT_MODE_MICTOR,
+ TPIU_OUT_MODE_SDC,
+};
+
+enum tpiu_set {
+ TPIU_SET_NONE,
+ TPIU_SET_A,
+ TPIU_SET_B,
+};
+
struct tpiu_drvdata {
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
struct clk *clk;
+ struct mutex mutex;
+ enum tpiu_out_mode out_mode;
+ struct regulator *reg;
+ unsigned int reg_low;
+ unsigned int reg_high;
+ unsigned int reg_lpm;
+ unsigned int reg_hpm;
+ enum tpiu_set set;
+ unsigned int seta_gpiocnt;
+ unsigned int *seta_gpios;
+ struct gpiomux_setting *seta_cfgs;
+ unsigned int setb_gpiocnt;
+ unsigned int *setb_gpios;
+ struct gpiomux_setting *setb_cfgs;
+ bool enable;
};
-static void __tpiu_enable(struct tpiu_drvdata *drvdata)
+struct gpiomux_setting old_cfg;
+
+static void tpiu_flush_and_stop(struct tpiu_drvdata *drvdata)
{
+ int count;
+ uint32_t ffcr;
+
+ ffcr = tpiu_readl(drvdata, TPIU_FFCR);
+ ffcr |= BIT(12);
+ tpiu_writel(drvdata, ffcr, TPIU_FFCR);
+ ffcr |= BIT(6);
+ tpiu_writel(drvdata, ffcr, TPIU_FFCR);
+ /* Ensure flush completes */
+ for (count = TIMEOUT_US; BVAL(tpiu_readl(drvdata, TPIU_FFCR), 6) != 0
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while flushing TPIU, TPIU_FFCR: %#x\n",
+ tpiu_readl(drvdata, TPIU_FFCR));
+}
+
+static int __tpiu_enable_seta(struct tpiu_drvdata *drvdata)
+{
+ int i, ret;
+
+ if (!drvdata->seta_gpiocnt)
+ return -EINVAL;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++) {
+ ret = gpio_request(drvdata->seta_gpios[i], NULL);
+ if (ret) {
+ dev_err(drvdata->dev,
+ "gpio_request failed for seta_gpio: %u\n",
+ drvdata->seta_gpios[i]);
+ goto err0;
+ }
+ ret = msm_gpiomux_write(drvdata->seta_gpios[i],
+ GPIOMUX_ACTIVE,
+ &drvdata->seta_cfgs[i],
+ &old_cfg);
+ if (ret < 0) {
+ dev_err(drvdata->dev,
+ "gpio write failed for seta_gpio: %u\n",
+ drvdata->seta_gpios[i]);
+ goto err1;
+ }
+ }
+ return 0;
+err1:
+ gpio_free(drvdata->seta_gpios[i]);
+err0:
+ i--;
+ while (i >= 0) {
+ gpio_free(drvdata->seta_gpios[i]);
+ i--;
+ }
+ return ret;
+}
+
+static int __tpiu_enable_setb(struct tpiu_drvdata *drvdata)
+{
+ int i, ret;
+
+ if (!drvdata->setb_gpiocnt)
+ return -EINVAL;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++) {
+ ret = gpio_request(drvdata->setb_gpios[i], NULL);
+ if (ret) {
+ dev_err(drvdata->dev,
+ "gpio_request failed for setb_gpio: %u\n",
+ drvdata->setb_gpios[i]);
+ goto err0;
+ }
+ ret = msm_gpiomux_write(drvdata->setb_gpios[i],
+ GPIOMUX_ACTIVE,
+ &drvdata->setb_cfgs[i],
+ &old_cfg);
+ if (ret < 0) {
+ dev_err(drvdata->dev,
+ "gpio write failed for setb_gpio: %u\n",
+ drvdata->setb_gpios[i]);
+ goto err1;
+ }
+ }
+ return 0;
+err1:
+ gpio_free(drvdata->setb_gpios[i]);
+err0:
+ i--;
+ while (i >= 0) {
+ gpio_free(drvdata->setb_gpios[i]);
+ i--;
+ }
+ return ret;
+}
+
+static int __tpiu_enable_to_mictor(struct tpiu_drvdata *drvdata)
+{
+ int ret;
+
+ if (drvdata->set == TPIU_SET_A) {
+ ret = __tpiu_enable_seta(drvdata);
+ if (ret)
+ return ret;
+ } else if (drvdata->set == TPIU_SET_B) {
+ ret = __tpiu_enable_setb(drvdata);
+ if (ret)
+ return ret;
+ }
+
TPIU_UNLOCK(drvdata);
- /* TODO: fill this up */
+ tpiu_writel(drvdata, 0x8000, TPIU_CURR_PORTSZ);
+ tpiu_writel(drvdata, 0x101, TPIU_FFCR);
TPIU_LOCK(drvdata);
+
+ return 0;
+}
+
+static int __tpiu_enable_to_sdc(struct tpiu_drvdata *drvdata)
+{
+ int ret;
+
+ if (!drvdata->reg)
+ return -EINVAL;
+
+ ret = regulator_set_optimum_mode(drvdata->reg, drvdata->reg_hpm);
+ if (ret < 0)
+ return ret;
+ ret = regulator_set_voltage(drvdata->reg, drvdata->reg_low,
+ drvdata->reg_high);
+ if (ret)
+ goto err0;
+ ret = regulator_enable(drvdata->reg);
+ if (ret)
+ goto err1;
+
+ msm_tlmm_misc_reg_write(TLMM_SDC2_HDRV_PULL_CTL, 0x16D);
+ msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 1);
+
+ TPIU_UNLOCK(drvdata);
+
+ tpiu_writel(drvdata, 0x8, TPIU_CURR_PORTSZ);
+ tpiu_writel(drvdata, 0x103, TPIU_FFCR);
+
+ TPIU_LOCK(drvdata);
+
+ return 0;
+err1:
+ regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+err0:
+ regulator_set_optimum_mode(drvdata->reg, 0);
+ return ret;
}
static int tpiu_enable(struct coresight_device *csdev)
@@ -83,27 +263,85 @@
if (ret)
return ret;
- __tpiu_enable(drvdata);
+ mutex_lock(&drvdata->mutex);
+
+ if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+ ret = __tpiu_enable_to_mictor(drvdata);
+ else
+ ret = __tpiu_enable_to_sdc(drvdata);
+ if (ret)
+ goto err;
+ drvdata->enable = true;
+
+ mutex_unlock(&drvdata->mutex);
dev_info(drvdata->dev, "TPIU enabled\n");
return 0;
+err:
+ mutex_unlock(&drvdata->mutex);
+ clk_disable_unprepare(drvdata->clk);
+ return ret;
}
static void __tpiu_disable(struct tpiu_drvdata *drvdata)
{
TPIU_UNLOCK(drvdata);
- tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
- tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
+ tpiu_flush_and_stop(drvdata);
TPIU_LOCK(drvdata);
}
+static void __tpiu_disable_seta(struct tpiu_drvdata *drvdata)
+{
+ int i;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++)
+ gpio_free(drvdata->seta_gpios[i]);
+}
+
+static void __tpiu_disable_setb(struct tpiu_drvdata *drvdata)
+{
+ int i;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++)
+ gpio_free(drvdata->setb_gpios[i]);
+}
+
+static void __tpiu_disable_to_mictor(struct tpiu_drvdata *drvdata)
+{
+ __tpiu_disable(drvdata);
+
+ if (drvdata->set == TPIU_SET_A)
+ __tpiu_disable_seta(drvdata);
+ else if (drvdata->set == TPIU_SET_B)
+ __tpiu_disable_setb(drvdata);
+}
+
+static void __tpiu_disable_to_sdc(struct tpiu_drvdata *drvdata)
+{
+ __tpiu_disable(drvdata);
+
+ msm_tlmm_misc_reg_write(TLMM_ETM_MODE_REG, 0);
+
+ regulator_disable(drvdata->reg);
+ regulator_set_optimum_mode(drvdata->reg, 0);
+ regulator_set_voltage(drvdata->reg, 0, drvdata->reg_high);
+}
+
static void tpiu_disable(struct coresight_device *csdev)
{
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- __tpiu_disable(drvdata);
+ mutex_lock(&drvdata->mutex);
+
+ if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+ __tpiu_disable_to_mictor(drvdata);
+ else
+ __tpiu_disable_to_sdc(drvdata);
+ drvdata->enable = false;
+
+ mutex_unlock(&drvdata->mutex);
clk_disable_unprepare(drvdata->clk);
@@ -125,10 +363,331 @@
.abort = tpiu_abort,
};
+static ssize_t tpiu_show_out_mode(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ drvdata->out_mode == TPIU_OUT_MODE_MICTOR ?
+ "mictor" : "sdc");
+}
+
+static ssize_t tpiu_store_out_mode(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ char str[10] = "";
+ int ret;
+
+ if (strlen(buf) >= 10)
+ return -EINVAL;
+ if (sscanf(buf, "%s", str) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ if (!strcmp(str, "mictor")) {
+ if (drvdata->out_mode == TPIU_OUT_MODE_MICTOR)
+ goto out;
+
+ if (!drvdata->enable) {
+ drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+ goto out;
+ }
+ __tpiu_disable_to_sdc(drvdata);
+ ret = __tpiu_enable_to_mictor(drvdata);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to enable mictor\n");
+ goto err;
+ }
+ drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+ } else if (!strcmp(str, "sdc")) {
+ if (drvdata->out_mode == TPIU_OUT_MODE_SDC)
+ goto out;
+
+ if (!drvdata->enable) {
+ drvdata->out_mode = TPIU_OUT_MODE_SDC;
+ goto out;
+ }
+ __tpiu_disable_to_mictor(drvdata);
+ ret = __tpiu_enable_to_sdc(drvdata);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to enable sdc\n");
+ goto err;
+ }
+ drvdata->out_mode = TPIU_OUT_MODE_SDC;
+ }
+out:
+ mutex_unlock(&drvdata->mutex);
+ return size;
+err:
+ mutex_unlock(&drvdata->mutex);
+ return ret;
+}
+static DEVICE_ATTR(out_mode, S_IRUGO | S_IWUSR, tpiu_show_out_mode,
+ tpiu_store_out_mode);
+
static const struct coresight_ops tpiu_cs_ops = {
.sink_ops = &tpiu_sink_ops,
};
+static ssize_t tpiu_show_set(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ drvdata->set == TPIU_SET_A ?
+ "a" : "b");
+}
+
+static ssize_t tpiu_store_set(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ char str[10] = "";
+ int ret;
+
+ if (strlen(buf) >= 10)
+ return -EINVAL;
+ if (sscanf(buf, "%s", str) != 1)
+ return -EINVAL;
+
+ mutex_lock(&drvdata->mutex);
+ if (!strcmp(str, "a")) {
+ if (drvdata->set == TPIU_SET_A)
+ goto out;
+
+ if (!drvdata->enable || drvdata->out_mode !=
+ TPIU_OUT_MODE_MICTOR) {
+ drvdata->set = TPIU_SET_A;
+ goto out;
+ }
+ __tpiu_disable_setb(drvdata);
+ ret = __tpiu_enable_seta(drvdata);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to enable set A\n");
+ goto err;
+ }
+ drvdata->set = TPIU_SET_A;
+ } else if (!strcmp(str, "b")) {
+ if (drvdata->set == TPIU_SET_B)
+ goto out;
+
+ if (!drvdata->enable || drvdata->out_mode !=
+ TPIU_OUT_MODE_MICTOR) {
+ drvdata->set = TPIU_SET_B;
+ goto out;
+ }
+ __tpiu_disable_seta(drvdata);
+ ret = __tpiu_enable_setb(drvdata);
+ if (ret) {
+ dev_err(drvdata->dev, "failed to enable set B\n");
+ goto err;
+ }
+ drvdata->set = TPIU_SET_B;
+ }
+out:
+ mutex_unlock(&drvdata->mutex);
+ return size;
+err:
+ mutex_unlock(&drvdata->mutex);
+ return ret;
+}
+static DEVICE_ATTR(set, S_IRUGO | S_IWUSR, tpiu_show_set, tpiu_store_set);
+
+static struct attribute *tpiu_attrs[] = {
+ &dev_attr_out_mode.attr,
+ &dev_attr_set.attr,
+ NULL,
+};
+
+static struct attribute_group tpiu_attr_grp = {
+ .attrs = tpiu_attrs,
+};
+
+static const struct attribute_group *tpiu_attr_grps[] = {
+ &tpiu_attr_grp,
+ NULL,
+};
+
+static int __devinit tpiu_parse_of_data(struct platform_device *pdev,
+ struct tpiu_drvdata *drvdata)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct device_node *reg_node = NULL;
+ struct device *dev = &pdev->dev;
+ const __be32 *prop;
+ int i, len, gpio, ret;
+ uint32_t *seta_cfgs, *setb_cfgs;
+
+ reg_node = of_parse_phandle(node, "vdd-supply", 0);
+ if (reg_node) {
+ drvdata->reg = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(drvdata->reg))
+ return PTR_ERR(drvdata->reg);
+
+ prop = of_get_property(node, "qcom,vdd-voltage-level", &len);
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ of_node_put(reg_node);
+ return -EINVAL;
+ } else {
+ drvdata->reg_low = be32_to_cpup(&prop[0]);
+ drvdata->reg_high = be32_to_cpup(&prop[1]);
+ }
+
+ prop = of_get_property(node, "qcom,vdd-current-level", &len);
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ of_node_put(reg_node);
+ return -EINVAL;
+ } else {
+ drvdata->reg_lpm = be32_to_cpup(&prop[0]);
+ drvdata->reg_hpm = be32_to_cpup(&prop[1]);
+ }
+ of_node_put(reg_node);
+ } else {
+ dev_err(dev, "sdc voltage supply not specified or available\n");
+ }
+
+ drvdata->out_mode = TPIU_OUT_MODE_MICTOR;
+ drvdata->set = TPIU_SET_B;
+
+ drvdata->seta_gpiocnt = of_gpio_named_count(node, "qcom,seta-gpios");
+ if (drvdata->seta_gpiocnt) {
+ drvdata->seta_gpios = devm_kzalloc(dev,
+ sizeof(*drvdata->seta_gpios) *
+ drvdata->seta_gpiocnt, GFP_KERNEL);
+ if (!drvdata->seta_gpios)
+ return -ENOMEM;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++) {
+ gpio = of_get_named_gpio(node, "qcom,seta-gpios", i);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ drvdata->seta_gpios[i] = gpio;
+ }
+
+ drvdata->seta_cfgs = devm_kzalloc(dev,
+ sizeof(*drvdata->seta_cfgs) *
+ drvdata->seta_gpiocnt, GFP_KERNEL);
+ if (!drvdata->seta_cfgs)
+ return -ENOMEM;
+
+ seta_cfgs = devm_kzalloc(dev, sizeof(*seta_cfgs) *
+ drvdata->seta_gpiocnt, GFP_KERNEL);
+ if (!seta_cfgs)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(node, "qcom,seta-gpios-func",
+ (u32 *)seta_cfgs,
+ drvdata->seta_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++)
+ drvdata->seta_cfgs[i].func = seta_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,seta-gpios-drv",
+ (u32 *)seta_cfgs,
+ drvdata->seta_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++)
+ drvdata->seta_cfgs[i].drv = seta_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,seta-gpios-pull",
+ (u32 *)seta_cfgs,
+ drvdata->seta_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++)
+ drvdata->seta_cfgs[i].pull = seta_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,seta-gpios-dir",
+ (u32 *)seta_cfgs,
+ drvdata->seta_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->seta_gpiocnt; i++)
+ drvdata->seta_cfgs[i].dir = seta_cfgs[i];
+ } else {
+ dev_err(dev, "seta gpios not specified\n");
+ }
+
+ drvdata->setb_gpiocnt = of_gpio_named_count(node, "qcom,setb-gpios");
+ if (drvdata->setb_gpiocnt) {
+ drvdata->setb_gpios = devm_kzalloc(dev,
+ sizeof(*drvdata->setb_gpios) *
+ drvdata->setb_gpiocnt, GFP_KERNEL);
+ if (!drvdata->setb_gpios)
+ return -ENOMEM;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++) {
+ gpio = of_get_named_gpio(node, "qcom,setb-gpios", i);
+ if (!gpio_is_valid(gpio))
+ return gpio;
+
+ drvdata->setb_gpios[i] = gpio;
+ }
+
+ drvdata->setb_cfgs = devm_kzalloc(dev,
+ sizeof(*drvdata->setb_cfgs) *
+ drvdata->setb_gpiocnt, GFP_KERNEL);
+ if (!drvdata->setb_cfgs)
+ return -ENOMEM;
+
+ setb_cfgs = devm_kzalloc(dev, sizeof(*setb_cfgs) *
+ drvdata->setb_gpiocnt, GFP_KERNEL);
+ if (!setb_cfgs)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(node, "qcom,setb-gpios-func",
+ (u32 *)setb_cfgs,
+ drvdata->setb_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++)
+ drvdata->setb_cfgs[i].func = setb_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,setb-gpios-drv",
+ (u32 *)setb_cfgs,
+ drvdata->setb_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++)
+ drvdata->setb_cfgs[i].drv = setb_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,setb-gpios-pull",
+ (u32 *)setb_cfgs,
+ drvdata->setb_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++)
+ drvdata->setb_cfgs[i].pull = setb_cfgs[i];
+
+ ret = of_property_read_u32_array(node, "qcom,setb-gpios-dir",
+ (u32 *)setb_cfgs,
+ drvdata->setb_gpiocnt);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < drvdata->setb_gpiocnt; i++)
+ drvdata->setb_cfgs[i].dir = setb_cfgs[i];
+ } else {
+ dev_err(dev, "setb gpios not specified\n");
+ }
+
+ return 0;
+}
+
static int __devinit tpiu_probe(struct platform_device *pdev)
{
int ret;
@@ -151,7 +710,7 @@
drvdata->dev = &pdev->dev;
platform_set_drvdata(pdev, drvdata);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpiu-base");
if (!res)
return -ENODEV;
@@ -159,6 +718,8 @@
if (!drvdata->base)
return -ENOMEM;
+ mutex_init(&drvdata->mutex);
+
drvdata->clk = devm_clk_get(dev, "core_clk");
if (IS_ERR(drvdata->clk))
return PTR_ERR(drvdata->clk);
@@ -176,6 +737,12 @@
clk_disable_unprepare(drvdata->clk);
+ if (pdev->dev.of_node) {
+ ret = tpiu_parse_of_data(pdev, drvdata);
+ if (ret)
+ return ret;
+ }
+
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
@@ -184,6 +751,7 @@
desc->ops = &tpiu_cs_ops;
desc->pdata = pdev->dev.platform_data;
desc->dev = &pdev->dev;
+ desc->groups = tpiu_attr_grps;
desc->owner = THIS_MODULE;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev))
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 5c1cc5a..24cf30a 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -2366,6 +2366,7 @@
ce_support->aes_ccm = false;
ce_support->ota = pce_dev->ota;
ce_support->aligned_only = false;
+ ce_support->is_shared = false;
ce_support->bam = false;
return 0;
}
diff --git a/drivers/crypto/msm/qce.h b/drivers/crypto/msm/qce.h
index 8a31003..3ff84cf 100644
--- a/drivers/crypto/msm/qce.h
+++ b/drivers/crypto/msm/qce.h
@@ -113,6 +113,7 @@
bool ota;
bool aligned_only;
bool bam;
+ bool is_shared;
};
/* Sha operation parameters */
diff --git a/drivers/crypto/msm/qce40.c b/drivers/crypto/msm/qce40.c
index 84d41da..7b0964d 100644
--- a/drivers/crypto/msm/qce40.c
+++ b/drivers/crypto/msm/qce40.c
@@ -2634,6 +2634,7 @@
ce_support->aes_ccm = true;
ce_support->ota = false;
ce_support->aligned_only = false;
+ ce_support->is_shared = false;
ce_support->bam = false;
return 0;
}
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 9d8e825..8545a5c 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -41,6 +41,7 @@
#define CRYPTO_CONFIG_RESET 0xE001F
#define QCE_MAX_NUM_DSCR 0x400
#define QCE_SIZE_BAM_DSCR 0x08
+#define QCE_SECTOR_SIZE 0x200
static DEFINE_MUTEX(bam_register_cnt);
struct bam_registration_info {
@@ -61,6 +62,7 @@
unsigned char *coh_vmem; /* Allocated coherent virtual memory */
dma_addr_t coh_pmem; /* Allocated coherent physical memory */
int memsize; /* Memory allocated */
+ int is_shared; /* CE HW is shared */
void __iomem *iobase; /* Virtual io base of CE HW */
unsigned int phy_iobase; /* Physical io base of CE HW */
@@ -444,6 +446,7 @@
uint32_t enck_size_in_word = 0;
uint32_t key_size;
bool use_hw_key = false;
+ bool use_pipe_key = false;
uint32_t encr_cfg = 0;
uint32_t ivsize = creq->ivsize;
int i;
@@ -455,6 +458,7 @@
key_size = creq->encklen;
_byte_stream_to_net_words(enckey32, creq->enckey, key_size);
+ pce = cmdlistinfo->go_proc;
/* check for null key. If null, use hw key*/
enck_size_in_word = key_size/sizeof(uint32_t);
@@ -462,15 +466,22 @@
if (enckey32[i] != 0)
break;
}
- pce = cmdlistinfo->go_proc;
if (i == enck_size_in_word) {
use_hw_key = true;
pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
pce_dev->phy_iobase);
- } else {
+ }
+ if (use_hw_key == false) {
+ for (i = 0; i < enck_size_in_word; i++) {
+ if (enckey32[i] != 0xFFFFFFFF)
+ break;
+ }
+ if (i == enck_size_in_word)
+ use_pipe_key = true;
+ }
+ if (use_hw_key == false)
pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
pce_dev->phy_iobase);
- }
if ((creq->op == QCE_REQ_AEAD) && (creq->mode == QCE_MODE_CCM)) {
uint32_t authklen32 = creq->encklen/sizeof(uint32_t);
@@ -599,7 +610,10 @@
/* write xts du size */
pce = cmdlistinfo->encr_xts_du_size;
- pce->data = creq->cryptlen;
+ if (use_pipe_key == true)
+ pce->data = QCE_SECTOR_SIZE;
+ else
+ pce->data = creq->cryptlen;
}
if (creq->mode != QCE_MODE_ECB) {
if (creq->mode == QCE_MODE_XTS)
@@ -652,6 +666,10 @@
break;
} /* end of switch (creq->mode) */
+ if (use_pipe_key)
+ encr_cfg |= (CRYPTO_USE_PIPE_KEY_ENCR_ENABLED
+ << CRYPTO_USE_PIPE_KEY_ENCR);
+
/* write encr seg cfg */
pce = cmdlistinfo->encr_seg_cfg;
if ((creq->alg == CIPHER_ALG_DES) || (creq->alg == CIPHER_ALG_3DES)) {
@@ -1047,7 +1065,7 @@
/* Producer pipe will handle this connection */
sps_connect_info->mode = SPS_MODE_SRC;
sps_connect_info->options =
- SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_DESC_DONE;
+ SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
} else {
/* For CE consumer transfer, source should be
* system memory where as destination should
@@ -2333,6 +2351,7 @@
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.producer.event.callback = _aead_sps_producer_callback;
+ pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
&pce_dev->ce_sps.producer.event);
if (rc) {
@@ -2341,6 +2360,7 @@
}
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.consumer.event.callback = _aead_sps_consumer_callback;
+ pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
&pce_dev->ce_sps.consumer.event);
if (rc) {
@@ -2400,8 +2420,6 @@
if (totallen_in > SPS_MAX_PKT_SIZE) {
_qce_set_flag(&pce_dev->ce_sps.out_transfer,
SPS_IOVEC_FLAG_INT);
- pce_dev->ce_sps.producer.event.options =
- SPS_O_DESC_DONE;
pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
} else {
_qce_sps_add_data(
@@ -2489,6 +2507,7 @@
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.producer.event.callback =
_ablk_cipher_sps_producer_callback;
+ pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
&pce_dev->ce_sps.producer.event);
if (rc) {
@@ -2498,6 +2517,7 @@
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.consumer.event.callback =
_ablk_cipher_sps_consumer_callback;
+ pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
&pce_dev->ce_sps.consumer.event);
if (rc) {
@@ -2519,7 +2539,6 @@
if (areq->nbytes > SPS_MAX_PKT_SIZE) {
_qce_set_flag(&pce_dev->ce_sps.out_transfer,
SPS_IOVEC_FLAG_INT);
- pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
} else {
pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
@@ -2571,6 +2590,7 @@
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.producer.event.callback = _sha_sps_producer_callback;
+ pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
&pce_dev->ce_sps.producer.event);
if (rc) {
@@ -2580,6 +2600,7 @@
/* Register callback event for EOT (End of transfer) event. */
pce_dev->ce_sps.consumer.event.callback = _sha_sps_consumer_callback;
+ pce_dev->ce_sps.consumer.event.options = SPS_O_DESC_DONE;
rc = sps_register_event(pce_dev->ce_sps.consumer.pipe,
&pce_dev->ce_sps.consumer.event);
if (rc) {
@@ -2619,6 +2640,9 @@
struct resource *resource;
int rc = 0;
+ pce_dev->is_shared = of_property_read_bool((&pdev->dev)->of_node,
+ "qcom,ce-hw-shared");
+
if (of_property_read_u32((&pdev->dev)->of_node,
"qcom,bam-pipe-pair",
&pce_dev->ce_sps.pipe_pair_index)) {
@@ -2704,6 +2728,7 @@
rc = clk_set_rate(pce_dev->ce_core_src_clk, 100000000);
if (rc) {
clk_put(pce_dev->ce_core_src_clk);
+ pce_dev->ce_core_src_clk = NULL;
pr_err("Unable to set the core src clk @100Mhz.\n");
goto err_clk;
}
@@ -2748,43 +2773,79 @@
}
pce_dev->ce_bus_clk = ce_bus_clk;
- /* Enable CE core clk */
- rc = clk_prepare_enable(pce_dev->ce_core_clk);
- if (rc) {
- pr_err("Unable to enable/prepare CE core clk\n");
- if (pce_dev->ce_core_src_clk != NULL)
- clk_put(pce_dev->ce_core_src_clk);
- clk_put(pce_dev->ce_core_clk);
+err_clk:
+ if (rc)
+ pr_err("Unable to init CE clks, rc = %d\n", rc);
+ return rc;
+}
+
+static void __qce_deinit_clk(struct qce_device *pce_dev)
+{
+ if (pce_dev->ce_clk != NULL) {
clk_put(pce_dev->ce_clk);
- goto err_clk;
- } else {
- /* Enable CE clk */
+ pce_dev->ce_clk = NULL;
+ }
+ if (pce_dev->ce_core_clk != NULL) {
+ clk_put(pce_dev->ce_core_clk);
+ pce_dev->ce_core_clk = NULL;
+ }
+ if (pce_dev->ce_bus_clk != NULL) {
+ clk_put(pce_dev->ce_bus_clk);
+ pce_dev->ce_bus_clk = NULL;
+ }
+ if (pce_dev->ce_core_src_clk != NULL) {
+ clk_put(pce_dev->ce_core_src_clk);
+ pce_dev->ce_core_src_clk = NULL;
+ }
+}
+
+static int __qce_enable_clk(void *handle)
+{
+ struct qce_device *pce_dev = (struct qce_device *) handle;
+ int rc = 0;
+
+ /* Enable CE core clk */
+ if (pce_dev->ce_core_clk != NULL) {
+ rc = clk_prepare_enable(pce_dev->ce_core_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE core clk\n");
+ return rc;
+ }
+ }
+ /* Enable CE clk */
+ if (pce_dev->ce_clk != NULL) {
rc = clk_prepare_enable(pce_dev->ce_clk);
if (rc) {
pr_err("Unable to enable/prepare CE iface clk\n");
clk_disable_unprepare(pce_dev->ce_core_clk);
- if (pce_dev->ce_core_src_clk != NULL)
- clk_put(pce_dev->ce_core_src_clk);
- clk_put(pce_dev->ce_core_clk);
- clk_put(pce_dev->ce_clk);
- goto err_clk;
+ return rc;
}
- /* Enable AXI clk */
+ }
+ /* Enable AXI clk */
+ if (pce_dev->ce_bus_clk != NULL) {
rc = clk_prepare_enable(pce_dev->ce_bus_clk);
if (rc) {
pr_err("Unable to enable/prepare CE BUS clk\n");
+ clk_disable_unprepare(pce_dev->ce_clk);
clk_disable_unprepare(pce_dev->ce_core_clk);
- if (pce_dev->ce_core_src_clk != NULL)
- clk_put(pce_dev->ce_core_src_clk);
- clk_put(pce_dev->ce_core_clk);
- clk_put(pce_dev->ce_clk);
- clk_put(pce_dev->ce_bus_clk);
- goto err_clk;
+ return rc;
}
}
-err_clk:
- if (rc)
- pr_err("Unable to init CE clks, rc = %d\n", rc);
+ return rc;
+}
+
+static int __qce_disable_clk(void *handle)
+{
+ struct qce_device *pce_dev = (struct qce_device *) handle;
+ int rc = 0;
+
+ if (pce_dev->ce_clk != NULL)
+ clk_disable_unprepare(pce_dev->ce_clk);
+ if (pce_dev->ce_core_clk != NULL)
+ clk_disable_unprepare(pce_dev->ce_core_clk);
+ if (pce_dev->ce_bus_clk != NULL)
+ clk_disable_unprepare(pce_dev->ce_bus_clk);
+
return rc;
}
@@ -2824,8 +2885,13 @@
if (*rc)
goto err_mem;
+ *rc = __qce_enable_clk(pce_dev);
+ if (*rc)
+ goto err;
+
if (_probe_ce_engine(pce_dev)) {
*rc = -ENXIO;
+ __qce_disable_clk(pce_dev);
goto err;
}
*rc = 0;
@@ -2834,13 +2900,8 @@
return pce_dev;
err:
- clk_disable_unprepare(pce_dev->ce_clk);
- clk_disable_unprepare(pce_dev->ce_core_clk);
+ __qce_deinit_clk(pce_dev);
- if (pce_dev->ce_core_src_clk != NULL)
- clk_put(pce_dev->ce_core_src_clk);
- clk_put(pce_dev->ce_clk);
- clk_put(pce_dev->ce_core_clk);
err_mem:
if (pce_dev->coh_vmem)
dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
@@ -2870,14 +2931,8 @@
dma_free_coherent(pce_dev->pdev, pce_dev->memsize,
pce_dev->coh_vmem, pce_dev->coh_pmem);
- clk_disable_unprepare(pce_dev->ce_clk);
- clk_disable_unprepare(pce_dev->ce_core_clk);
- clk_disable_unprepare(pce_dev->ce_bus_clk);
- if (pce_dev->ce_core_src_clk != NULL)
- clk_put(pce_dev->ce_core_src_clk);
- clk_put(pce_dev->ce_clk);
- clk_put(pce_dev->ce_core_clk);
- clk_put(pce_dev->ce_bus_clk);
+ __qce_disable_clk(pce_dev);
+ __qce_deinit_clk(pce_dev);
qce_sps_exit(pce_dev);
kfree(handle);
@@ -2902,6 +2957,7 @@
ce_support->aes_xts = true;
ce_support->ota = false;
ce_support->bam = true;
+ ce_support->is_shared = (pce_dev->is_shared == 1) ? true : false;
ce_support->aes_ccm = true;
if (pce_dev->ce_sps.minor_version)
ce_support->aligned_only = false;
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 464fa21..1c63b70 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -30,7 +30,7 @@
comment "DEVFREQ Governors"
config DEVFREQ_GOV_SIMPLE_ONDEMAND
- bool "Simple Ondemand"
+ tristate "Simple Ondemand"
help
Chooses frequency based on the recent load on the device. Works
similar as ONDEMAND governor of CPUFREQ does. A device with
@@ -39,7 +39,7 @@
values to the governor with data field at devfreq_add_device().
config DEVFREQ_GOV_PERFORMANCE
- bool "Performance"
+ tristate "Performance"
help
Sets the frequency at the maximum available frequency.
This governor always returns UINT_MAX as frequency so that
@@ -47,7 +47,7 @@
at any time.
config DEVFREQ_GOV_POWERSAVE
- bool "Powersave"
+ tristate "Powersave"
help
Sets the frequency at the minimum available frequency.
This governor always returns 0 as frequency so that
@@ -55,7 +55,7 @@
at any time.
config DEVFREQ_GOV_USERSPACE
- bool "Userspace"
+ tristate "Userspace"
help
Sets the frequency at the user specified one.
This governor returns the user configured frequency if there
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 70c31d4..89d779c 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -27,21 +27,17 @@
#include <linux/hrtimer.h>
#include "governor.h"
-struct class *devfreq_class;
+static struct class *devfreq_class;
/*
- * devfreq_work periodically monitors every registered device.
- * The minimum polling interval is one jiffy. The polling interval is
- * determined by the minimum polling period among all polling devfreq
- * devices. The resolution of polling interval is one jiffy.
+ * devfreq core provides delayed work based load monitoring helper
+ * functions. Governors can use these or can implement their own
+ * monitoring mechanism.
*/
-static bool polling;
static struct workqueue_struct *devfreq_wq;
-static struct delayed_work devfreq_work;
-/* wait removing if this is to be removed */
-static struct devfreq *wait_remove_device;
-
+/* The list of all device-devfreq governors */
+static LIST_HEAD(devfreq_governor_list);
/* The list of all device-devfreq */
static LIST_HEAD(devfreq_list);
static DEFINE_MUTEX(devfreq_list_lock);
@@ -73,6 +69,79 @@
}
/**
+ * devfreq_get_freq_level() - Lookup freq_table for the frequency
+ * @devfreq: the devfreq instance
+ * @freq: the target frequency
+ */
+static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+{
+ int lev;
+
+ for (lev = 0; lev < devfreq->profile->max_state; lev++)
+ if (freq == devfreq->profile->freq_table[lev])
+ return lev;
+
+ return -EINVAL;
+}
+
+/**
+ * devfreq_update_status() - Update statistics of devfreq behavior
+ * @devfreq: the devfreq instance
+ * @freq: the update target frequency
+ */
+static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
+{
+ int lev, prev_lev;
+ unsigned long cur_time;
+
+ lev = devfreq_get_freq_level(devfreq, freq);
+ if (lev < 0)
+ return lev;
+
+ cur_time = jiffies;
+ devfreq->time_in_state[lev] +=
+ cur_time - devfreq->last_stat_updated;
+ if (freq != devfreq->previous_freq) {
+ prev_lev = devfreq_get_freq_level(devfreq,
+ devfreq->previous_freq);
+ devfreq->trans_table[(prev_lev *
+ devfreq->profile->max_state) + lev]++;
+ devfreq->total_trans++;
+ }
+ devfreq->last_stat_updated = cur_time;
+
+ return 0;
+}
+
+/**
+ * find_devfreq_governor() - find devfreq governor from name
+ * @name: name of the governor
+ *
+ * Search the list of devfreq governors and return the matched
+ * governor's pointer. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq_governor *find_devfreq_governor(const char *name)
+{
+ struct devfreq_governor *tmp_governor;
+
+ if (unlikely(IS_ERR_OR_NULL(name))) {
+ pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+ return ERR_PTR(-EINVAL);
+ }
+ WARN(!mutex_is_locked(&devfreq_list_lock),
+ "devfreq_list_lock must be locked.");
+
+ list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
+ if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+ return tmp_governor;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+/* Load monitoring helper functions for governors use */
+
+/**
* update_devfreq() - Reevaluate the device and configure frequency.
* @devfreq: the devfreq instance.
*
@@ -90,6 +159,9 @@
return -EINVAL;
}
+ if (!devfreq->governor)
+ return -EINVAL;
+
/* Reevaluate the proper frequency */
err = devfreq->governor->get_target_freq(devfreq, &freq);
if (err)
@@ -116,16 +188,173 @@
if (err)
return err;
+ if (devfreq->profile->freq_table)
+ if (devfreq_update_status(devfreq, freq))
+ dev_err(&devfreq->dev,
+ "Couldn't update frequency transition information.\n");
+
devfreq->previous_freq = freq;
return err;
}
+EXPORT_SYMBOL(update_devfreq);
+
+/**
+ * devfreq_monitor() - Periodically poll devfreq objects.
+ * @work: the work struct used to run devfreq_monitor periodically.
+ *
+ */
+static void devfreq_monitor(struct work_struct *work)
+{
+ int err;
+ struct devfreq *devfreq = container_of(work,
+ struct devfreq, work.work);
+
+ mutex_lock(&devfreq->lock);
+ err = update_devfreq(devfreq);
+ if (err)
+ dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
+
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ mutex_unlock(&devfreq->lock);
+}
+
+/**
+ * devfreq_monitor_start() - Start load monitoring of devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function for starting devfreq device load monitoing. By
+ * default delayed work based monitoring is supported. Function
+ * to be called from governor in response to DEVFREQ_GOV_START
+ * event when device is added to devfreq framework.
+ */
+void devfreq_monitor_start(struct devfreq *devfreq)
+{
+ INIT_DELAYED_WORK_DEFERRABLE(&devfreq->work, devfreq_monitor);
+ if (devfreq->profile->polling_ms)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+}
+EXPORT_SYMBOL(devfreq_monitor_start);
+
+/**
+ * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to stop devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_STOP
+ * event when device is removed from devfreq framework.
+ */
+void devfreq_monitor_stop(struct devfreq *devfreq)
+{
+ cancel_delayed_work_sync(&devfreq->work);
+}
+EXPORT_SYMBOL(devfreq_monitor_stop);
+
+/**
+ * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to suspend devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_SUSPEND
+ * event or when polling interval is set to zero.
+ *
+ * Note: Though this function is same as devfreq_monitor_stop(),
+ * intentionally kept separate to provide hooks for collecting
+ * transition statistics.
+ */
+void devfreq_monitor_suspend(struct devfreq *devfreq)
+{
+ mutex_lock(&devfreq->lock);
+ if (devfreq->stop_polling) {
+ mutex_unlock(&devfreq->lock);
+ return;
+ }
+
+ devfreq->stop_polling = true;
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+}
+EXPORT_SYMBOL(devfreq_monitor_suspend);
+
+/**
+ * devfreq_monitor_resume() - Resume load monitoring of a devfreq instance
+ * @devfreq: the devfreq instance.
+ *
+ * Helper function to resume devfreq device load monitoing. Function
+ * to be called from governor in response to DEVFREQ_GOV_RESUME
+ * event or when polling interval is set to non-zero.
+ */
+void devfreq_monitor_resume(struct devfreq *devfreq)
+{
+ mutex_lock(&devfreq->lock);
+ if (!devfreq->stop_polling)
+ goto out;
+
+ if (!delayed_work_pending(&devfreq->work) &&
+ devfreq->profile->polling_ms)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ devfreq->stop_polling = false;
+
+out:
+ mutex_unlock(&devfreq->lock);
+}
+EXPORT_SYMBOL(devfreq_monitor_resume);
+
+/**
+ * devfreq_interval_update() - Update device devfreq monitoring interval
+ * @devfreq: the devfreq instance.
+ * @delay: new polling interval to be set.
+ *
+ * Helper function to set new load monitoring polling interval. Function
+ * to be called from governor in response to DEVFREQ_GOV_INTERVAL event.
+ */
+void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
+{
+ unsigned int cur_delay = devfreq->profile->polling_ms;
+ unsigned int new_delay = *delay;
+
+ mutex_lock(&devfreq->lock);
+ devfreq->profile->polling_ms = new_delay;
+
+ if (devfreq->stop_polling)
+ goto out;
+
+ /* if new delay is zero, stop polling */
+ if (!new_delay) {
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+ return;
+ }
+
+ /* if current delay is zero, start polling with new delay */
+ if (!cur_delay) {
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ goto out;
+ }
+
+ /* if current delay is greater than new delay, restart polling */
+ if (cur_delay > new_delay) {
+ mutex_unlock(&devfreq->lock);
+ cancel_delayed_work_sync(&devfreq->work);
+ mutex_lock(&devfreq->lock);
+ if (!devfreq->stop_polling)
+ queue_delayed_work(devfreq_wq, &devfreq->work,
+ msecs_to_jiffies(devfreq->profile->polling_ms));
+ }
+out:
+ mutex_unlock(&devfreq->lock);
+}
+EXPORT_SYMBOL(devfreq_interval_update);
/**
* devfreq_notifier_call() - Notify that the device frequency requirements
* has been changed out of devfreq framework.
- * @nb the notifier_block (supposed to be devfreq->nb)
- * @type not used
- * @devp not used
+ * @nb: the notifier_block (supposed to be devfreq->nb)
+ * @type: not used
+ * @devp: not used
*
* Called by a notifier that uses devfreq->nb.
*/
@@ -143,59 +372,34 @@
}
/**
- * _remove_devfreq() - Remove devfreq from the device.
+ * _remove_devfreq() - Remove devfreq from the list and release its resources.
* @devfreq: the devfreq struct
* @skip: skip calling device_unregister().
- *
- * Note that the caller should lock devfreq->lock before calling
- * this. _remove_devfreq() will unlock it and free devfreq
- * internally. devfreq_list_lock should be locked by the caller
- * as well (not relased at return)
- *
- * Lock usage:
- * devfreq->lock: locked before call.
- * unlocked at return (and freed)
- * devfreq_list_lock: locked before call.
- * kept locked at return.
- * if devfreq is centrally polled.
- *
- * Freed memory:
- * devfreq
*/
static void _remove_devfreq(struct devfreq *devfreq, bool skip)
{
- if (!mutex_is_locked(&devfreq->lock)) {
- WARN(true, "devfreq->lock must be locked by the caller.\n");
+ mutex_lock(&devfreq_list_lock);
+ if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
+ mutex_unlock(&devfreq_list_lock);
+ dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
return;
}
- if (!devfreq->governor->no_central_polling &&
- !mutex_is_locked(&devfreq_list_lock)) {
- WARN(true, "devfreq_list_lock must be locked by the caller.\n");
- return;
- }
+ list_del(&devfreq->node);
+ mutex_unlock(&devfreq_list_lock);
- if (devfreq->being_removed)
- return;
-
- devfreq->being_removed = true;
+ if (devfreq->governor)
+ devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
if (devfreq->profile->exit)
devfreq->profile->exit(devfreq->dev.parent);
- if (devfreq->governor->exit)
- devfreq->governor->exit(devfreq);
-
if (!skip && get_device(&devfreq->dev)) {
device_unregister(&devfreq->dev);
put_device(&devfreq->dev);
}
- if (!devfreq->governor->no_central_polling)
- list_del(&devfreq->node);
-
- mutex_unlock(&devfreq->lock);
mutex_destroy(&devfreq->lock);
-
kfree(devfreq);
}
@@ -210,163 +414,39 @@
static void devfreq_dev_release(struct device *dev)
{
struct devfreq *devfreq = to_devfreq(dev);
- bool central_polling = !devfreq->governor->no_central_polling;
- /*
- * If devfreq_dev_release() was called by device_unregister() of
- * _remove_devfreq(), we cannot mutex_lock(&devfreq->lock) and
- * being_removed is already set. This also partially checks the case
- * where devfreq_dev_release() is called from a thread other than
- * the one called _remove_devfreq(); however, this case is
- * dealt completely with another following being_removed check.
- *
- * Because being_removed is never being
- * unset, we do not need to worry about race conditions on
- * being_removed.
- */
- if (devfreq->being_removed)
- return;
-
- if (central_polling)
- mutex_lock(&devfreq_list_lock);
-
- mutex_lock(&devfreq->lock);
-
- /*
- * Check being_removed flag again for the case where
- * devfreq_dev_release() was called in a thread other than the one
- * possibly called _remove_devfreq().
- */
- if (devfreq->being_removed) {
- mutex_unlock(&devfreq->lock);
- goto out;
- }
-
- /* devfreq->lock is unlocked and removed in _removed_devfreq() */
_remove_devfreq(devfreq, true);
-
-out:
- if (central_polling)
- mutex_unlock(&devfreq_list_lock);
-}
-
-/**
- * devfreq_monitor() - Periodically poll devfreq objects.
- * @work: the work struct used to run devfreq_monitor periodically.
- *
- */
-static void devfreq_monitor(struct work_struct *work)
-{
- static unsigned long last_polled_at;
- struct devfreq *devfreq, *tmp;
- int error;
- unsigned long jiffies_passed;
- unsigned long next_jiffies = ULONG_MAX, now = jiffies;
- struct device *dev;
-
- /* Initially last_polled_at = 0, polling every device at bootup */
- jiffies_passed = now - last_polled_at;
- last_polled_at = now;
- if (jiffies_passed == 0)
- jiffies_passed = 1;
-
- mutex_lock(&devfreq_list_lock);
- list_for_each_entry_safe(devfreq, tmp, &devfreq_list, node) {
- mutex_lock(&devfreq->lock);
- dev = devfreq->dev.parent;
-
- /* Do not remove tmp for a while */
- wait_remove_device = tmp;
-
- if (devfreq->governor->no_central_polling ||
- devfreq->next_polling == 0) {
- mutex_unlock(&devfreq->lock);
- continue;
- }
- mutex_unlock(&devfreq_list_lock);
-
- /*
- * Reduce more next_polling if devfreq_wq took an extra
- * delay. (i.e., CPU has been idled.)
- */
- if (devfreq->next_polling <= jiffies_passed) {
- error = update_devfreq(devfreq);
-
- /* Remove a devfreq with an error. */
- if (error && error != -EAGAIN) {
-
- dev_err(dev, "Due to update_devfreq error(%d), devfreq(%s) is removed from the device\n",
- error, devfreq->governor->name);
-
- /*
- * Unlock devfreq before locking the list
- * in order to avoid deadlock with
- * find_device_devfreq or others
- */
- mutex_unlock(&devfreq->lock);
- mutex_lock(&devfreq_list_lock);
- /* Check if devfreq is already removed */
- if (IS_ERR(find_device_devfreq(dev)))
- continue;
- mutex_lock(&devfreq->lock);
- /* This unlocks devfreq->lock and free it */
- _remove_devfreq(devfreq, false);
- continue;
- }
- devfreq->next_polling = devfreq->polling_jiffies;
- } else {
- devfreq->next_polling -= jiffies_passed;
- }
-
- if (devfreq->next_polling)
- next_jiffies = (next_jiffies > devfreq->next_polling) ?
- devfreq->next_polling : next_jiffies;
-
- mutex_unlock(&devfreq->lock);
- mutex_lock(&devfreq_list_lock);
- }
- wait_remove_device = NULL;
- mutex_unlock(&devfreq_list_lock);
-
- if (next_jiffies > 0 && next_jiffies < ULONG_MAX) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work, next_jiffies);
- } else {
- polling = false;
- }
}
/**
* devfreq_add_device() - Add devfreq feature to the device
* @dev: the device to add devfreq feature.
* @profile: device-specific profile to run devfreq.
- * @governor: the policy to choose frequency.
+ * @governor_name: name of the policy to choose frequency.
* @data: private data for the governor. The devfreq framework does not
* touch this value.
*/
struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- const struct devfreq_governor *governor,
+ const char *governor_name,
void *data)
{
struct devfreq *devfreq;
+ struct devfreq_governor *governor;
int err = 0;
- if (!dev || !profile || !governor) {
+ if (!dev || !profile || !governor_name) {
dev_err(dev, "%s: Invalid parameters.\n", __func__);
return ERR_PTR(-EINVAL);
}
-
- if (!governor->no_central_polling) {
- mutex_lock(&devfreq_list_lock);
- devfreq = find_device_devfreq(dev);
- mutex_unlock(&devfreq_list_lock);
- if (!IS_ERR(devfreq)) {
- dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
- err = -EINVAL;
- goto err_out;
- }
+ mutex_lock(&devfreq_list_lock);
+ devfreq = find_device_devfreq(dev);
+ mutex_unlock(&devfreq_list_lock);
+ if (!IS_ERR(devfreq)) {
+ dev_err(dev, "%s: Unable to create devfreq for the device. It already has one.\n", __func__);
+ err = -EINVAL;
+ goto err_out;
}
devfreq = kzalloc(sizeof(struct devfreq), GFP_KERNEL);
@@ -383,92 +463,316 @@
devfreq->dev.class = devfreq_class;
devfreq->dev.release = devfreq_dev_release;
devfreq->profile = profile;
- devfreq->governor = governor;
+ strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
devfreq->previous_freq = profile->initial_freq;
devfreq->data = data;
- devfreq->next_polling = devfreq->polling_jiffies
- = msecs_to_jiffies(devfreq->profile->polling_ms);
devfreq->nb.notifier_call = devfreq_notifier_call;
+ devfreq->trans_table = devm_kzalloc(dev, sizeof(unsigned int) *
+ devfreq->profile->max_state *
+ devfreq->profile->max_state,
+ GFP_KERNEL);
+ devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
+ devfreq->profile->max_state,
+ GFP_KERNEL);
+ devfreq->last_stat_updated = jiffies;
+
dev_set_name(&devfreq->dev, dev_name(dev));
err = device_register(&devfreq->dev);
if (err) {
put_device(&devfreq->dev);
+ mutex_unlock(&devfreq->lock);
goto err_dev;
}
- if (governor->init)
- err = governor->init(devfreq);
- if (err)
- goto err_init;
-
mutex_unlock(&devfreq->lock);
- if (governor->no_central_polling)
- goto out;
-
mutex_lock(&devfreq_list_lock);
-
list_add(&devfreq->node, &devfreq_list);
- if (devfreq_wq && devfreq->next_polling && !polling) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work,
- devfreq->next_polling);
- }
+ governor = find_devfreq_governor(devfreq->governor_name);
+ if (!IS_ERR(governor))
+ devfreq->governor = governor;
+ if (devfreq->governor)
+ err = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_START, NULL);
mutex_unlock(&devfreq_list_lock);
-out:
+ if (err) {
+ dev_err(dev, "%s: Unable to start governor for the device\n",
+ __func__);
+ goto err_init;
+ }
+
return devfreq;
err_init:
+ list_del(&devfreq->node);
device_unregister(&devfreq->dev);
err_dev:
- mutex_unlock(&devfreq->lock);
kfree(devfreq);
err_out:
return ERR_PTR(err);
}
+EXPORT_SYMBOL(devfreq_add_device);
/**
* devfreq_remove_device() - Remove devfreq feature from a device.
- * @devfreq the devfreq instance to be removed
+ * @devfreq: the devfreq instance to be removed
*/
int devfreq_remove_device(struct devfreq *devfreq)
{
- bool central_polling;
-
if (!devfreq)
return -EINVAL;
- central_polling = !devfreq->governor->no_central_polling;
-
- if (central_polling) {
- mutex_lock(&devfreq_list_lock);
- while (wait_remove_device == devfreq) {
- mutex_unlock(&devfreq_list_lock);
- schedule();
- mutex_lock(&devfreq_list_lock);
- }
- }
-
- mutex_lock(&devfreq->lock);
- _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
-
- if (central_polling)
- mutex_unlock(&devfreq_list_lock);
+ _remove_devfreq(devfreq, false);
return 0;
}
+EXPORT_SYMBOL(devfreq_remove_device);
+
+/**
+ * devfreq_suspend_device() - Suspend devfreq of a device.
+ * @devfreq: the devfreq instance to be suspended
+ */
+int devfreq_suspend_device(struct devfreq *devfreq)
+{
+ if (!devfreq)
+ return -EINVAL;
+
+ if (!devfreq->governor)
+ return 0;
+
+ return devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_SUSPEND, NULL);
+}
+EXPORT_SYMBOL(devfreq_suspend_device);
+
+/**
+ * devfreq_resume_device() - Resume devfreq of a device.
+ * @devfreq: the devfreq instance to be resumed
+ */
+int devfreq_resume_device(struct devfreq *devfreq)
+{
+ if (!devfreq)
+ return -EINVAL;
+
+ if (!devfreq->governor)
+ return 0;
+
+ return devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_RESUME, NULL);
+}
+EXPORT_SYMBOL(devfreq_resume_device);
+
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor: the devfreq governor to be added
+ */
+int devfreq_add_governor(struct devfreq_governor *governor)
+{
+ struct devfreq_governor *g;
+ struct devfreq *devfreq;
+ int err = 0;
+
+ if (!governor) {
+ pr_err("%s: Invalid parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&devfreq_list_lock);
+ g = find_devfreq_governor(governor->name);
+ if (!IS_ERR(g)) {
+ pr_err("%s: governor %s already registered\n", __func__,
+ g->name);
+ err = -EINVAL;
+ goto err_out;
+ }
+
+ list_add(&governor->node, &devfreq_governor_list);
+
+ list_for_each_entry(devfreq, &devfreq_list, node) {
+ int ret = 0;
+ struct device *dev = devfreq->dev.parent;
+
+ if (!strncmp(devfreq->governor_name, governor->name,
+ DEVFREQ_NAME_LEN)) {
+ /* The following should never occur */
+ if (devfreq->governor) {
+ dev_warn(dev,
+ "%s: Governor %s already present\n",
+ __func__, devfreq->governor->name);
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev,
+ "%s: Governor %s stop = %d\n",
+ __func__,
+ devfreq->governor->name, ret);
+ }
+ /* Fall through */
+ }
+ devfreq->governor = governor;
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_START, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s start=%d\n",
+ __func__, devfreq->governor->name,
+ ret);
+ }
+ }
+ }
+
+err_out:
+ mutex_unlock(&devfreq_list_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(devfreq_add_governor);
+
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @governor: the devfreq governor to be removed
+ */
+int devfreq_remove_governor(struct devfreq_governor *governor)
+{
+ struct devfreq_governor *g;
+ struct devfreq *devfreq;
+ int err = 0;
+
+ if (!governor) {
+ pr_err("%s: Invalid parameters.\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&devfreq_list_lock);
+ g = find_devfreq_governor(governor->name);
+ if (IS_ERR(g)) {
+ pr_err("%s: governor %s not registered\n", __func__,
+ governor->name);
+ err = PTR_ERR(g);
+ goto err_out;
+ }
+ list_for_each_entry(devfreq, &devfreq_list, node) {
+ int ret;
+ struct device *dev = devfreq->dev.parent;
+
+ if (!strncmp(devfreq->governor_name, governor->name,
+ DEVFREQ_NAME_LEN)) {
+ /* we should have a devfreq governor! */
+ if (!devfreq->governor) {
+ dev_warn(dev, "%s: Governor %s NOT present\n",
+ __func__, governor->name);
+ continue;
+ /* Fall through */
+ }
+ ret = devfreq->governor->event_handler(devfreq,
+ DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s stop=%d\n",
+ __func__, devfreq->governor->name,
+ ret);
+ }
+ devfreq->governor = NULL;
+ }
+ }
+
+ list_del(&governor->node);
+err_out:
+ mutex_unlock(&devfreq_list_lock);
+
+ return err;
+}
+EXPORT_SYMBOL(devfreq_remove_governor);
static ssize_t show_governor(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ if (!to_devfreq(dev)->governor)
+ return -EINVAL;
+
return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
}
+static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct devfreq *df = to_devfreq(dev);
+ int ret;
+ char str_governor[DEVFREQ_NAME_LEN + 1];
+ struct devfreq_governor *governor;
+
+ ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
+ if (ret != 1)
+ return -EINVAL;
+
+ mutex_lock(&devfreq_list_lock);
+ governor = find_devfreq_governor(str_governor);
+ if (IS_ERR(governor)) {
+ ret = PTR_ERR(governor);
+ goto out;
+ }
+ if (df->governor == governor)
+ goto out;
+
+ if (df->governor) {
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+ if (ret) {
+ dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+ __func__, df->governor->name, ret);
+ goto out;
+ }
+ }
+ df->governor = governor;
+ strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
+ ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+ if (ret)
+ dev_warn(dev, "%s: Governor %s not started(%d)\n",
+ __func__, df->governor->name, ret);
+out:
+ mutex_unlock(&devfreq_list_lock);
+
+ if (!ret)
+ ret = count;
+ return ret;
+}
+static ssize_t show_available_governors(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq_governor *tmp_governor;
+ ssize_t count = 0;
+
+ mutex_lock(&devfreq_list_lock);
+ list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
+ count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+ "%s ", tmp_governor->name);
+ mutex_unlock(&devfreq_list_lock);
+
+ /* Truncate the trailing space */
+ if (count)
+ count--;
+
+ count += sprintf(&buf[count], "\n");
+
+ return count;
+}
+
static ssize_t show_freq(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ unsigned long freq;
+ struct devfreq *devfreq = to_devfreq(dev);
+
+ if (devfreq->profile->get_cur_freq &&
+ !devfreq->profile->get_cur_freq(devfreq->dev.parent, &freq))
+ return sprintf(buf, "%lu\n", freq);
+
+ return sprintf(buf, "%lu\n", devfreq->previous_freq);
+}
+
+static ssize_t show_target_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
return sprintf(buf, "%lu\n", to_devfreq(dev)->previous_freq);
}
@@ -486,39 +790,19 @@
unsigned int value;
int ret;
+ if (!df->governor)
+ return -EINVAL;
+
ret = sscanf(buf, "%u", &value);
if (ret != 1)
- goto out;
+ return -EINVAL;
- mutex_lock(&df->lock);
- df->profile->polling_ms = value;
- df->next_polling = df->polling_jiffies
- = msecs_to_jiffies(value);
- mutex_unlock(&df->lock);
-
+ df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
ret = count;
- if (df->governor->no_central_polling)
- goto out;
-
- mutex_lock(&devfreq_list_lock);
- if (df->next_polling > 0 && !polling) {
- polling = true;
- queue_delayed_work(devfreq_wq, &devfreq_work,
- df->next_polling);
- }
- mutex_unlock(&devfreq_list_lock);
-out:
return ret;
}
-static ssize_t show_central_polling(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n",
- !to_devfreq(dev)->governor->no_central_polling);
-}
-
static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -529,7 +813,7 @@
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
- goto out;
+ return -EINVAL;
mutex_lock(&df->lock);
max = df->max_freq;
@@ -543,7 +827,6 @@
ret = count;
unlock:
mutex_unlock(&df->lock);
-out:
return ret;
}
@@ -563,7 +846,7 @@
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
- goto out;
+ return -EINVAL;
mutex_lock(&df->lock);
min = df->min_freq;
@@ -577,7 +860,6 @@
ret = count;
unlock:
mutex_unlock(&df->lock);
-out:
return ret;
}
@@ -587,34 +869,92 @@
return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
}
+static ssize_t show_available_freqs(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *df = to_devfreq(d);
+ struct device *dev = df->dev.parent;
+ struct opp *opp;
+ ssize_t count = 0;
+ unsigned long freq = 0;
+
+ rcu_read_lock();
+ do {
+ opp = opp_find_freq_ceil(dev, &freq);
+ if (IS_ERR(opp))
+ break;
+
+ count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+ "%lu ", freq);
+ freq++;
+ } while (1);
+ rcu_read_unlock();
+
+ /* Truncate the trailing space */
+ if (count)
+ count--;
+
+ count += sprintf(&buf[count], "\n");
+
+ return count;
+}
+
+static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct devfreq *devfreq = to_devfreq(dev);
+ ssize_t len;
+ int i, j, err;
+ unsigned int max_state = devfreq->profile->max_state;
+
+ err = devfreq_update_status(devfreq, devfreq->previous_freq);
+ if (err)
+ return 0;
+
+ len = sprintf(buf, " From : To\n");
+ len += sprintf(buf + len, " :");
+ for (i = 0; i < max_state; i++)
+ len += sprintf(buf + len, "%8u",
+ devfreq->profile->freq_table[i]);
+
+ len += sprintf(buf + len, " time(ms)\n");
+
+ for (i = 0; i < max_state; i++) {
+ if (devfreq->profile->freq_table[i]
+ == devfreq->previous_freq) {
+ len += sprintf(buf + len, "*");
+ } else {
+ len += sprintf(buf + len, " ");
+ }
+ len += sprintf(buf + len, "%8u:",
+ devfreq->profile->freq_table[i]);
+ for (j = 0; j < max_state; j++)
+ len += sprintf(buf + len, "%8u",
+ devfreq->trans_table[(i * max_state) + j]);
+ len += sprintf(buf + len, "%10u\n",
+ jiffies_to_msecs(devfreq->time_in_state[i]));
+ }
+
+ len += sprintf(buf + len, "Total transition : %u\n",
+ devfreq->total_trans);
+ return len;
+}
+
static struct device_attribute devfreq_attrs[] = {
- __ATTR(governor, S_IRUGO, show_governor, NULL),
+ __ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
+ __ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
- __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+ __ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
+ __ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
store_polling_interval),
__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
+ __ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
{ },
};
-/**
- * devfreq_start_polling() - Initialize data structure for devfreq framework and
- * start polling registered devfreq devices.
- */
-static int __init devfreq_start_polling(void)
-{
- mutex_lock(&devfreq_list_lock);
- polling = false;
- devfreq_wq = create_freezable_workqueue("devfreq_wq");
- INIT_DELAYED_WORK_DEFERRABLE(&devfreq_work, devfreq_monitor);
- mutex_unlock(&devfreq_list_lock);
-
- devfreq_monitor(&devfreq_work.work);
- return 0;
-}
-late_initcall(devfreq_start_polling);
-
static int __init devfreq_init(void)
{
devfreq_class = class_create(THIS_MODULE, "devfreq");
@@ -622,7 +962,15 @@
pr_err("%s: couldn't create class\n", __FILE__);
return PTR_ERR(devfreq_class);
}
+
+ devfreq_wq = create_freezable_workqueue("devfreq_wq");
+ if (IS_ERR(devfreq_wq)) {
+ class_destroy(devfreq_class);
+ pr_err("%s: couldn't create workqueue\n", __FILE__);
+ return PTR_ERR(devfreq_wq);
+ }
devfreq_class->dev_attrs = devfreq_attrs;
+
return 0;
}
subsys_initcall(devfreq_init);
@@ -630,6 +978,7 @@
static void __exit devfreq_exit(void)
{
class_destroy(devfreq_class);
+ destroy_workqueue(devfreq_wq);
}
module_exit(devfreq_exit);
@@ -641,10 +990,15 @@
/**
* devfreq_recommended_opp() - Helper function to get proper OPP for the
* freq value given to target callback.
- * @dev The devfreq user device. (parent of devfreq)
- * @freq The frequency given to target function
- * @flags Flags handed from devfreq framework.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @freq: The frequency given to target function
+ * @flags: Flags handed from devfreq framework.
*
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
*/
struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
u32 flags)
@@ -656,14 +1010,14 @@
opp = opp_find_freq_floor(dev, freq);
/* If not available, use the closest opp */
- if (opp == ERR_PTR(-ENODEV))
+ if (opp == ERR_PTR(-ERANGE))
opp = opp_find_freq_ceil(dev, freq);
} else {
/* The freq is an lower bound. opp should be higher */
opp = opp_find_freq_ceil(dev, freq);
/* If not available, use the closest opp */
- if (opp == ERR_PTR(-ENODEV))
+ if (opp == ERR_PTR(-ERANGE))
opp = opp_find_freq_floor(dev, freq);
}
@@ -674,35 +1028,49 @@
* devfreq_register_opp_notifier() - Helper function to get devfreq notified
* for any changes in the OPP availability
* changes
- * @dev The devfreq user device. (parent of devfreq)
- * @devfreq The devfreq object.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @devfreq: The devfreq object.
*/
int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
{
- struct srcu_notifier_head *nh = opp_get_notifier(dev);
+ struct srcu_notifier_head *nh;
+ int ret = 0;
+ rcu_read_lock();
+ nh = opp_get_notifier(dev);
if (IS_ERR(nh))
- return PTR_ERR(nh);
- return srcu_notifier_chain_register(nh, &devfreq->nb);
+ ret = PTR_ERR(nh);
+ rcu_read_unlock();
+ if (!ret)
+ ret = srcu_notifier_chain_register(nh, &devfreq->nb);
+
+ return ret;
}
/**
* devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq
* notified for any changes in the OPP
* availability changes anymore.
- * @dev The devfreq user device. (parent of devfreq)
- * @devfreq The devfreq object.
+ * @dev: The devfreq user device. (parent of devfreq)
+ * @devfreq: The devfreq object.
*
* At exit() callback of devfreq_dev_profile, this must be included if
* devfreq_recommended_opp is used.
*/
int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
{
- struct srcu_notifier_head *nh = opp_get_notifier(dev);
+ struct srcu_notifier_head *nh;
+ int ret = 0;
+ rcu_read_lock();
+ nh = opp_get_notifier(dev);
if (IS_ERR(nh))
- return PTR_ERR(nh);
- return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+ ret = PTR_ERR(nh);
+ rcu_read_unlock();
+ if (!ret)
+ ret = srcu_notifier_chain_unregister(nh, &devfreq->nb);
+
+ return ret;
}
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 88ddc77..f6c54bd 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -73,6 +73,16 @@
#define EX4210_LV_NUM (LV_2 + 1)
#define EX4x12_LV_NUM (LV_4 + 1)
+/**
+ * struct busfreq_opp_info - opp information for bus
+ * @rate: Frequency in hertz
+ * @volt: Voltage in microvolts corresponding to this OPP
+ */
+struct busfreq_opp_info {
+ unsigned long rate;
+ unsigned long volt;
+};
+
struct busfreq_data {
enum exynos4_busf_type type;
struct device *dev;
@@ -80,7 +90,7 @@
bool disabled;
struct regulator *vdd_int;
struct regulator *vdd_mif; /* Exynos4412/4212 only */
- struct opp *curr_opp;
+ struct busfreq_opp_info curr_oppinfo;
struct exynos4_ppmu dmc[2];
struct notifier_block pm_notifier;
@@ -296,13 +306,14 @@
};
-static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4210_set_busclk(struct busfreq_data *data,
+ struct busfreq_opp_info *oppi)
{
unsigned int index;
unsigned int tmp;
for (index = LV_0; index < EX4210_LV_NUM; index++)
- if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk)
+ if (oppi->rate == exynos4210_busclk_table[index].clk)
break;
if (index == EX4210_LV_NUM)
@@ -361,13 +372,14 @@
return 0;
}
-static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4x12_set_busclk(struct busfreq_data *data,
+ struct busfreq_opp_info *oppi)
{
unsigned int index;
unsigned int tmp;
for (index = LV_0; index < EX4x12_LV_NUM; index++)
- if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk)
+ if (oppi->rate == exynos4x12_mifclk_table[index].clk)
break;
if (index == EX4x12_LV_NUM)
@@ -576,11 +588,12 @@
return -EINVAL;
}
-static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
- struct opp *oldopp)
+static int exynos4_bus_setvolt(struct busfreq_data *data,
+ struct busfreq_opp_info *oppi,
+ struct busfreq_opp_info *oldoppi)
{
int err = 0, tmp;
- unsigned long volt = opp_get_voltage(opp);
+ unsigned long volt = oppi->volt;
switch (data->type) {
case TYPE_BUSF_EXYNOS4210:
@@ -595,11 +608,11 @@
if (err)
break;
- tmp = exynos4x12_get_intspec(opp_get_freq(opp));
+ tmp = exynos4x12_get_intspec(oppi->rate);
if (tmp < 0) {
err = tmp;
regulator_set_voltage(data->vdd_mif,
- opp_get_voltage(oldopp),
+ oldoppi->volt,
MAX_SAFEVOLT);
break;
}
@@ -609,7 +622,7 @@
/* Try to recover */
if (err)
regulator_set_voltage(data->vdd_mif,
- opp_get_voltage(oldopp),
+ oldoppi->volt,
MAX_SAFEVOLT);
break;
default:
@@ -626,17 +639,26 @@
struct platform_device *pdev = container_of(dev, struct platform_device,
dev);
struct busfreq_data *data = platform_get_drvdata(pdev);
- struct opp *opp = devfreq_recommended_opp(dev, _freq, flags);
- unsigned long freq = opp_get_freq(opp);
- unsigned long old_freq = opp_get_freq(data->curr_opp);
+ struct opp *opp;
+ unsigned long freq;
+ unsigned long old_freq = data->curr_oppinfo.rate;
+ struct busfreq_opp_info new_oppinfo;
- if (IS_ERR(opp))
+ rcu_read_lock();
+ opp = devfreq_recommended_opp(dev, _freq, flags);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
return PTR_ERR(opp);
+ }
+ new_oppinfo.rate = opp_get_freq(opp);
+ new_oppinfo.volt = opp_get_voltage(opp);
+ rcu_read_unlock();
+ freq = new_oppinfo.rate;
if (old_freq == freq)
return 0;
- dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp));
+ dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt);
mutex_lock(&data->lock);
@@ -644,17 +666,18 @@
goto out;
if (old_freq < freq)
- err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+ err = exynos4_bus_setvolt(data, &new_oppinfo,
+ &data->curr_oppinfo);
if (err)
goto out;
if (old_freq != freq) {
switch (data->type) {
case TYPE_BUSF_EXYNOS4210:
- err = exynos4210_set_busclk(data, opp);
+ err = exynos4210_set_busclk(data, &new_oppinfo);
break;
case TYPE_BUSF_EXYNOS4x12:
- err = exynos4x12_set_busclk(data, opp);
+ err = exynos4x12_set_busclk(data, &new_oppinfo);
break;
default:
err = -EINVAL;
@@ -664,11 +687,12 @@
goto out;
if (old_freq > freq)
- err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+ err = exynos4_bus_setvolt(data, &new_oppinfo,
+ &data->curr_oppinfo);
if (err)
goto out;
- data->curr_opp = opp;
+ data->curr_oppinfo = new_oppinfo;
out:
mutex_unlock(&data->lock);
return err;
@@ -702,7 +726,7 @@
exynos4_read_ppmu(data);
busier_dmc = exynos4_get_busier_dmc(data);
- stat->current_frequency = opp_get_freq(data->curr_opp);
+ stat->current_frequency = data->curr_oppinfo.rate;
if (busier_dmc)
addr = S5P_VA_DMC1;
@@ -933,6 +957,7 @@
struct busfreq_data *data = container_of(this, struct busfreq_data,
pm_notifier);
struct opp *opp;
+ struct busfreq_opp_info new_oppinfo;
unsigned long maxfreq = ULONG_MAX;
int err = 0;
@@ -943,18 +968,29 @@
data->disabled = true;
+ rcu_read_lock();
opp = opp_find_freq_floor(data->dev, &maxfreq);
+ if (IS_ERR(opp)) {
+ rcu_read_unlock();
+ dev_err(data->dev, "%s: unable to find a min freq\n",
+ __func__);
+ return PTR_ERR(opp);
+ }
+ new_oppinfo.rate = opp_get_freq(opp);
+ new_oppinfo.volt = opp_get_voltage(opp);
+ rcu_read_unlock();
- err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+ err = exynos4_bus_setvolt(data, &new_oppinfo,
+ &data->curr_oppinfo);
if (err)
goto unlock;
switch (data->type) {
case TYPE_BUSF_EXYNOS4210:
- err = exynos4210_set_busclk(data, opp);
+ err = exynos4210_set_busclk(data, &new_oppinfo);
break;
case TYPE_BUSF_EXYNOS4x12:
- err = exynos4x12_set_busclk(data, opp);
+ err = exynos4x12_set_busclk(data, &new_oppinfo);
break;
default:
err = -EINVAL;
@@ -962,7 +998,7 @@
if (err)
goto unlock;
- data->curr_opp = opp;
+ data->curr_oppinfo = new_oppinfo;
unlock:
mutex_unlock(&data->lock);
if (err)
@@ -987,7 +1023,7 @@
struct device *dev = &pdev->dev;
int err = 0;
- data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
if (data == NULL) {
dev_err(dev, "Cannot allocate memory.\n");
return -ENOMEM;
@@ -1012,63 +1048,52 @@
err = -EINVAL;
}
if (err)
- goto err_regulator;
+ return err;
- data->vdd_int = regulator_get(dev, "vdd_int");
+ data->vdd_int = devm_regulator_get(dev, "vdd_int");
if (IS_ERR(data->vdd_int)) {
dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
- err = PTR_ERR(data->vdd_int);
- goto err_regulator;
+ return PTR_ERR(data->vdd_int);
}
if (data->type == TYPE_BUSF_EXYNOS4x12) {
- data->vdd_mif = regulator_get(dev, "vdd_mif");
+ data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
if (IS_ERR(data->vdd_mif)) {
dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
- err = PTR_ERR(data->vdd_mif);
- regulator_put(data->vdd_int);
- goto err_regulator;
-
+ return PTR_ERR(data->vdd_mif);
}
}
+ rcu_read_lock();
opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
if (IS_ERR(opp)) {
+ rcu_read_unlock();
dev_err(dev, "Invalid initial frequency %lu kHz.\n",
- exynos4_devfreq_profile.initial_freq);
- err = PTR_ERR(opp);
- goto err_opp_add;
+ exynos4_devfreq_profile.initial_freq);
+ return PTR_ERR(opp);
}
- data->curr_opp = opp;
+ data->curr_oppinfo.rate = opp_get_freq(opp);
+ data->curr_oppinfo.volt = opp_get_voltage(opp);
+ rcu_read_unlock();
platform_set_drvdata(pdev, data);
busfreq_mon_reset(data);
data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
- &devfreq_simple_ondemand, NULL);
- if (IS_ERR(data->devfreq)) {
- err = PTR_ERR(data->devfreq);
- goto err_opp_add;
- }
+ "simple_ondemand", NULL);
+ if (IS_ERR(data->devfreq))
+ return PTR_ERR(data->devfreq);
devfreq_register_opp_notifier(dev, data->devfreq);
err = register_pm_notifier(&data->pm_notifier);
if (err) {
dev_err(dev, "Failed to setup pm notifier\n");
- goto err_devfreq_add;
+ devfreq_remove_device(data->devfreq);
+ return err;
}
return 0;
-err_devfreq_add:
- devfreq_remove_device(data->devfreq);
-err_opp_add:
- if (data->vdd_mif)
- regulator_put(data->vdd_mif);
- regulator_put(data->vdd_int);
-err_regulator:
- kfree(data);
- return err;
}
static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
@@ -1077,10 +1102,6 @@
unregister_pm_notifier(&data->pm_notifier);
devfreq_remove_device(data->devfreq);
- regulator_put(data->vdd_int);
- if (data->vdd_mif)
- regulator_put(data->vdd_mif);
- kfree(data);
return 0;
}
diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
index ea7f13c..fad7d63 100644
--- a/drivers/devfreq/governor.h
+++ b/drivers/devfreq/governor.h
@@ -18,7 +18,24 @@
#define to_devfreq(DEV) container_of((DEV), struct devfreq, dev)
+/* Devfreq events */
+#define DEVFREQ_GOV_START 0x1
+#define DEVFREQ_GOV_STOP 0x2
+#define DEVFREQ_GOV_INTERVAL 0x3
+#define DEVFREQ_GOV_SUSPEND 0x4
+#define DEVFREQ_GOV_RESUME 0x5
+
/* Caution: devfreq->lock must be locked before calling update_devfreq */
extern int update_devfreq(struct devfreq *devfreq);
+extern void devfreq_monitor_start(struct devfreq *devfreq);
+extern void devfreq_monitor_stop(struct devfreq *devfreq);
+extern void devfreq_monitor_suspend(struct devfreq *devfreq);
+extern void devfreq_monitor_resume(struct devfreq *devfreq);
+extern void devfreq_interval_update(struct devfreq *devfreq,
+ unsigned int *delay);
+
+extern int devfreq_add_governor(struct devfreq_governor *governor);
+extern int devfreq_remove_governor(struct devfreq_governor *governor);
+
#endif /* _GOVERNOR_H */
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index af75ddd..c72f942 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include <linux/module.h>
#include "governor.h"
static int devfreq_performance_func(struct devfreq *df,
@@ -26,14 +27,41 @@
return 0;
}
-static int performance_init(struct devfreq *devfreq)
+static int devfreq_performance_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
{
- return update_devfreq(devfreq);
+ int ret = 0;
+
+ if (event == DEVFREQ_GOV_START) {
+ mutex_lock(&devfreq->lock);
+ ret = update_devfreq(devfreq);
+ mutex_unlock(&devfreq->lock);
+ }
+
+ return ret;
}
-const struct devfreq_governor devfreq_performance = {
+static struct devfreq_governor devfreq_performance = {
.name = "performance",
- .init = performance_init,
.get_target_freq = devfreq_performance_func,
- .no_central_polling = true,
+ .event_handler = devfreq_performance_handler,
};
+
+static int __init devfreq_performance_init(void)
+{
+ return devfreq_add_governor(&devfreq_performance);
+}
+subsys_initcall(devfreq_performance_init);
+
+static void __exit devfreq_performance_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_performance);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_performance_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c
index fec0cdb..0c6bed5 100644
--- a/drivers/devfreq/governor_powersave.c
+++ b/drivers/devfreq/governor_powersave.c
@@ -10,6 +10,7 @@
*/
#include <linux/devfreq.h>
+#include <linux/module.h>
#include "governor.h"
static int devfreq_powersave_func(struct devfreq *df,
@@ -23,14 +24,41 @@
return 0;
}
-static int powersave_init(struct devfreq *devfreq)
+static int devfreq_powersave_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
{
- return update_devfreq(devfreq);
+ int ret = 0;
+
+ if (event == DEVFREQ_GOV_START) {
+ mutex_lock(&devfreq->lock);
+ ret = update_devfreq(devfreq);
+ mutex_unlock(&devfreq->lock);
+ }
+
+ return ret;
}
-const struct devfreq_governor devfreq_powersave = {
+static struct devfreq_governor devfreq_powersave = {
.name = "powersave",
- .init = powersave_init,
.get_target_freq = devfreq_powersave_func,
- .no_central_polling = true,
+ .event_handler = devfreq_powersave_handler,
};
+
+static int __init devfreq_powersave_init(void)
+{
+ return devfreq_add_governor(&devfreq_powersave);
+}
+subsys_initcall(devfreq_powersave_init);
+
+static void __exit devfreq_powersave_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_powersave);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_powersave_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index a2e3eae..0720ba8 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -10,8 +10,10 @@
*/
#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/devfreq.h>
#include <linux/math64.h>
+#include "governor.h"
/* Default constants for DevFreq-Simple-Ondemand (DFSO) */
#define DFSO_UPTHRESHOLD (90)
@@ -88,7 +90,58 @@
return 0;
}
-const struct devfreq_governor devfreq_simple_ondemand = {
+static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
+{
+ switch (event) {
+ case DEVFREQ_GOV_START:
+ devfreq_monitor_start(devfreq);
+ break;
+
+ case DEVFREQ_GOV_STOP:
+ devfreq_monitor_stop(devfreq);
+ break;
+
+ case DEVFREQ_GOV_INTERVAL:
+ devfreq_interval_update(devfreq, (unsigned int *)data);
+ break;
+
+ case DEVFREQ_GOV_SUSPEND:
+ devfreq_monitor_suspend(devfreq);
+ break;
+
+ case DEVFREQ_GOV_RESUME:
+ devfreq_monitor_resume(devfreq);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct devfreq_governor devfreq_simple_ondemand = {
.name = "simple_ondemand",
.get_target_freq = devfreq_simple_ondemand_func,
+ .event_handler = devfreq_simple_ondemand_handler,
};
+
+static int __init devfreq_simple_ondemand_init(void)
+{
+ return devfreq_add_governor(&devfreq_simple_ondemand);
+}
+subsys_initcall(devfreq_simple_ondemand_init);
+
+static void __exit devfreq_simple_ondemand_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_simple_ondemand);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_simple_ondemand_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index 0681246..35de6e8 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -14,6 +14,7 @@
#include <linux/devfreq.h>
#include <linux/pm.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include "governor.h"
struct userspace_data {
@@ -116,10 +117,46 @@
devfreq->data = NULL;
}
-const struct devfreq_governor devfreq_userspace = {
+static int devfreq_userspace_handler(struct devfreq *devfreq,
+ unsigned int event, void *data)
+{
+ int ret = 0;
+
+ switch (event) {
+ case DEVFREQ_GOV_START:
+ ret = userspace_init(devfreq);
+ break;
+ case DEVFREQ_GOV_STOP:
+ userspace_exit(devfreq);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static struct devfreq_governor devfreq_userspace = {
.name = "userspace",
.get_target_freq = devfreq_userspace_func,
- .init = userspace_init,
- .exit = userspace_exit,
- .no_central_polling = true,
+ .event_handler = devfreq_userspace_handler,
};
+
+static int __init devfreq_userspace_init(void)
+{
+ return devfreq_add_governor(&devfreq_userspace);
+}
+subsys_initcall(devfreq_userspace_init);
+
+static void __exit devfreq_userspace_exit(void)
+{
+ int ret;
+
+ ret = devfreq_remove_governor(&devfreq_userspace);
+ if (ret)
+ pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+ return;
+}
+module_exit(devfreq_userspace_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index f0c12f9..64341e9 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -821,7 +821,7 @@
param.invert = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
Q_REG_OUT_INVERT_SHIFT,
Q_REG_OUT_INVERT_MASK);
- param.pull = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ param.pull = q_reg_get(&q_spec->regs[Q_REG_I_DIG_PULL_CTL],
Q_REG_PULL_SHIFT, Q_REG_PULL_MASK);
param.vin_sel = q_reg_get(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
Q_REG_VIN_SHIFT, Q_REG_VIN_MASK);
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 9ab2343..9128177 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1248,14 +1248,12 @@
mutex_lock(&buffer->lock);
/* now map it to userspace */
ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
+ mutex_unlock(&buffer->lock);
if (ret) {
- mutex_unlock(&buffer->lock);
pr_err("%s: failure mapping buffer to userspace\n",
__func__);
} else {
- mutex_unlock(&buffer->lock);
-
vma->vm_ops = &ion_vm_ops;
/*
* move the buffer into the vm_private_data so we can access it
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index b51fa6a..798c027 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -241,25 +241,78 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
struct ion_carveout_heap *carveout_heap =
container_of(heap, struct ion_carveout_heap, heap);
+ unsigned int size_to_vmap, total_size;
+ int i, j;
+ void *ptr = NULL;
+ ion_phys_addr_t buff_phys = buffer->priv_phys;
- switch (cmd) {
- case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
- outer_cache_op = outer_clean_range;
- break;
- case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
- outer_cache_op = outer_inv_range;
- break;
- case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
- outer_cache_op = outer_flush_range;
- break;
- default:
- return -EINVAL;
+ if (!vaddr) {
+ /*
+ * Split the vmalloc space into smaller regions in
+ * order to clean and/or invalidate the cache.
+ */
+ size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8);
+ total_size = buffer->size;
+
+ for (i = 0; i < total_size; i += size_to_vmap) {
+ size_to_vmap = min(size_to_vmap, total_size - i);
+ for (j = 0; j < 10 && size_to_vmap; ++j) {
+ ptr = ioremap(buff_phys, size_to_vmap);
+ if (ptr) {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
+ buff_phys += size_to_vmap;
+ break;
+ } else {
+ size_to_vmap >>= 1;
+ }
+ }
+ if (!ptr) {
+ pr_err("Couldn't io-remap the memory\n");
+ return -EINVAL;
+ }
+ iounmap(ptr);
+ }
+ } else {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
}
if (carveout_heap->has_outer_cache) {
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 8063138..4f12e38 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -127,8 +127,8 @@
struct device *dev = heap->priv;
struct ion_cma_buffer_info *info = buffer->priv_virt;
- dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer,
- info->handle);
+ dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer,
+ &info->handle);
*addr = info->handle;
*len = buffer->size;
@@ -281,15 +281,30 @@
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ else
+ dmac_clean_range(vaddr, vaddr + length);
outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ else
+ dmac_inv_range(vaddr, vaddr + length);
outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
+ if (!vaddr) {
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ } else {
+ dmac_flush_range(vaddr, vaddr + length);
+ }
outer_cache_op = outer_flush_range;
break;
default:
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 496e5b4..d7a5920 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -73,6 +73,8 @@
{
struct device *dev = heap->priv;
struct ion_secure_cma_buffer_info *info;
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs);
dev_dbg(dev, "Request buffer allocation len %ld\n", len);
@@ -82,12 +84,7 @@
return ION_CMA_ALLOCATE_FAILED;
}
- if (!ION_IS_CACHED(flags))
- info->cpu_addr = dma_alloc_writecombine(dev, len,
- &(info->handle), 0);
- else
- info->cpu_addr = dma_alloc_nonconsistent(dev, len,
- &(info->handle), 0);
+ info->cpu_addr = dma_alloc_attrs(dev, len, &(info->handle), 0, &attrs);
if (!info->cpu_addr) {
dev_err(dev, "Fail to allocate buffer\n");
@@ -100,8 +97,6 @@
goto err;
}
- info->is_cached = ION_IS_CACHED(flags);
-
ion_secure_cma_get_sgtable(dev,
info->table, info->cpu_addr, info->handle, len);
@@ -131,6 +126,13 @@
return -ENOMEM;
}
+ if (ION_IS_CACHED(flags)) {
+ pr_err("%s: cannot allocate cached memory from secure heap %s\n",
+ __func__, heap->name);
+ return -ENOMEM;
+ }
+
+
buf = __ion_secure_cma_allocate(heap, buffer, len, align, flags);
if (buf) {
@@ -164,8 +166,8 @@
struct device *dev = heap->priv;
struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
- dev_dbg(dev, "Return buffer %p physical address 0x%x\n", buffer,
- info->handle);
+ dev_dbg(dev, "Return buffer %p physical address 0x%pa\n", buffer,
+ &info->handle);
*addr = info->handle;
*len = buffer->size;
@@ -191,24 +193,22 @@
struct ion_buffer *buffer,
struct vm_area_struct *vma)
{
+ pr_info("%s: mmaping from secure heap %s disallowed\n",
+ __func__, mapper->name);
return -EINVAL;
}
static void *ion_secure_cma_map_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
-
- atomic_inc(&info->secure.map_cnt);
- return info->cpu_addr;
+ pr_info("%s: kernel mapping from secure heap %s disallowed\n",
+ __func__, heap->name);
+ return NULL;
}
static void ion_secure_cma_unmap_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
-
- atomic_dec(&info->secure.map_cnt);
return;
}
@@ -311,32 +311,9 @@
unsigned int offset, unsigned int length,
unsigned int cmd)
{
- void (*outer_cache_op)(phys_addr_t, phys_addr_t);
-
- switch (cmd) {
- case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
- outer_cache_op = outer_clean_range;
- break;
- case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
- outer_cache_op = outer_inv_range;
- break;
- case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
- outer_cache_op = outer_flush_range;
- break;
- default:
- return -EINVAL;
- }
-
- if (cma_heap_has_outer_cache) {
- struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
-
- outer_cache_op(info->handle, info->handle + length);
- }
-
- return 0;
+ pr_info("%s: cache operations disallowed from secure heap %s\n",
+ __func__, heap->name);
+ return -EINVAL;
}
static int ion_secure_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index a7473e2..8a5e5c9 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -614,6 +614,11 @@
int i;
pgprot_t pgprot;
+ if (!pages) {
+ mutex_unlock(&cp_heap->lock);
+ return ERR_PTR(-ENOMEM);
+ }
+
if (ION_IS_CACHED(buffer->flags))
pgprot = PAGE_KERNEL;
else
@@ -731,26 +736,78 @@
void *vaddr, unsigned int offset, unsigned int length,
unsigned int cmd)
{
- void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
struct ion_cp_heap *cp_heap =
- container_of(heap, struct ion_cp_heap, heap);
+ container_of(heap, struct ion_cp_heap, heap);
+ unsigned int size_to_vmap, total_size;
struct ion_cp_buffer *buf = buffer->priv_virt;
+ int i, j;
+ void *ptr = NULL;
+ ion_phys_addr_t buff_phys = buffer->priv_phys;
- switch (cmd) {
- case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
- outer_cache_op = outer_clean_range;
- break;
- case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
- outer_cache_op = outer_inv_range;
- break;
- case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
- outer_cache_op = outer_flush_range;
- break;
- default:
- return -EINVAL;
+ if (!vaddr) {
+ /*
+ * Split the vmalloc space into smaller regions in
+ * order to clean and/or invalidate the cache.
+ */
+ size_to_vmap = (VMALLOC_END - VMALLOC_START)/8;
+ total_size = buffer->size;
+ for (i = 0; i < total_size; i += size_to_vmap) {
+ size_to_vmap = min(size_to_vmap, total_size - i);
+ for (j = 0; j < 10 && size_to_vmap; ++j) {
+ ptr = ioremap(buff_phys, size_to_vmap);
+ if (ptr) {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(ptr,
+ ptr + size_to_vmap);
+ outer_cache_op =
+ outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
+ buff_phys += size_to_vmap;
+ break;
+ } else {
+ size_to_vmap >>= 1;
+ }
+ }
+ if (!ptr) {
+ pr_err("Couldn't io-remap the memory\n");
+ return -EINVAL;
+ }
+ iounmap(ptr);
+ }
+ } else {
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ dmac_inv_range(vaddr, vaddr + length);
+ outer_cache_op = outer_inv_range;
+ break;
+ case ION_IOC_CLEAN_INV_CACHES:
+ dmac_flush_range(vaddr, vaddr + length);
+ outer_cache_op = outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
}
if (cp_heap->has_outer_cache) {
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 761fdde..9ab6b85 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -330,6 +330,14 @@
data->mapped_size = iova_length;
extra = iova_length - buffer->size;
+ /* Use the biggest alignment to allow bigger IOMMU mappings.
+ * Use the first entry since the first entry will always be the
+ * biggest entry. To take advantage of bigger mapping sizes both the
+ * VA and PA addresses have to be aligned to the biggest size.
+ */
+ if (buffer->sg_table->sgl->length > align)
+ align = buffer->sg_table->sgl->length;
+
ret = msm_allocate_iova_address(domain_num, partition_num,
data->mapped_size, align,
&data->iova_addr);
@@ -409,15 +417,30 @@
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ else
+ dmac_clean_range(vaddr, vaddr + length);
outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ else
+ dmac_inv_range(vaddr, vaddr + length);
outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
+ if (!vaddr) {
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ } else {
+ dmac_flush_range(vaddr, vaddr + length);
+ }
outer_cache_op = outer_flush_range;
break;
default:
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index f33fc18..7046709 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -28,6 +28,7 @@
#include <mach/memory.h>
#include <asm/cacheflush.h>
#include <linux/msm_ion.h>
+#include <linux/dma-mapping.h>
static atomic_t system_heap_allocated;
static atomic_t system_contig_heap_allocated;
@@ -184,15 +185,30 @@
switch (cmd) {
case ION_IOC_CLEAN_CACHES:
- dmac_clean_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ else
+ dmac_clean_range(vaddr, vaddr + length);
outer_cache_op = outer_clean_range;
break;
case ION_IOC_INV_CACHES:
- dmac_inv_range(vaddr, vaddr + length);
+ if (!vaddr)
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ else
+ dmac_inv_range(vaddr, vaddr + length);
outer_cache_op = outer_inv_range;
break;
case ION_IOC_CLEAN_INV_CACHES:
- dmac_flush_range(vaddr, vaddr + length);
+ if (!vaddr) {
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_TO_DEVICE);
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_FROM_DEVICE);
+ } else {
+ dmac_flush_range(vaddr, vaddr + length);
+ }
outer_cache_op = outer_flush_range;
break;
default:
@@ -255,6 +271,14 @@
data->mapped_size = iova_length;
extra = iova_length - buffer->size;
+ /* Use the biggest alignment to allow bigger IOMMU mappings.
+ * Use the first entry since the first entry will always be the
+ * biggest entry. To take advantage of bigger mapping sizes both the
+ * VA and PA addresses have to be aligned to the biggest size.
+ */
+ if (table->sgl->length > align)
+ align = table->sgl->length;
+
ret = msm_allocate_iova_address(domain_num, partition_num,
data->mapped_size, align,
&data->iova_addr);
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
index 8c9b95d..48c2efb 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.c
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -55,7 +55,7 @@
cmd.permission_type = permission_type;
cmd.lock = SCM_CP_PROTECT;
- return scm_call(SCM_SVC_CP, SCM_CP_LOCK_CMD_ID,
+ return scm_call(SCM_SVC_MP, SCM_CP_LOCK_CMD_ID,
&cmd, sizeof(cmd), NULL, 0);
}
@@ -68,7 +68,7 @@
cmd.permission_type = permission_type;
cmd.lock = SCM_CP_UNPROTECT;
- return scm_call(SCM_SVC_CP, SCM_CP_LOCK_CMD_ID,
+ return scm_call(SCM_SVC_MP, SCM_CP_LOCK_CMD_ID,
&cmd, sizeof(cmd), NULL, 0);
}
@@ -154,7 +154,7 @@
request.chunks.chunk_list_size = nchunks;
request.chunks.chunk_size = chunk_size;
- return scm_call(SCM_SVC_CP, MEM_PROTECT_LOCK_ID,
+ return scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID,
&request, sizeof(request), &resp, sizeof(resp));
}
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index bd27385..33e6fed 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -54,6 +54,11 @@
.name = ION_VMALLOC_HEAP_NAME,
},
{
+ .id = ION_SYSTEM_CONTIG_HEAP_ID,
+ .type = ION_HEAP_TYPE_SYSTEM_CONTIG,
+ .name = ION_KMALLOC_HEAP_NAME,
+ },
+ {
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_SECURE_DMA,
.name = ION_MM_HEAP_NAME,
@@ -715,7 +720,7 @@
start = (unsigned long) data.vaddr;
end = (unsigned long) data.vaddr + data.length;
- if (check_vaddr_bounds(start, end)) {
+ if (start && check_vaddr_bounds(start, end)) {
up_read(&mm->mmap_sem);
pr_err("%s: virtual address %p is out of bounds\n",
__func__, data.vaddr);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index e245cfc..ed351bd 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -232,12 +232,14 @@
#define A3XX_SP_VS_OUT_REG_7 0x22CE
#define A3XX_SP_VS_VPC_DST_REG_0 0x22D0
#define A3XX_SP_VS_OBJ_OFFSET_REG 0x22D4
+#define A3XX_SP_VS_OBJ_START_REG 0x22D5
#define A3XX_SP_VS_PVT_MEM_ADDR_REG 0x22D7
#define A3XX_SP_VS_PVT_MEM_SIZE_REG 0x22D8
#define A3XX_SP_VS_LENGTH_REG 0x22DF
#define A3XX_SP_FS_CTRL_REG0 0x22E0
#define A3XX_SP_FS_CTRL_REG1 0x22E1
#define A3XX_SP_FS_OBJ_OFFSET_REG 0x22E2
+#define A3XX_SP_FS_OBJ_START_REG 0x22E3
#define A3XX_SP_FS_PVT_MEM_ADDR_REG 0x22E5
#define A3XX_SP_FS_PVT_MEM_SIZE_REG 0x22E6
#define A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x22E8
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index bf45a63..b9f00b5 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/delay.h>
#include <mach/socinfo.h>
#include <mach/msm_bus_board.h>
@@ -121,14 +122,21 @@
* If the values of these registers are same after
* KGSL_TIMEOUT_PART time, GPU hang is reported in
* kernel log.
+ * *****ALERT******ALERT********ALERT*************
+ * Order of registers below is important, registers
+ * from LONG_IB_DETECT_REG_INDEX_START to
+ * LONG_IB_DETECT_REG_INDEX_END are used in long ib detection.
*/
-unsigned int hang_detect_regs[] = {
+#define LONG_IB_DETECT_REG_INDEX_START 1
+#define LONG_IB_DETECT_REG_INDEX_END 5
+
+unsigned int ft_detect_regs[] = {
A3XX_RBBM_STATUS,
- REG_CP_RB_RPTR,
+ REG_CP_RB_RPTR, /* LONG_IB_DETECT_REG_INDEX_START */
REG_CP_IB1_BASE,
REG_CP_IB1_BUFSZ,
REG_CP_IB2_BASE,
- REG_CP_IB2_BUFSZ,
+ REG_CP_IB2_BUFSZ, /* LONG_IB_DETECT_REG_INDEX_END */
0,
0,
0,
@@ -137,7 +145,7 @@
0
};
-const unsigned int hang_detect_regs_count = ARRAY_SIZE(hang_detect_regs);
+const unsigned int ft_detect_regs_count = ARRAY_SIZE(ft_detect_regs);
/*
* This is the master list of all GPU cores that are supported by this
@@ -302,8 +310,14 @@
struct kgsl_context *context;
struct adreno_context *adreno_ctx = NULL;
- if (!adreno_dev->drawctxt_active)
+ /*
+ * If we're idle and we don't need to use the GPU to save context
+ * state, use the CPU instead of the GPU to reprogram the
+ * iommu for simplicity's sake.
+ */
+ if (!adreno_dev->drawctxt_active || device->ftbl->isidle(device))
return kgsl_mmu_device_setstate(&device->mmu, flags);
+
num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu);
context = idr_find(&device->context_idr, context_id);
@@ -1217,12 +1231,12 @@
return 0;
}
-static int adreno_start(struct kgsl_device *device, unsigned int init_ram)
+static int adreno_init(struct kgsl_device *device)
{
- int status = -EINVAL;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ if (KGSL_STATE_DUMP_AND_FT != device->state)
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
/* Power up the device */
@@ -1246,10 +1260,9 @@
if (adreno_dev->gpurev == ADRENO_REV_UNKNOWN) {
KGSL_DRV_ERR(device, "Unknown chip ID %x\n",
adreno_dev->chip_id);
- goto error_clk_off;
+ BUG_ON(1);
}
-
/*
* Check if firmware supports the sync lock PM4 packets needed
* for IOMMUv1
@@ -1261,7 +1274,40 @@
adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
- /* Set up the MMU */
+ rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
+
+ /* Assign correct RBBM status register to hang detect regs
+ */
+ ft_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
+
+ /* Add A3XX specific registers for hang detection */
+ if (adreno_is_a3xx(adreno_dev)) {
+ ft_detect_regs[6] = A3XX_RBBM_PERFCTR_SP_7_LO;
+ ft_detect_regs[7] = A3XX_RBBM_PERFCTR_SP_7_HI;
+ ft_detect_regs[8] = A3XX_RBBM_PERFCTR_SP_6_LO;
+ ft_detect_regs[9] = A3XX_RBBM_PERFCTR_SP_6_HI;
+ ft_detect_regs[10] = A3XX_RBBM_PERFCTR_SP_5_LO;
+ ft_detect_regs[11] = A3XX_RBBM_PERFCTR_SP_5_HI;
+ }
+
+ /* Power down the device */
+ kgsl_pwrctrl_disable(device);
+
+ return 0;
+}
+
+static int adreno_start(struct kgsl_device *device)
+{
+ int status = -EINVAL;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+ if (KGSL_STATE_DUMP_AND_FT != device->state)
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+
+ /* Power up the device */
+ kgsl_pwrctrl_enable(device);
+
+ /* Set up a2xx special case */
if (adreno_is_a2xx(adreno_dev)) {
/*
* the MH_CLNT_INTF_CTRL_CONFIG registers aren't present
@@ -1275,20 +1321,6 @@
kgsl_mh_start(device);
}
- /* Assign correct RBBM status register to hang detect regs
- */
- hang_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
-
- /* Add A3XX specific registers for hang detection */
- if (adreno_is_a3xx(adreno_dev)) {
- hang_detect_regs[6] = A3XX_RBBM_PERFCTR_SP_7_LO;
- hang_detect_regs[7] = A3XX_RBBM_PERFCTR_SP_7_HI;
- hang_detect_regs[8] = A3XX_RBBM_PERFCTR_SP_6_LO;
- hang_detect_regs[9] = A3XX_RBBM_PERFCTR_SP_6_HI;
- hang_detect_regs[10] = A3XX_RBBM_PERFCTR_SP_5_LO;
- hang_detect_regs[11] = A3XX_RBBM_PERFCTR_SP_5_HI;
- }
-
status = kgsl_mmu_start(device);
if (status)
goto error_clk_off;
@@ -1305,16 +1337,13 @@
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
device->ftbl->irqctrl(device, 1);
- status = adreno_ringbuffer_start(&adreno_dev->ringbuffer, init_ram);
+ status = adreno_ringbuffer_start(&adreno_dev->ringbuffer);
if (status)
goto error_irq_off;
- /*
- * While recovery is on we do not want timer to
- * fire and attempt to change any device state
- */
-
- if (KGSL_STATE_DUMP_AND_RECOVER != device->state)
+ /* While fault tolerance is on we do not want timer to
+ * fire and attempt to change any device state */
+ if (KGSL_STATE_DUMP_AND_FT != device->state)
mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
device->reset_counter++;
@@ -1328,7 +1357,8 @@
kgsl_mmu_stop(&device->mmu);
error_clk_off:
- kgsl_pwrctrl_disable(device);
+ if (KGSL_STATE_DUMP_AND_FT != device->state)
+ kgsl_pwrctrl_disable(device);
return status;
}
@@ -1356,26 +1386,26 @@
}
static void adreno_mark_context_status(struct kgsl_device *device,
- int recovery_status)
+ int ft_status)
{
struct kgsl_context *context;
int next = 0;
/*
* Set the reset status of all contexts to
* INNOCENT_CONTEXT_RESET_EXT except for the bad context
- * since thats the guilty party, if recovery failed then
+ * since thats the guilty party, if fault tolerance failed then
* mark all as guilty
*/
while ((context = idr_get_next(&device->context_idr, &next))) {
struct adreno_context *adreno_context = context->devctxt;
- if (recovery_status) {
+ if (ft_status) {
context->reset_status =
KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
} else if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
context->reset_status) {
if (adreno_context->flags & (CTXT_FLAGS_GPU_HANG |
- CTXT_FLAGS_GPU_HANG_RECOVERED))
+ CTXT_FLAGS_GPU_HANG_FT))
context->reset_status =
KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
else
@@ -1410,103 +1440,310 @@
}
}
-static void adreno_destroy_recovery_data(struct adreno_recovery_data *rec_data)
+static void adreno_destroy_ft_data(struct adreno_ft_data *ft_data)
{
- vfree(rec_data->rb_buffer);
- vfree(rec_data->bad_rb_buffer);
+ vfree(ft_data->rb_buffer);
+ vfree(ft_data->bad_rb_buffer);
+ vfree(ft_data->good_rb_buffer);
}
-static int adreno_setup_recovery_data(struct kgsl_device *device,
- struct adreno_recovery_data *rec_data)
+static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
+ unsigned int *ptr,
+ bool inc)
+{
+ int status = -EINVAL;
+ unsigned int val1;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int start_ptr = *ptr;
+
+ while ((start_ptr / sizeof(unsigned int)) != rb->wptr) {
+ if (inc)
+ start_ptr = adreno_ringbuffer_inc_wrapped(start_ptr,
+ size);
+ else
+ start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
+ size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
+ if (KGSL_CMD_IDENTIFIER == val1) {
+ if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
+ start_ptr = adreno_ringbuffer_dec_wrapped(
+ start_ptr, size);
+ *ptr = start_ptr;
+ status = 0;
+ break;
+ }
+ }
+ return status;
+}
+
+static int _find_cmd_seq_after_eop_ts(struct adreno_ringbuffer *rb,
+ unsigned int *rb_rptr,
+ unsigned int global_eop,
+ bool inc)
+{
+ int status = -EINVAL;
+ unsigned int temp_rb_rptr = *rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int val[3];
+ int i = 0;
+ bool check = false;
+
+ if (inc && temp_rb_rptr / sizeof(unsigned int) != rb->wptr)
+ return status;
+
+ do {
+ /*
+ * when decrementing we need to decrement first and
+ * then read make sure we cover all the data
+ */
+ if (!inc)
+ temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
+ temp_rb_rptr, size);
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
+ temp_rb_rptr);
+
+ if (check && ((inc && val[i] == global_eop) ||
+ (!inc && (val[i] ==
+ cp_type3_packet(CP_MEM_WRITE, 2) ||
+ val[i] == CACHE_FLUSH_TS)))) {
+ /* decrement i, i.e i = (i - 1 + 3) % 3 if
+ * we are going forward, else increment i */
+ i = (i + 2) % 3;
+ if (val[i] == rb->device->memstore.gpuaddr +
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ eoptimestamp)) {
+ int j = ((i + 2) % 3);
+ if ((inc && (val[j] == CACHE_FLUSH_TS ||
+ val[j] == cp_type3_packet(
+ CP_MEM_WRITE, 2))) ||
+ (!inc && val[j] == global_eop)) {
+ /* Found the global eop */
+ status = 0;
+ break;
+ }
+ }
+ /* if no match found then increment i again
+ * since we decremented before matching */
+ i = (i + 1) % 3;
+ }
+ if (inc)
+ temp_rb_rptr = adreno_ringbuffer_inc_wrapped(
+ temp_rb_rptr, size);
+
+ i = (i + 1) % 3;
+ if (2 == i)
+ check = true;
+ } while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr);
+ /* temp_rb_rptr points to the command stream after global eop,
+ * move backward till the start of command sequence */
+ if (!status) {
+ status = _find_start_of_cmd_seq(rb, &temp_rb_rptr, false);
+ if (!status) {
+ *rb_rptr = temp_rb_rptr;
+ KGSL_FT_INFO(rb->device,
+ "Offset of cmd sequence after eop timestamp: 0x%x\n",
+ temp_rb_rptr / sizeof(unsigned int));
+ }
+ }
+ if (status)
+ KGSL_FT_ERR(rb->device,
+ "Failed to find the command sequence after eop timestamp\n");
+ return status;
+}
+
+static int _find_hanging_ib_sequence(struct adreno_ringbuffer *rb,
+ unsigned int *rb_rptr,
+ unsigned int ib1)
+{
+ int status = -EINVAL;
+ unsigned int temp_rb_rptr = *rb_rptr;
+ unsigned int size = rb->buffer_desc.size;
+ unsigned int val[2];
+ int i = 0;
+ bool check = false;
+ bool ctx_switch = false;
+
+ while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
+ kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+
+ if (check && val[i] == ib1) {
+ /* decrement i, i.e i = (i - 1 + 2) % 2 */
+ i = (i + 1) % 2;
+ if (adreno_cmd_is_ib(val[i])) {
+ /* go till start of command sequence */
+ status = _find_start_of_cmd_seq(rb,
+ &temp_rb_rptr, false);
+
+ KGSL_FT_INFO(rb->device,
+ "Found the hanging IB at offset 0x%x\n",
+ temp_rb_rptr / sizeof(unsigned int));
+ break;
+ }
+ /* if no match the increment i since we decremented
+ * before checking */
+ i = (i + 1) % 2;
+ }
+ /* Make sure you do not encounter a context switch twice, we can
+ * encounter it once for the bad context as the start of search
+ * can point to the context switch */
+ if (val[i] == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
+ if (ctx_switch) {
+ KGSL_FT_ERR(rb->device,
+ "Context switch encountered before bad "
+ "IB found\n");
+ break;
+ }
+ ctx_switch = true;
+ }
+ i = (i + 1) % 2;
+ if (1 == i)
+ check = true;
+ temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
+ size);
+ }
+ if (!status)
+ *rb_rptr = temp_rb_rptr;
+ return status;
+}
+
+static void adreno_setup_ft_data(struct kgsl_device *device,
+ struct adreno_ft_data *ft_data)
{
int ret = 0;
- unsigned int ib1_sz, ib2_sz;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+ struct kgsl_context *context;
+ struct adreno_context *adreno_context;
+ unsigned int rb_rptr = rb->wptr * sizeof(unsigned int);
- memset(rec_data, 0, sizeof(*rec_data));
+ memset(ft_data, 0, sizeof(*ft_data));
+ ft_data->start_of_replay_cmds = 0xFFFFFFFF;
+ ft_data->replay_for_snapshot = 0xFFFFFFFF;
- adreno_regread(device, REG_CP_IB1_BUFSZ, &ib1_sz);
- adreno_regread(device, REG_CP_IB2_BUFSZ, &ib2_sz);
- if (ib1_sz || ib2_sz)
- adreno_regread(device, REG_CP_IB1_BASE, &rec_data->ib1);
+ adreno_regread(device, REG_CP_IB1_BASE, &ft_data->ib1);
- kgsl_sharedmem_readl(&device->memstore, &rec_data->context_id,
+ kgsl_sharedmem_readl(&device->memstore, &ft_data->context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
kgsl_sharedmem_readl(&device->memstore,
- &rec_data->global_eop,
- KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp));
+ &ft_data->global_eop,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ eoptimestamp));
- rec_data->rb_buffer = vmalloc(rb->buffer_desc.size);
- if (!rec_data->rb_buffer) {
+ ft_data->rb_buffer = vmalloc(rb->buffer_desc.size);
+ if (!ft_data->rb_buffer) {
KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
rb->buffer_desc.size);
- return -ENOMEM;
+ return;
}
- rec_data->bad_rb_buffer = vmalloc(rb->buffer_desc.size);
- if (!rec_data->bad_rb_buffer) {
+ ft_data->bad_rb_buffer = vmalloc(rb->buffer_desc.size);
+ if (!ft_data->bad_rb_buffer) {
KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
rb->buffer_desc.size);
- ret = -ENOMEM;
- goto done;
+ return;
}
- rec_data->fault = device->mmu.fault;
-done:
+ ft_data->good_rb_buffer = vmalloc(rb->buffer_desc.size);
+ if (!ft_data->good_rb_buffer) {
+ KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
+ rb->buffer_desc.size);
+ return;
+ }
+ ft_data->status = 0;
+
+ /* find the start of bad command sequence in rb */
+ context = idr_find(&device->context_idr, ft_data->context_id);
+ /* Look for the command stream that is right after the global eop */
+
+ if (!context) {
+ /*
+ * If there is no context then fault tolerance does not need to
+ * replay anything, just reset GPU and thats it
+ */
+ return;
+ }
+
+ ft_data->ft_policy = adreno_dev->ft_policy;
+
+ if (!ft_data->ft_policy)
+ ft_data->ft_policy = KGSL_FT_DEFAULT_POLICY;
+
+ ret = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
+ ft_data->global_eop + 1, false);
if (ret) {
- vfree(rec_data->rb_buffer);
- vfree(rec_data->bad_rb_buffer);
+ ft_data->ft_policy |= KGSL_FT_TEMP_DISABLE;
+ return;
+ } else
+ ft_data->ft_policy &= ~KGSL_FT_TEMP_DISABLE;
+
+ ft_data->start_of_replay_cmds = rb_rptr;
+
+ adreno_context = context->devctxt;
+ if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
+ if (ft_data->ib1) {
+ ret = _find_hanging_ib_sequence(rb,
+ &rb_rptr, ft_data->ib1);
+ if (ret) {
+ KGSL_FT_ERR(device,
+ "Start not found for replay IB sequence\n");
+ ret = 0;
+ return;
+ }
+ ft_data->start_of_replay_cmds = rb_rptr;
+ ft_data->replay_for_snapshot = rb_rptr;
+ }
}
- return ret;
}
static int
-_adreno_recover_hang(struct kgsl_device *device,
- struct adreno_recovery_data *rec_data,
- bool try_bad_commands)
+_adreno_check_long_ib(struct kgsl_device *device)
{
- int ret;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- struct kgsl_context *context;
- struct adreno_context *adreno_context = NULL;
- struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
+ unsigned int curr_global_ts = 0;
- context = idr_find(&device->context_idr, rec_data->context_id);
- if (context == NULL) {
- KGSL_DRV_ERR(device, "Last context unknown id:%d\n",
- rec_data->context_id);
+ /* check if the global ts is still the same */
+ kgsl_sharedmem_readl(&device->memstore,
+ &curr_global_ts,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ eoptimestamp));
+
+ /* Mark long ib as handled */
+ adreno_dev->long_ib = 0;
+
+ if (curr_global_ts == adreno_dev->long_ib_ts) {
+ KGSL_FT_ERR(device,
+ "IB ran too long, invalidate ctxt\n");
+ return 1;
} else {
- adreno_context = context->devctxt;
- adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
- /*
- * set the invalid ts flag to 0 for this context since we have
- * detected a hang for it
- */
- context->wait_on_invalid_ts = false;
+ /* Do nothing GPU has gone ahead */
+ KGSL_FT_INFO(device, "false long ib detection return\n");
+ return 0;
}
+}
- /* Extract valid contents from rb which can still be executed after
- * hang */
- ret = adreno_ringbuffer_extract(rb, rec_data);
- if (ret)
- goto done;
+static int
+_adreno_ft_restart_device(struct kgsl_device *device,
+ struct kgsl_context *context)
+{
+
+ struct adreno_context *adreno_context = context->devctxt;
/* restart device */
- ret = adreno_stop(device);
- if (ret) {
- KGSL_DRV_ERR(device, "Device stop failed in recovery\n");
- goto done;
+ if (adreno_stop(device)) {
+ KGSL_FT_ERR(device, "Device stop failed\n");
+ return 1;
}
- ret = adreno_start(device, true);
- if (ret) {
- KGSL_DRV_ERR(device, "Device start failed in recovery\n");
- goto done;
+ if (adreno_init(device)) {
+ KGSL_FT_ERR(device, "Device init failed\n");
+ return 1;
+ }
+
+ if (adreno_start(device)) {
+ KGSL_FT_ERR(device, "Device start failed\n");
+ return 1;
}
if (context)
@@ -1516,83 +1753,284 @@
/* If iommu is used then we need to make sure that the iommu clocks
* are on since there could be commands in pipeline that touch iommu */
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
- ret = kgsl_mmu_enable_clk(&device->mmu,
- KGSL_IOMMU_CONTEXT_USER);
- if (ret)
- goto done;
+ if (kgsl_mmu_enable_clk(&device->mmu,
+ KGSL_IOMMU_CONTEXT_USER))
+ return 1;
}
- /* Do not try the bad commands if recovery has failed bad commands
- * once already or if hang is due to a fault */
- if (!try_bad_commands || rec_data->fault)
- rec_data->bad_rb_size = 0;
+ return 0;
+}
- if (rec_data->bad_rb_size) {
- int idle_ret;
- /* submit the bad and good context commands and wait for
- * them to pass */
- adreno_ringbuffer_restore(rb, rec_data->bad_rb_buffer,
- rec_data->bad_rb_size);
- idle_ret = adreno_idle(device);
- if (idle_ret) {
- ret = adreno_stop(device);
- if (ret) {
- KGSL_DRV_ERR(device,
- "Device stop failed in recovery\n");
- goto done;
- }
- ret = adreno_start(device, true);
- if (ret) {
- KGSL_DRV_ERR(device,
- "Device start failed in recovery\n");
- goto done;
- }
- if (context)
- kgsl_mmu_setstate(&device->mmu,
- adreno_context->pagetable,
- KGSL_MEMSTORE_GLOBAL);
+static inline void
+_adreno_debug_ft_info(struct kgsl_device *device,
+ struct adreno_ft_data *ft_data)
+{
- if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
- ret = kgsl_mmu_enable_clk(&device->mmu,
- KGSL_IOMMU_CONTEXT_USER);
- if (ret)
- goto done;
- }
+ /*
+ * Dumping rb is a very useful tool to debug FT.
+ * It will tell us if we are extracting the rb correctly
+ * NOP'ing the right IB, skipping the EOF correctly etc.
+ */
+ if (device->ft_log >= 7) {
- ret = idle_ret;
- KGSL_DRV_ERR(device,
- "Bad context commands hung in recovery\n");
- } else {
- KGSL_DRV_ERR(device,
- "Bad context commands succeeded in recovery\n");
- if (adreno_context)
- adreno_context->flags = (adreno_context->flags &
- ~CTXT_FLAGS_GPU_HANG) |
- CTXT_FLAGS_GPU_HANG_RECOVERED;
- adreno_dev->drawctxt_active = last_active_ctx;
- }
+ /* Print fault tolerance data here */
+ KGSL_FT_INFO(device, "Temp RB buffer size 0x%X\n",
+ ft_data->rb_size);
+ adreno_dump_rb(device, ft_data->rb_buffer,
+ ft_data->rb_size<<2, 0, ft_data->rb_size);
+
+ KGSL_FT_INFO(device, "Bad RB buffer size 0x%X\n",
+ ft_data->bad_rb_size);
+ adreno_dump_rb(device, ft_data->bad_rb_buffer,
+ ft_data->bad_rb_size<<2, 0, ft_data->bad_rb_size);
+
+ KGSL_FT_INFO(device, "Good RB buffer size 0x%X\n",
+ ft_data->good_rb_size);
+ adreno_dump_rb(device, ft_data->good_rb_buffer,
+ ft_data->good_rb_size<<2, 0, ft_data->good_rb_size);
+
}
- /* If either the bad command sequence failed or we did not play it */
- if (ret || !rec_data->bad_rb_size) {
- adreno_ringbuffer_restore(rb, rec_data->rb_buffer,
- rec_data->rb_size);
+}
+
+static int
+_adreno_ft_resubmit_rb(struct kgsl_device *device,
+ struct adreno_ringbuffer *rb,
+ struct kgsl_context *context,
+ struct adreno_ft_data *ft_data,
+ unsigned int *buff, unsigned int size)
+{
+ unsigned int ret = 0;
+ unsigned int retry_num = 0;
+
+ _adreno_debug_ft_info(device, ft_data);
+
+ do {
+ ret = _adreno_ft_restart_device(device, context);
+ if (ret == 0)
+ break;
+ /*
+ * If device restart fails sleep for 20ms before
+ * attempting restart. This allows GPU HW to settle
+ * and improve the chances of next restart to be
+ * successful.
+ */
+ msleep(20);
+ KGSL_FT_ERR(device, "Retry device restart %d\n", retry_num);
+ retry_num++;
+ } while (retry_num < 4);
+
+ if (ret) {
+ KGSL_FT_ERR(device, "Device restart failed\n");
+ BUG_ON(1);
+ goto done;
+ }
+
+ if (size) {
+
+ /* submit commands and wait for them to pass */
+ adreno_ringbuffer_restore(rb, buff, size);
+
ret = adreno_idle(device);
- if (ret) {
- /* If we fail here we can try to invalidate another
- * context and try recovering again */
- ret = -EAGAIN;
- goto done;
+ }
+
+done:
+ return ret;
+}
+
+
+static int
+_adreno_ft(struct kgsl_device *device,
+ struct adreno_ft_data *ft_data)
+{
+ int ret = 0, i;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+ struct kgsl_context *context;
+ struct adreno_context *adreno_context = NULL;
+ struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
+ unsigned int long_ib = 0;
+
+ context = idr_find(&device->context_idr, ft_data->context_id);
+ if (context == NULL) {
+ KGSL_FT_ERR(device, "Last context unknown id:%d\n",
+ ft_data->context_id);
+ goto play_good_cmds;
+ } else {
+ adreno_context = context->devctxt;
+ adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
+ /*
+ * set the invalid ts flag to 0 for this context since we have
+ * detected a hang for it
+ */
+ context->wait_on_invalid_ts = false;
+
+ if (!(adreno_context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) {
+ KGSL_FT_ERR(device, "Fault tolerance not supported\n");
+ goto play_good_cmds;
}
- /* ringbuffer now has data from the last valid context id,
- * so restore the active_ctx to the last valid context */
- if (rec_data->last_valid_ctx_id) {
- struct kgsl_context *last_ctx =
- idr_find(&device->context_idr,
- rec_data->last_valid_ctx_id);
- if (last_ctx)
- adreno_dev->drawctxt_active = last_ctx->devctxt;
+
+ /*
+ * This flag will be set by userspace for contexts
+ * that do not want to be fault tolerant (ex: OPENCL)
+ */
+ if (adreno_context->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE) {
+ ft_data->status = 1;
+ KGSL_FT_ERR(device,
+ "No FT set for this context play good cmds\n");
+ goto play_good_cmds;
+ }
+
+ }
+
+ /* Check if we detected a long running IB, if false return */
+ if (adreno_dev->long_ib) {
+ long_ib = _adreno_check_long_ib(device);
+ if (!long_ib) {
+ adreno_context->flags &= ~CTXT_FLAGS_GPU_HANG;
+ return 0;
}
}
+
+ /*
+ * Extract valid contents from rb which can still be executed after
+ * hang
+ */
+ adreno_ringbuffer_extract(rb, ft_data);
+
+ /* If long IB detected do not attempt replay of bad cmds */
+ if (long_ib) {
+ _adreno_debug_ft_info(device, ft_data);
+ goto play_good_cmds;
+ }
+
+ if ((ft_data->ft_policy & KGSL_FT_DISABLE) ||
+ (ft_data->ft_policy & KGSL_FT_TEMP_DISABLE)) {
+ KGSL_FT_ERR(device, "NO FT policy play only good cmds\n");
+ ft_data->status = 1;
+ goto play_good_cmds;
+ }
+
+ /* Do not try the reply if hang is due to a pagefault */
+ if (adreno_context->pagefault) {
+ if ((ft_data->context_id == adreno_context->id) &&
+ (ft_data->global_eop == adreno_context->pagefault_ts)) {
+ ft_data->ft_policy &= ~KGSL_FT_REPLAY;
+ KGSL_FT_ERR(device, "MMU fault skipping replay\n");
+ }
+
+ adreno_context->pagefault = 0;
+ }
+
+ if (ft_data->ft_policy & KGSL_FT_REPLAY) {
+ ret = _adreno_ft_resubmit_rb(device, rb, context, ft_data,
+ ft_data->bad_rb_buffer, ft_data->bad_rb_size);
+
+ if (ret) {
+ KGSL_FT_ERR(device, "Replay status: 1\n");
+ ft_data->status = 1;
+ } else
+ goto play_good_cmds;
+ }
+
+ if (ft_data->ft_policy & KGSL_FT_SKIPIB) {
+ for (i = 0; i < ft_data->bad_rb_size; i++) {
+ if ((ft_data->bad_rb_buffer[i] ==
+ CP_HDR_INDIRECT_BUFFER_PFD) &&
+ (ft_data->bad_rb_buffer[i+1] == ft_data->ib1)) {
+
+ ft_data->bad_rb_buffer[i] = cp_nop_packet(2);
+ ft_data->bad_rb_buffer[i+1] =
+ KGSL_NOP_IB_IDENTIFIER;
+ ft_data->bad_rb_buffer[i+2] =
+ KGSL_NOP_IB_IDENTIFIER;
+ break;
+ }
+ }
+
+ if ((i == (ft_data->bad_rb_size)) || (!ft_data->ib1)) {
+ KGSL_FT_ERR(device, "Bad IB to NOP not found\n");
+ ft_data->status = 1;
+ goto play_good_cmds;
+ }
+
+ ret = _adreno_ft_resubmit_rb(device, rb, context, ft_data,
+ ft_data->bad_rb_buffer, ft_data->bad_rb_size);
+
+ if (ret) {
+ KGSL_FT_ERR(device, "NOP faulty IB status: 1\n");
+ ft_data->status = 1;
+ } else {
+ ft_data->status = 0;
+ goto play_good_cmds;
+ }
+ }
+
+ if (ft_data->ft_policy & KGSL_FT_SKIPFRAME) {
+ for (i = 0; i < ft_data->bad_rb_size; i++) {
+ if (ft_data->bad_rb_buffer[i] ==
+ KGSL_END_OF_FRAME_IDENTIFIER) {
+ ft_data->bad_rb_buffer[0] = cp_nop_packet(i);
+ break;
+ }
+ }
+
+ /* EOF not found in RB, discard till EOF in
+ next IB submission */
+ if (i == ft_data->bad_rb_size) {
+ adreno_context->flags |= CTXT_FLAGS_SKIP_EOF;
+ KGSL_FT_INFO(device,
+ "EOF not found in RB, skip next issueib till EOF\n");
+ ft_data->bad_rb_buffer[0] = cp_nop_packet(i);
+ }
+
+ ret = _adreno_ft_resubmit_rb(device, rb, context, ft_data,
+ ft_data->bad_rb_buffer, ft_data->bad_rb_size);
+
+ if (ret) {
+ KGSL_FT_ERR(device, "Skip EOF status: 1\n");
+ ft_data->status = 1;
+ } else {
+ ft_data->status = 0;
+ goto play_good_cmds;
+ }
+ }
+
+play_good_cmds:
+
+ if (ft_data->status)
+ KGSL_FT_ERR(device, "Bad context commands failed\n");
+ else {
+ KGSL_FT_INFO(device, "Bad context commands success\n");
+
+ if (adreno_context) {
+ adreno_context->flags = (adreno_context->flags &
+ ~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
+ }
+ adreno_dev->drawctxt_active = last_active_ctx;
+ }
+
+ ret = _adreno_ft_resubmit_rb(device, rb, context, ft_data,
+ ft_data->good_rb_buffer, ft_data->good_rb_size);
+
+ if (ret) {
+ /* If we fail here we can try to invalidate another
+ * context and try fault tolerance again */
+ ret = -EAGAIN;
+ KGSL_FT_ERR(device, "Playing good commands unsuccessful\n");
+ goto done;
+ } else
+ KGSL_FT_INFO(device, "Playing good commands successful\n");
+
+ /* ringbuffer now has data from the last valid context id,
+ * so restore the active_ctx to the last valid context */
+ if (ft_data->last_valid_ctx_id) {
+ struct kgsl_context *last_ctx =
+ idr_find(&device->context_idr,
+ ft_data->last_valid_ctx_id);
+ if (last_ctx)
+ adreno_dev->drawctxt_active = last_ctx->devctxt;
+ }
+
done:
/* Turn off iommu clocks */
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
@@ -1601,40 +2039,38 @@
}
static int
-adreno_recover_hang(struct kgsl_device *device,
- struct adreno_recovery_data *rec_data)
+adreno_ft(struct kgsl_device *device,
+ struct adreno_ft_data *ft_data)
{
int ret = 0;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
unsigned int timestamp;
- KGSL_DRV_ERR(device,
- "Starting recovery from 3D GPU hang. Recovery parameters: IB1: 0x%X, "
+ KGSL_FT_INFO(device,
+ "Start Parameters: IB1: 0x%X, "
"Bad context_id: %u, global_eop: 0x%x\n",
- rec_data->ib1, rec_data->context_id, rec_data->global_eop);
+ ft_data->ib1, ft_data->context_id, ft_data->global_eop);
timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
- KGSL_DRV_ERR(device, "Last issued global timestamp: %x\n", timestamp);
+ KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
/* We may need to replay commands multiple times based on whether
* multiple contexts hang the GPU */
while (true) {
- if (!ret)
- ret = _adreno_recover_hang(device, rec_data, true);
- else
- ret = _adreno_recover_hang(device, rec_data, false);
+
+ ret = _adreno_ft(device, ft_data);
if (-EAGAIN == ret) {
- /* setup new recovery parameters and retry, this
+ /* setup new fault tolerance parameters and retry, this
* means more than 1 contexts are causing hang */
- adreno_destroy_recovery_data(rec_data);
- adreno_setup_recovery_data(device, rec_data);
- KGSL_DRV_ERR(device,
- "Retry recovery from 3D GPU hang. Recovery parameters: "
+ adreno_destroy_ft_data(ft_data);
+ adreno_setup_ft_data(device, ft_data);
+ KGSL_FT_INFO(device,
+ "Retry. Parameters: "
"IB1: 0x%X, Bad context_id: %u, global_eop: 0x%x\n",
- rec_data->ib1, rec_data->context_id,
- rec_data->global_eop);
+ ft_data->ib1, ft_data->context_id,
+ ft_data->global_eop);
} else {
break;
}
@@ -1643,7 +2079,7 @@
if (ret)
goto done;
- /* Restore correct states after recovery */
+ /* Restore correct states after fault tolerance */
if (adreno_dev->drawctxt_active)
device->mmu.hwpagetable =
adreno_dev->drawctxt_active->pagetable;
@@ -1662,34 +2098,39 @@
done:
adreno_set_max_ts_for_bad_ctxs(device);
adreno_mark_context_status(device, ret);
- if (!ret)
- KGSL_DRV_ERR(device, "Recovery succeeded\n");
- else
- KGSL_DRV_ERR(device, "Recovery failed\n");
+ KGSL_FT_ERR(device, "policy 0x%X status 0x%x\n",
+ ft_data->ft_policy, ret);
return ret;
}
int
-adreno_dump_and_recover(struct kgsl_device *device)
+adreno_dump_and_exec_ft(struct kgsl_device *device)
{
int result = -ETIMEDOUT;
- struct adreno_recovery_data rec_data;
+ struct adreno_ft_data ft_data;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ unsigned int curr_pwrlevel;
if (device->state == KGSL_STATE_HUNG)
goto done;
- if (device->state == KGSL_STATE_DUMP_AND_RECOVER) {
+ if (device->state == KGSL_STATE_DUMP_AND_FT) {
mutex_unlock(&device->mutex);
- wait_for_completion(&device->recovery_gate);
+ wait_for_completion(&device->ft_gate);
mutex_lock(&device->mutex);
if (device->state != KGSL_STATE_HUNG)
result = 0;
} else {
- kgsl_pwrctrl_set_state(device, KGSL_STATE_DUMP_AND_RECOVER);
- INIT_COMPLETION(device->recovery_gate);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_DUMP_AND_FT);
+ INIT_COMPLETION(device->ft_gate);
/* Detected a hang */
- /* Get the recovery data as soon as hang is detected */
- result = adreno_setup_recovery_data(device, &rec_data);
+ /* Run fault tolerance at max power level */
+ curr_pwrlevel = pwr->active_pwrlevel;
+ kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel);
+
+ /* Get the fault tolerance data as soon as hang is detected */
+ adreno_setup_ft_data(device, &ft_data);
/*
* Trigger an automatic dump of the state to
* the console
@@ -1697,25 +2138,43 @@
kgsl_postmortem_dump(device, 0);
/*
- * Make a GPU snapshot. For now, do it after the PM dump so we
- * can at least be sure the PM dump will work as it always has
+ * If long ib is detected, do not attempt postmortem or
+ * snapshot, if GPU is still executing commands
+ * we will get errors
*/
- kgsl_device_snapshot(device, 1);
+ if (!adreno_dev->long_ib) {
+ /*
+ * Trigger an automatic dump of the state to
+ * the console
+ */
+ kgsl_postmortem_dump(device, 0);
- result = adreno_recover_hang(device, &rec_data);
- adreno_destroy_recovery_data(&rec_data);
+ /*
+ * Make a GPU snapshot. For now, do it after the
+ * PM dump so we can at least be sure the PM dump
+ * will work as it always has
+ */
+ kgsl_device_snapshot(device, 1);
+ }
+
+ result = adreno_ft(device, &ft_data);
+ adreno_destroy_ft_data(&ft_data);
+
+ /* restore power level */
+ kgsl_pwrctrl_pwrlevel_change(device, curr_pwrlevel);
+
if (result) {
kgsl_pwrctrl_set_state(device, KGSL_STATE_HUNG);
} else {
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
}
- complete_all(&device->recovery_gate);
+ complete_all(&device->ft_gate);
}
done:
return result;
}
-EXPORT_SYMBOL(adreno_dump_and_recover);
+EXPORT_SYMBOL(adreno_dump_and_exec_ft);
static int adreno_getproperty(struct kgsl_device *device,
enum kgsl_property_type type,
@@ -1882,7 +2341,7 @@
do {
if (time_after(jiffies, wait)) {
/* Check to see if the core is hung */
- if (adreno_hang_detect(device, regs))
+ if (adreno_ft_detect(device, regs))
return -ETIMEDOUT;
wait = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
@@ -1906,7 +2365,7 @@
unsigned int rbbm_status;
unsigned long wait_time;
unsigned long wait_time_part;
- unsigned int prev_reg_val[hang_detect_regs_count];
+ unsigned int prev_reg_val[ft_detect_regs_count];
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -1939,7 +2398,7 @@
if (time_after(jiffies, wait_time_part)) {
wait_time_part = jiffies +
msecs_to_jiffies(KGSL_TIMEOUT_PART);
- if ((adreno_hang_detect(device, prev_reg_val)))
+ if ((adreno_ft_detect(device, prev_reg_val)))
goto err;
}
@@ -1947,9 +2406,9 @@
err:
KGSL_DRV_ERR(device, "spun too long waiting for RB to idle\n");
- if (KGSL_STATE_DUMP_AND_RECOVER != device->state &&
- !adreno_dump_and_recover(device)) {
- wait_time = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
+ if (KGSL_STATE_DUMP_AND_FT != device->state &&
+ !adreno_dump_and_exec_ft(device)) {
+ wait_time = jiffies + ADRENO_IDLE_TIMEOUT;
goto retry;
}
return -ETIMEDOUT;
@@ -2297,16 +2756,28 @@
-unsigned int adreno_hang_detect(struct kgsl_device *device,
+unsigned int adreno_ft_detect(struct kgsl_device *device,
unsigned int *prev_reg_val)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- unsigned int curr_reg_val[hang_detect_regs_count];
- unsigned int hang_detected = 1;
+ unsigned int curr_reg_val[ft_detect_regs_count];
+ unsigned int fast_hang_detected = 1;
+ unsigned int long_ib_detected = 1;
unsigned int i;
static unsigned long next_hang_detect_time;
+ static unsigned int prev_global_ts;
+ unsigned int curr_global_ts = 0;
+ unsigned int curr_context_id = 0;
+ static struct adreno_context *curr_context;
+ static struct kgsl_context *context;
if (!adreno_dev->fast_hang_detect)
+ fast_hang_detected = 0;
+
+ if (!adreno_dev->long_ib_detect)
+ long_ib_detected = 0;
+
+ if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED))
return 0;
if (is_adreno_rbbm_status_idle(device)) {
@@ -2340,20 +2811,125 @@
next_hang_detect_time = (jiffies +
msecs_to_jiffies(KGSL_TIMEOUT_PART-1));
- for (i = 0; i < hang_detect_regs_count; i++) {
-
- if (hang_detect_regs[i] == 0)
+ /* Read the current Hang detect reg values here */
+ for (i = 0; i < ft_detect_regs_count; i++) {
+ if (ft_detect_regs[i] == 0)
continue;
-
- adreno_regread(device, hang_detect_regs[i],
- &curr_reg_val[i]);
- if (curr_reg_val[i] != prev_reg_val[i]) {
- prev_reg_val[i] = curr_reg_val[i];
- hang_detected = 0;
- }
+ adreno_regread(device, ft_detect_regs[i],
+ &curr_reg_val[i]);
}
- return hang_detected;
+ /* Read the current global timestamp here */
+ kgsl_sharedmem_readl(&device->memstore,
+ &curr_global_ts,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ eoptimestamp));
+ /* Make sure the memstore read has posted */
+ mb();
+
+ if (curr_global_ts == prev_global_ts) {
+
+ /* Get the current context here */
+ if (context == NULL) {
+ kgsl_sharedmem_readl(&device->memstore,
+ &curr_context_id,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ current_context));
+ /* Make sure the memstore read has posted */
+ mb();
+ context = idr_find(&device->context_idr,
+ curr_context_id);
+ if (context != NULL) {
+ curr_context = context->devctxt;
+ curr_context->ib_gpu_time_used = 0;
+ } else {
+ KGSL_DRV_ERR(device,
+ "Fault tolerance no context found\n");
+ }
+ }
+
+ if (curr_context != NULL) {
+
+ curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
+ KGSL_FT_INFO(device,
+ "Proc %s used GPU Time %d ms on timestamp 0x%X\n",
+ curr_context->pid_name, curr_context->ib_gpu_time_used,
+ curr_global_ts+1);
+
+ for (i = 0; i < ft_detect_regs_count; i++) {
+ if (curr_reg_val[i] != prev_reg_val[i]) {
+ fast_hang_detected = 0;
+
+ /* Check for long IB here */
+ if ((i >=
+ LONG_IB_DETECT_REG_INDEX_START)
+ &&
+ (i <=
+ LONG_IB_DETECT_REG_INDEX_END))
+ long_ib_detected = 0;
+ }
+ }
+
+ if (fast_hang_detected) {
+ KGSL_FT_ERR(device,
+ "Proc %s, ctxt_id %d ts %d triggered fault tolerance"
+ " on global ts %d\n",
+ curr_context->pid_name, curr_context->id
+ , (kgsl_readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED)+1),
+ curr_global_ts+1);
+ return 1;
+ }
+
+ if ((long_ib_detected) &&
+ (!(curr_context->flags &
+ CTXT_FLAGS_NO_FAULT_TOLERANCE))) {
+ curr_context->ib_gpu_time_used +=
+ KGSL_TIMEOUT_PART;
+ if (curr_context->ib_gpu_time_used >
+ KGSL_TIMEOUT_LONG_IB_DETECTION) {
+ if (adreno_dev->long_ib_ts !=
+ curr_global_ts) {
+ KGSL_FT_ERR(device,
+ "Proc %s, ctxt_id %d ts %d"
+ "used GPU for %d ms long ib "
+ "detected on global ts %d\n",
+ curr_context->pid_name,
+ curr_context->id,
+ (kgsl_readtimestamp(device,
+ context,
+ KGSL_TIMESTAMP_RETIRED)+1),
+ curr_context->ib_gpu_time_used,
+ curr_global_ts+1);
+ adreno_dev->long_ib = 1;
+ adreno_dev->long_ib_ts =
+ curr_global_ts;
+ curr_context->ib_gpu_time_used =
+ 0;
+ return 1;
+ }
+ }
+ }
+ } else {
+ KGSL_FT_ERR(device,
+ "Last context unknown id:%d\n",
+ curr_context_id);
+ }
+ } else {
+ /* GPU is moving forward */
+ prev_global_ts = curr_global_ts;
+ context = NULL;
+ curr_context = NULL;
+ adreno_dev->long_ib = 0;
+ adreno_dev->long_ib_ts = 0;
+ }
+
+
+ /* If hangs are not detected copy the current reg values
+ * to previous values and return no hang */
+ for (i = 0; i < ft_detect_regs_count; i++)
+ prev_reg_val[i] = curr_reg_val[i];
+ return 0;
}
/**
@@ -2362,7 +2938,8 @@
* @context - pointer to the active KGSL context
* @timestamp - the timestamp that the process was waiting for
*
- * Process a possible GPU hang and try to recover from it cleanly
+ * Process a possible GPU hang and try fault tolerance from it
+ * cleanly
*/
static int adreno_handle_hang(struct kgsl_device *device,
struct kgsl_context *context, unsigned int timestamp)
@@ -2370,6 +2947,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int context_id = _get_context_id(context);
unsigned int ts_issued;
+ unsigned int rptr;
/* Do one last check to see if we somehow made it through */
if (kgsl_check_timestamp(device, context, timestamp))
@@ -2377,15 +2955,22 @@
ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
- KGSL_DRV_ERR(device,
+ adreno_regread(device, REG_CP_RB_RPTR, &rptr);
+
+ /* Make sure timestamp check finished before triggering a hang */
+ mb();
+
+ KGSL_DRV_WARN(device,
"Device hang detected while waiting for timestamp: "
"<%d:0x%x>, last submitted timestamp: <%d:0x%x>, "
- "wptr: 0x%x\n",
- context_id, timestamp, context_id, ts_issued,
- adreno_dev->ringbuffer.wptr);
+ "retired timestamp: <%d:0x%x>, wptr: 0x%x, rptr: 0x%x\n",
+ context_id, timestamp, context_id, ts_issued, context_id,
+ kgsl_readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED),
+ adreno_dev->ringbuffer.wptr, rptr);
- /* Return 0 after a successful recovery */
- if (!adreno_dump_and_recover(device))
+ /* Return 0 after a successful fault tolerance */
+ if (!adreno_dump_and_exec_ft(device))
return 0;
return -ETIMEDOUT;
@@ -2439,7 +3024,7 @@
struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
unsigned int context_id = _get_context_id(context);
- unsigned int prev_reg_val[hang_detect_regs_count];
+ unsigned int prev_reg_val[ft_detect_regs_count];
unsigned int time_elapsed = 0;
unsigned int wait;
int ts_compare = 1;
@@ -2498,7 +3083,7 @@
}
/* Check to see if the GPU is hung */
- if (adreno_hang_detect(device, prev_reg_val)) {
+ if (adreno_ft_detect(device, prev_reg_val)) {
ret = adreno_handle_hang(device, context, timestamp);
break;
}
@@ -2714,6 +3299,7 @@
.idle = adreno_idle,
.isidle = adreno_isidle,
.suspend_context = adreno_suspend_context,
+ .init = adreno_init,
.start = adreno_start,
.stop = adreno_stop,
.getproperty = adreno_getproperty,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index c1f2423..6c57078 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -34,6 +34,7 @@
#define KGSL_CMD_FLAGS_NONE 0x00000000
#define KGSL_CMD_FLAGS_PMODE 0x00000001
#define KGSL_CMD_FLAGS_INTERNAL_ISSUE 0x00000002
+#define KGSL_CMD_FLAGS_EOF 0x00000100
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF
@@ -41,6 +42,8 @@
#define KGSL_CMD_INTERNAL_IDENTIFIER 0x2EEDD00D
#define KGSL_START_OF_IB_IDENTIFIER 0x2EADEABE
#define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD
+#define KGSL_END_OF_FRAME_IDENTIFIER 0x2E0F2E0F
+#define KGSL_NOP_IB_IDENTIFIER 0x20F20F20
#ifdef CONFIG_MSM_SCM
#define ADRENO_DEFAULT_PWRSCALE_POLICY (&kgsl_pwrscale_policy_tz)
@@ -101,9 +104,15 @@
unsigned int instruction_size;
unsigned int ib_check_level;
unsigned int fast_hang_detect;
+ unsigned int ft_policy;
+ unsigned int long_ib_detect;
+ unsigned int long_ib;
+ unsigned int long_ib_ts;
+ unsigned int ft_pf_policy;
unsigned int gpulist_index;
struct ocmem_buf *ocmem_hdl;
unsigned int ocmem_base;
+ unsigned int gpu_cycles;
};
struct adreno_gpudev {
@@ -133,8 +142,8 @@
};
/*
- * struct adreno_recovery_data - Structure that contains all information to
- * perform gpu recovery from hangs
+ * struct adreno_ft_data - Structure that contains all information to
+ * perform gpu fault tolerance
* @ib1 - IB1 that the GPU was executing when hang happened
* @context_id - Context which caused the hang
* @global_eop - eoptimestamp at time of hang
@@ -142,11 +151,19 @@
* @rb_size - Number of valid dwords in rb_buffer
* @bad_rb_buffer - Buffer that holds commands from the hanging context
* bad_rb_size - Number of valid dwords in bad_rb_buffer
+ * @good_rb_buffer - Buffer that holds commands from good contexts
+ * good_rb_size - Number of valid dwords in good_rb_buffer
* @last_valid_ctx_id - The last context from which commands were placed in
* ringbuffer before the GPU hung
+ * @step - Current fault tolerance step being executed
+ * @err_code - Fault tolerance error code
* @fault - Indicates whether the hang was caused due to a pagefault
+ * @start_of_replay_cmds - Offset in ringbuffer from where commands can be
+ * replayed during fault tolerance
+ * @replay_for_snapshot - Offset in ringbuffer where IB's can be saved for
+ * replaying with snapshot
*/
-struct adreno_recovery_data {
+struct adreno_ft_data {
unsigned int ib1;
unsigned int context_id;
unsigned int global_eop;
@@ -154,10 +171,32 @@
unsigned int rb_size;
unsigned int *bad_rb_buffer;
unsigned int bad_rb_size;
+ unsigned int *good_rb_buffer;
+ unsigned int good_rb_size;
unsigned int last_valid_ctx_id;
- int fault;
+ unsigned int status;
+ unsigned int ft_policy;
+ unsigned int err_code;
+ unsigned int start_of_replay_cmds;
+ unsigned int replay_for_snapshot;
};
+/* Fault Tolerance policy flags */
+#define KGSL_FT_DISABLE BIT(0)
+#define KGSL_FT_REPLAY BIT(1)
+#define KGSL_FT_SKIPIB BIT(2)
+#define KGSL_FT_SKIPFRAME BIT(3)
+#define KGSL_FT_TEMP_DISABLE BIT(4)
+#define KGSL_FT_DEFAULT_POLICY (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
+
+/* Pagefault policy flags */
+#define KGSL_FT_PAGEFAULT_INT_ENABLE 0x00000001
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE 0x00000002
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE 0x00000004
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT 0x00000008
+#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY (KGSL_FT_PAGEFAULT_INT_ENABLE + \
+ KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
+
extern struct adreno_gpudev adreno_a2xx_gpudev;
extern struct adreno_gpudev adreno_a3xx_gpudev;
@@ -179,8 +218,8 @@
extern const unsigned int a330_registers[];
extern const unsigned int a330_registers_count;
-extern unsigned int hang_detect_regs[];
-extern const unsigned int hang_detect_regs_count;
+extern unsigned int ft_detect_regs[];
+extern const unsigned int ft_detect_regs_count;
int adreno_idle(struct kgsl_device *device);
@@ -211,9 +250,12 @@
void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
int hang);
-int adreno_dump_and_recover(struct kgsl_device *device);
+int adreno_dump_and_exec_ft(struct kgsl_device *device);
-unsigned int adreno_hang_detect(struct kgsl_device *device,
+void adreno_dump_rb(struct kgsl_device *device, const void *buf,
+ size_t len, int start, int size);
+
+unsigned int adreno_ft_detect(struct kgsl_device *device,
unsigned int *prev_reg_val);
static inline int adreno_is_a200(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 08c800e..f1024d6 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -52,8 +52,8 @@
0x2240, 0x227e,
0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8,
0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7,
- 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356,
- 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
+ 0x22ff, 0x22ff, 0x2340, 0x2343,
+ 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d,
0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472,
0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef,
0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511,
@@ -61,8 +61,8 @@
0x25f0, 0x25f0,
0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce,
0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec,
- 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749,
- 0x2750, 0x2756, 0x2760, 0x2760, 0x300C, 0x300E, 0x301C, 0x301D,
+ 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743,
+ 0x300C, 0x300E, 0x301C, 0x301D,
0x302A, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031, 0x3034, 0x3036,
0x303C, 0x303C, 0x305E, 0x305F,
};
@@ -70,7 +70,7 @@
const unsigned int a3xx_registers_count = ARRAY_SIZE(a3xx_registers) / 2;
/* Removed the following HLSQ register ranges from being read during
- * recovery since reading the registers may cause the device to hang:
+ * fault tolerance since reading the registers may cause the device to hang:
*/
const unsigned int a3xx_hlsq_registers[] = {
0x0e00, 0x0e05, 0x0e0c, 0x0e0c, 0x0e22, 0x0e23,
@@ -2704,26 +2704,22 @@
static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = &adreno_dev->dev;
- unsigned int reg, val;
-
- /* Freeze the counter */
- adreno_regread(device, A3XX_RBBM_RBBM_CTL, ®);
- reg &= ~RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
- adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+ unsigned int val;
+ unsigned int ret = 0;
/* Read the value */
adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val);
- /* Reset the counter */
- reg |= RBBM_RBBM_CTL_RESET_PWR_CTR1;
- adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+ /* Return 0 for the first read */
+ if (adreno_dev->gpu_cycles != 0) {
+ if (val < adreno_dev->gpu_cycles)
+ ret = (0xFFFFFFFF - adreno_dev->gpu_cycles) + val;
+ else
+ ret = val - adreno_dev->gpu_cycles;
+ }
- /* Re-enable the counter */
- reg &= ~RBBM_RBBM_CTL_RESET_PWR_CTR1;
- reg |= RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
- adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
-
- return val;
+ adreno_dev->gpu_cycles = val;
+ return ret;
}
struct a3xx_vbif_data {
@@ -2824,10 +2820,6 @@
{ A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 },
/* Set up VBIF_ROUND_ROBIN_QOS_ARB */
{ A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 },
- /* Disable VBIF clock gating. This is to enable AXI running
- * higher frequency than GPU.
- */
- { A3XX_VBIF_CLKON, 1 },
{0, 0},
};
@@ -2848,6 +2840,7 @@
struct kgsl_device *device = &adreno_dev->dev;
struct a3xx_vbif_data *vbif = NULL;
int i;
+ unsigned int reg;
for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
@@ -2928,6 +2921,20 @@
adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
SP_FS_CFLOW_INSTRUCTIONS);
}
+
+ adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
+ SP_FS_FULL_ALU_INSTRUCTIONS);
+
+ /* Turn on the GPU busy counter and let it run free */
+
+ adreno_dev->gpu_cycles = 0;
+
+ adreno_regread(device, A3XX_RBBM_RBBM_CTL, ®);
+ reg |= RBBM_RBBM_CTL_RESET_PWR_CTR1;
+ adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
+ reg &= ~RBBM_RBBM_CTL_RESET_PWR_CTR1;
+ reg |= RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
+ adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
}
/* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 1989ff5..ef599e9 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -64,5 +64,33 @@
adreno_dev->fast_hang_detect = 1;
debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
&adreno_dev->fast_hang_detect);
+ /*
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+ adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
+ debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
+ &adreno_dev->ft_policy);
+ /* By default enable long IB detection */
+ adreno_dev->long_ib_detect = 1;
+ debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
+ &adreno_dev->long_ib_detect);
+ /*
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+ adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
+ debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
+ &adreno_dev->ft_pf_policy);
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b109e14..023b057 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -155,6 +155,8 @@
if (drawctxt == NULL)
return -ENOMEM;
+ drawctxt->pid = task_pid_nr(current);
+ strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
drawctxt->pagetable = pagetable;
drawctxt->bin_base_offset = 0;
drawctxt->id = context->id;
@@ -177,6 +179,9 @@
drawctxt->flags |= CTXT_FLAGS_USER_GENERATED_TS;
}
+ if (flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
+ drawctxt->flags |= CTXT_FLAGS_NO_FAULT_TOLERANCE;
+
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
if (ret)
goto err;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 65dbd4c..aba29ae 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,8 @@
#ifndef __ADRENO_DRAWCTXT_H
#define __ADRENO_DRAWCTXT_H
+#include <linux/sched.h>
+
#include "adreno_pm4types.h"
#include "a2xx_reg.h"
@@ -44,12 +46,16 @@
#define CTXT_FLAGS_TRASHSTATE BIT(10)
/* per context timestamps enabled */
#define CTXT_FLAGS_PER_CONTEXT_TS BIT(11)
-/* Context has caused a GPU hang and recovered properly */
-#define CTXT_FLAGS_GPU_HANG_RECOVERED BIT(12)
+/* Context has caused a GPU hang and fault tolerance successful */
+#define CTXT_FLAGS_GPU_HANG_FT BIT(12)
/* Context is being destroyed so dont save it */
#define CTXT_FLAGS_BEING_DESTROYED BIT(13)
/* User mode generated timestamps enabled */
#define CTXT_FLAGS_USER_GENERATED_TS BIT(14)
+/* Context skip till EOF */
+#define CTXT_FLAGS_SKIP_EOF BIT(15)
+/* Context no fault tolerance */
+#define CTXT_FLAGS_NO_FAULT_TOLERANCE BIT(16)
struct kgsl_device;
struct adreno_device;
@@ -82,8 +88,13 @@
};
struct adreno_context {
+ pid_t pid;
+ char pid_name[TASK_COMM_LEN];
unsigned int id;
+ unsigned int ib_gpu_time_used;
uint32_t flags;
+ uint32_t pagefault;
+ unsigned long pagefault_ts;
struct kgsl_pagetable *pagetable;
struct kgsl_memdesc gpustate;
unsigned int reg_restore[3];
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 2b9c286..5396196 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -305,7 +305,7 @@
#endif
}
-static void adreno_dump_rb(struct kgsl_device *device, const void *buf,
+void adreno_dump_rb(struct kgsl_device *device, const void *buf,
size_t len, int start, int size)
{
const uint32_t *ptr = buf;
@@ -702,7 +702,7 @@
" %08X\n", r1, r2, r3);
KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ",
- kgsl_mmu_get_ptsize());
+ kgsl_mmu_get_ptsize(&device->mmu));
kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1);
KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1);
@@ -729,6 +729,7 @@
unsigned int ts_processed = 0xdeaddead;
struct kgsl_context *context;
unsigned int context_id;
+ unsigned int rbbm_status;
static struct ib_list ib_list;
@@ -738,12 +739,16 @@
mb();
- msm_clk_dump_debug_info();
+ if (device->pm_dump_enable) {
+ msm_clk_dump_debug_info();
- if (adreno_is_a2xx(adreno_dev))
- adreno_dump_a2xx(device);
- else if (adreno_is_a3xx(adreno_dev))
- adreno_dump_a3xx(device);
+ if (adreno_is_a2xx(adreno_dev))
+ adreno_dump_a2xx(device);
+ else if (adreno_is_a3xx(adreno_dev))
+ adreno_dump_a3xx(device);
+ }
+
+ kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status);
pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
cur_pt_base = pt_base;
@@ -758,6 +763,18 @@
kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base);
kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz);
+ /* If postmortem dump is not enabled, dump minimal set and return */
+ if (!device->pm_dump_enable) {
+
+ KGSL_LOG_DUMP(device,
+ "STATUS %08X | IB1:%08X/%08X | IB2: %08X/%08X"
+ " | RPTR: %04X | WPTR: %04X\n",
+ rbbm_status, cp_ib1_base, cp_ib1_bufsz, cp_ib2_base,
+ cp_ib2_bufsz, cp_rb_rptr, cp_rb_wptr);
+
+ return 0;
+ }
+
kgsl_sharedmem_readl(&device->memstore,
(unsigned int *) &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -766,7 +783,7 @@
if (context) {
ts_processed = kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED);
- KGSL_LOG_DUMP(device, "CTXT: %d TIMESTM RTRD: %08X\n",
+ KGSL_LOG_DUMP(device, "FT CTXT: %d TIMESTM RTRD: %08X\n",
context->id, ts_processed);
} else
KGSL_LOG_DUMP(device, "BAD CTXT: %d\n", context_id);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 69b34fa..b746671 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -64,7 +64,7 @@
unsigned long wait_time;
unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
unsigned long wait_time_part;
- unsigned int prev_reg_val[hang_detect_regs_count];
+ unsigned int prev_reg_val[ft_detect_regs_count];
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -109,7 +109,7 @@
if (time_after(jiffies, wait_time_part)) {
wait_time_part = jiffies +
msecs_to_jiffies(KGSL_TIMEOUT_PART);
- if ((adreno_hang_detect(rb->device,
+ if ((adreno_ft_detect(rb->device,
prev_reg_val))){
KGSL_DRV_ERR(rb->device,
"Hang detected while waiting for freespace in"
@@ -129,7 +129,7 @@
continue;
err:
- if (!adreno_dump_and_recover(rb->device)) {
+ if (!adreno_dump_and_exec_ft(rb->device)) {
if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
KGSL_CTXT_WARN(rb->device,
"Context %p caused a gpu hang. Will not accept commands for context %d\n",
@@ -138,7 +138,7 @@
}
wait_time = jiffies + wait_timeout;
} else {
- /* GPU is hung and we cannot recover */
+ /* GPU is hung and fault tolerance failed */
BUG();
}
}
@@ -319,7 +319,7 @@
return 0;
}
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
+int adreno_ringbuffer_start(struct adreno_ringbuffer *rb)
{
int status;
/*cp_rb_cntl_u cp_rb_cntl; */
@@ -331,9 +331,6 @@
if (rb->flags & KGSL_FLAGS_STARTED)
return 0;
- if (init_ram)
- rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
sizeof(struct kgsl_rbmemptrs));
@@ -581,7 +578,7 @@
if (adreno_is_a2xx(adreno_dev))
total_sizedwords += 2; /* CP_WAIT_FOR_IDLE */
- total_sizedwords += 2; /* scratchpad ts for recovery */
+ total_sizedwords += 2; /* scratchpad ts for fault tolerance */
total_sizedwords += 3; /* sop timestamp */
total_sizedwords += 4; /* eop timestamp */
@@ -629,7 +626,7 @@
}
timestamp = rb->timestamp[context_id];
- /* scratchpad ts for recovery */
+ /* scratchpad ts for fault tolerance */
GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
@@ -756,6 +753,11 @@
GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
}
+ if (flags & KGSL_CMD_FLAGS_EOF) {
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_END_OF_FRAME_IDENTIFIER);
+ }
+
adreno_ringbuffer_submit(rb);
return timestamp;
@@ -999,20 +1001,12 @@
drawctxt = context->devctxt;
if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
- KGSL_CTXT_WARN(device, "Context %p caused a gpu hang.."
+ KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
" will not accept commands for context %d\n",
- drawctxt, drawctxt->id);
+ drawctxt->pid_name, drawctxt->id);
return -EDEADLK;
}
- cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
- GFP_KERNEL);
- if (!link) {
- KGSL_CORE_ERR("kzalloc(%d) failed\n",
- sizeof(unsigned int) * (numibs * 3 + 4));
- return -ENOMEM;
- }
-
/*When preamble is enabled, the preamble buffer with state restoration
commands are stored in the first node of the IB chain. We can skip that
if a context switch hasn't occured */
@@ -1021,6 +1015,27 @@
adreno_dev->drawctxt_active == drawctxt)
start_index = 1;
+ if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
+ KGSL_CTXT_ERR(device,
+ "proc %s triggered fault tolerance"
+ " skipping commands for context till EOF %d\n",
+ drawctxt->pid_name, drawctxt->id);
+ if (flags & KGSL_CMD_FLAGS_EOF)
+ drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
+ if (start_index)
+ numibs = 1;
+ else
+ numibs = 0;
+ }
+
+ cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
+ GFP_KERNEL);
+ if (!link) {
+ KGSL_CORE_ERR("kzalloc(%d) failed\n",
+ sizeof(unsigned int) * (numibs * 3 + 4));
+ return -ENOMEM;
+ }
+
if (!start_index) {
*cmds++ = cp_nop_packet(1);
*cmds++ = KGSL_START_OF_IB_IDENTIFIER;
@@ -1060,7 +1075,7 @@
*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
drawctxt,
- 0,
+ (flags & KGSL_CMD_FLAGS_EOF),
&link[0], (cmds - link), *timestamp);
#ifdef CONFIG_MSM_KGSL_CFF_DUMP
@@ -1072,173 +1087,21 @@
adreno_idle(device);
#endif
- /* If context hung and recovered then return error so that the
- * application may handle it */
-
- ret = (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED) ?
- -EDEADLK : 0;
+ /*
+ * If context hung and recovered then return error so that the
+ * application may handle it
+ */
+ if (drawctxt->flags & CTXT_FLAGS_GPU_HANG_FT) {
+ drawctxt->flags &= ~CTXT_FLAGS_GPU_HANG_FT;
+ ret = -EPROTO;
+ } else
+ ret = 0;
done:
kfree(link);
return ret;
}
-static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
- unsigned int *ptr,
- bool inc)
-{
- int status = -EINVAL;
- unsigned int val1;
- unsigned int size = rb->buffer_desc.size;
- unsigned int start_ptr = *ptr;
-
- while ((start_ptr / sizeof(unsigned int)) != rb->wptr) {
- if (inc)
- start_ptr = adreno_ringbuffer_inc_wrapped(start_ptr,
- size);
- else
- start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
- size);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
- if (KGSL_CMD_IDENTIFIER == val1) {
- if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
- start_ptr = adreno_ringbuffer_dec_wrapped(
- start_ptr, size);
- *ptr = start_ptr;
- status = 0;
- break;
- }
- }
- return status;
-}
-
-static int _find_cmd_seq_after_eop_ts(struct adreno_ringbuffer *rb,
- unsigned int *rb_rptr,
- unsigned int global_eop,
- bool inc)
-{
- int status = -EINVAL;
- unsigned int temp_rb_rptr = *rb_rptr;
- unsigned int size = rb->buffer_desc.size;
- unsigned int val[3];
- int i = 0;
- bool check = false;
-
- if (inc && temp_rb_rptr / sizeof(unsigned int) != rb->wptr)
- return status;
-
- do {
- /* when decrementing we need to decrement first and
- * then read make sure we cover all the data */
- if (!inc)
- temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
- temp_rb_rptr, size);
- kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
- temp_rb_rptr);
-
- if (check && ((inc && val[i] == global_eop) ||
- (!inc && (val[i] ==
- cp_type3_packet(CP_MEM_WRITE, 2) ||
- val[i] == CACHE_FLUSH_TS)))) {
- /* decrement i, i.e i = (i - 1 + 3) % 3 if
- * we are going forward, else increment i */
- i = (i + 2) % 3;
- if (val[i] == rb->device->memstore.gpuaddr +
- KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp)) {
- int j = ((i + 2) % 3);
- if ((inc && (val[j] == CACHE_FLUSH_TS ||
- val[j] == cp_type3_packet(
- CP_MEM_WRITE, 2))) ||
- (!inc && val[j] == global_eop)) {
- /* Found the global eop */
- status = 0;
- break;
- }
- }
- /* if no match found then increment i again
- * since we decremented before matching */
- i = (i + 1) % 3;
- }
- if (inc)
- temp_rb_rptr = adreno_ringbuffer_inc_wrapped(
- temp_rb_rptr, size);
-
- i = (i + 1) % 3;
- if (2 == i)
- check = true;
- } while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr);
- /* temp_rb_rptr points to the command stream after global eop,
- * move backward till the start of command sequence */
- if (!status) {
- status = _find_start_of_cmd_seq(rb, &temp_rb_rptr, false);
- if (!status) {
- *rb_rptr = temp_rb_rptr;
- KGSL_DRV_ERR(rb->device,
- "Offset of cmd sequence after eop timestamp: 0x%x\n",
- temp_rb_rptr / sizeof(unsigned int));
- }
- }
- if (status)
- KGSL_DRV_ERR(rb->device,
- "Failed to find the command sequence after eop timestamp\n");
- return status;
-}
-
-static int _find_hanging_ib_sequence(struct adreno_ringbuffer *rb,
- unsigned int *rb_rptr,
- unsigned int ib1)
-{
- int status = -EINVAL;
- unsigned int temp_rb_rptr = *rb_rptr;
- unsigned int size = rb->buffer_desc.size;
- unsigned int val[2];
- int i = 0;
- bool check = false;
- bool ctx_switch = false;
-
- while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
- kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
-
- if (check && val[i] == ib1) {
- /* decrement i, i.e i = (i - 1 + 2) % 2 */
- i = (i + 1) % 2;
- if (adreno_cmd_is_ib(val[i])) {
- /* go till start of command sequence */
- status = _find_start_of_cmd_seq(rb,
- &temp_rb_rptr, false);
- KGSL_DRV_ERR(rb->device,
- "Found the hanging IB at offset 0x%x\n",
- temp_rb_rptr / sizeof(unsigned int));
- break;
- }
- /* if no match the increment i since we decremented
- * before checking */
- i = (i + 1) % 2;
- }
- /* Make sure you do not encounter a context switch twice, we can
- * encounter it once for the bad context as the start of search
- * can point to the context switch */
- if (val[i] == KGSL_CONTEXT_TO_MEM_IDENTIFIER) {
- if (ctx_switch) {
- KGSL_DRV_ERR(rb->device,
- "Context switch encountered before bad "
- "IB found\n");
- break;
- }
- ctx_switch = true;
- }
- i = (i + 1) % 2;
- if (1 == i)
- check = true;
- temp_rb_rptr = adreno_ringbuffer_inc_wrapped(temp_rb_rptr,
- size);
- }
- if (!status)
- *rb_rptr = temp_rb_rptr;
- return status;
-}
-
static void _turn_preamble_on_for_ib_seq(struct adreno_ringbuffer *rb,
unsigned int rb_rptr)
{
@@ -1261,7 +1124,7 @@
kgsl_sharedmem_writel(&rb->buffer_desc,
temp_rb_rptr, cp_nop_packet(1));
}
- KGSL_DRV_ERR(rb->device,
+ KGSL_FT_INFO(rb->device,
"Turned preamble on at offset 0x%x\n",
temp_rb_rptr / 4);
break;
@@ -1283,21 +1146,41 @@
}
}
-static void _copy_valid_rb_content(struct adreno_ringbuffer *rb,
- unsigned int rb_rptr, unsigned int *temp_rb_buffer,
- int *rb_size, unsigned int *bad_rb_buffer,
- int *bad_rb_size,
- int *last_valid_ctx_id)
+void adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
+ struct adreno_ft_data *ft_data)
{
- unsigned int good_rb_idx = 0, cmd_start_idx = 0;
+ struct kgsl_device *device = rb->device;
+ unsigned int rb_rptr = ft_data->start_of_replay_cmds;
+ unsigned int good_rb_idx = 0, bad_rb_idx = 0, temp_rb_idx = 0;
+ unsigned int last_good_cmd_end_idx = 0, last_bad_cmd_end_idx = 0;
+ unsigned int cmd_start_idx = 0;
unsigned int val1 = 0;
- struct kgsl_context *k_ctxt;
- struct adreno_context *a_ctxt;
- unsigned int bad_rb_idx = 0;
int copy_rb_contents = 0;
unsigned int temp_rb_rptr;
+ struct kgsl_context *k_ctxt;
+ struct adreno_context *a_ctxt;
unsigned int size = rb->buffer_desc.size;
- unsigned int good_cmd_start_idx = 0;
+ unsigned int *temp_rb_buffer = ft_data->rb_buffer;
+ int *rb_size = &ft_data->rb_size;
+ unsigned int *bad_rb_buffer = ft_data->bad_rb_buffer;
+ int *bad_rb_size = &ft_data->bad_rb_size;
+ unsigned int *good_rb_buffer = ft_data->good_rb_buffer;
+ int *good_rb_size = &ft_data->good_rb_size;
+
+ /*
+ * If the start index from where commands need to be copied is invalid
+ * then no need to save off any commands
+ */
+ if (0xFFFFFFFF == ft_data->start_of_replay_cmds)
+ return;
+
+ k_ctxt = idr_find(&device->context_idr, ft_data->context_id);
+ if (k_ctxt) {
+ a_ctxt = k_ctxt->devctxt;
+ if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
+ _turn_preamble_on_for_ib_seq(rb, rb_rptr);
+ }
+ k_ctxt = NULL;
/* Walk the rb from the context switch. Omit any commands
* for an invalid context. */
@@ -1307,9 +1190,11 @@
if (KGSL_CMD_IDENTIFIER == val1) {
/* Start is the NOP dword that comes before
* KGSL_CMD_IDENTIFIER */
- cmd_start_idx = bad_rb_idx - 1;
- if (copy_rb_contents)
- good_cmd_start_idx = good_rb_idx - 1;
+ cmd_start_idx = temp_rb_idx - 1;
+ if ((copy_rb_contents) && (good_rb_idx))
+ last_good_cmd_end_idx = good_rb_idx - 1;
+ if ((!copy_rb_contents) && (bad_rb_idx))
+ last_bad_cmd_end_idx = bad_rb_idx - 1;
}
/* check for context switch indicator */
@@ -1335,86 +1220,48 @@
!(a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) ||
!k_ctxt)) {
for (temp_idx = cmd_start_idx;
- temp_idx < bad_rb_idx;
+ temp_idx < temp_rb_idx;
temp_idx++)
- temp_rb_buffer[good_rb_idx++] =
- bad_rb_buffer[temp_idx];
- *last_valid_ctx_id = val2;
+ good_rb_buffer[good_rb_idx++] =
+ temp_rb_buffer[temp_idx];
+ ft_data->last_valid_ctx_id = val2;
copy_rb_contents = 1;
+ /* remove the good commands from bad buffer */
+ bad_rb_idx = last_bad_cmd_end_idx;
} else if (copy_rb_contents && k_ctxt &&
(a_ctxt->flags & CTXT_FLAGS_GPU_HANG)) {
- /* If we are changing to bad context then remove
- * the dwords we copied for this sequence from
- * the good buffer */
- good_rb_idx = good_cmd_start_idx;
+
+ /* If we are changing back to a bad context
+ * from good ctxt and were not copying commands
+ * to bad ctxt then copy over commands to
+ * the bad context */
+ for (temp_idx = cmd_start_idx;
+ temp_idx < temp_rb_idx;
+ temp_idx++)
+ bad_rb_buffer[bad_rb_idx++] =
+ temp_rb_buffer[temp_idx];
+ /* If we are changing to bad context then
+ * remove the dwords we copied for this
+ * sequence from the good buffer */
+ good_rb_idx = last_good_cmd_end_idx;
copy_rb_contents = 0;
}
}
}
if (copy_rb_contents)
- temp_rb_buffer[good_rb_idx++] = val1;
- /* Copy both good and bad commands for replay to the bad
- * buffer */
- bad_rb_buffer[bad_rb_idx++] = val1;
+ good_rb_buffer[good_rb_idx++] = val1;
+ else
+ bad_rb_buffer[bad_rb_idx++] = val1;
+
+ /* Copy both good and bad commands to temp buffer */
+ temp_rb_buffer[temp_rb_idx++] = val1;
rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr, size);
}
- *rb_size = good_rb_idx;
+ *good_rb_size = good_rb_idx;
*bad_rb_size = bad_rb_idx;
-}
-
-int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
- struct adreno_recovery_data *rec_data)
-{
- int status;
- struct kgsl_device *device = rb->device;
- unsigned int rb_rptr = rb->wptr * sizeof(unsigned int);
- struct kgsl_context *context;
- struct adreno_context *adreno_context;
-
- context = idr_find(&device->context_idr, rec_data->context_id);
-
- /* Look for the command stream that is right after the global eop */
- status = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
- rec_data->global_eop + 1, false);
- if (status)
- goto done;
-
- if (context) {
- adreno_context = context->devctxt;
-
- if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
- if (rec_data->ib1) {
- status = _find_hanging_ib_sequence(rb, &rb_rptr,
- rec_data->ib1);
- if (status)
- goto copy_rb_contents;
- }
- _turn_preamble_on_for_ib_seq(rb, rb_rptr);
- } else {
- status = -EINVAL;
- }
- }
-
-copy_rb_contents:
- _copy_valid_rb_content(rb, rb_rptr, rec_data->rb_buffer,
- &rec_data->rb_size,
- rec_data->bad_rb_buffer,
- &rec_data->bad_rb_size,
- &rec_data->last_valid_ctx_id);
- /* If we failed to get the hanging IB sequence then we cannot execute
- * commands from the bad context or preambles not supported */
- if (status) {
- rec_data->bad_rb_size = 0;
- status = 0;
- }
- /* If there is no context then that means there are no commands for
- * good case */
- if (!context)
- rec_data->rb_size = 0;
-done:
- return status;
+ *rb_size = temp_rb_idx;
}
void
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e87b506..e563ec7 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -27,7 +27,7 @@
struct kgsl_device;
struct kgsl_device_private;
-struct adreno_recovery_data;
+struct adreno_ft_data;
#define GSL_RB_MEMPTRS_SCRATCH_COUNT 8
struct kgsl_rbmemptrs {
@@ -97,8 +97,7 @@
int adreno_ringbuffer_init(struct kgsl_device *device);
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb,
- unsigned int init_ram);
+int adreno_ringbuffer_start(struct adreno_ringbuffer *rb);
void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb);
@@ -114,8 +113,8 @@
void kgsl_cp_intrcallback(struct kgsl_device *device);
-int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
- struct adreno_recovery_data *rec_data);
+void adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
+ struct adreno_ft_data *ft_data);
void
adreno_ringbuffer_restore(struct adreno_ringbuffer *rb, unsigned int *rb_buff,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index c8229e7..a76ed87 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -162,6 +162,12 @@
static unsigned int sp_fs_pvt_mem_addr;
/*
+ * Cached value of SP_VS_OBJ_START_REG and SP_FS_OBJ_START_REG.
+ */
+static unsigned int sp_vs_obj_start_reg;
+static unsigned int sp_fs_obj_start_reg;
+
+/*
* Each load state block has two possible types. Each type has a different
* number of dwords per unit. Use this handy lookup table to make sure
* we dump the right amount of data from the indirect buffer
@@ -373,6 +379,26 @@
sp_fs_pvt_mem_addr = 0;
}
+ if (sp_vs_obj_start_reg) {
+ ret = kgsl_snapshot_get_object(device, ptbase,
+ sp_vs_obj_start_reg & 0xFFFFFFE0, 0,
+ SNAPSHOT_GPU_OBJECT_GENERIC);
+ if (ret < 0)
+ return -EINVAL;
+ snapshot_frozen_objsize += ret;
+ sp_vs_obj_start_reg = 0;
+ }
+
+ if (sp_fs_obj_start_reg) {
+ ret = kgsl_snapshot_get_object(device, ptbase,
+ sp_fs_obj_start_reg & 0xFFFFFFE0, 0,
+ SNAPSHOT_GPU_OBJECT_GENERIC);
+ if (ret < 0)
+ return -EINVAL;
+ snapshot_frozen_objsize += ret;
+ sp_fs_obj_start_reg = 0;
+ }
+
/* Finally: VBOs */
/* The number of active VBOs is stored in VFD_CONTROL_O[31:27] */
@@ -444,7 +470,7 @@
int offset = type0_pkt_offset(*ptr);
int i;
- for (i = 0; i < size; i++, offset++) {
+ for (i = 0; i < size - 1; i++, offset++) {
/* Visiblity stream buffer */
@@ -505,6 +531,12 @@
case A3XX_SP_FS_PVT_MEM_ADDR_REG:
sp_fs_pvt_mem_addr = ptr[i + 1];
break;
+ case A3XX_SP_VS_OBJ_START_REG:
+ sp_vs_obj_start_reg = ptr[i + 1];
+ break;
+ case A3XX_SP_FS_OBJ_START_REG:
+ sp_fs_obj_start_reg = ptr[i + 1];
+ break;
}
}
}
@@ -786,6 +818,64 @@
return size + sizeof(*header);
}
+static int snapshot_capture_mem_list(struct kgsl_device *device, void *snapshot,
+ int remain, void *priv)
+{
+ struct kgsl_snapshot_replay_mem_list *header = snapshot;
+ struct kgsl_process_private *private;
+ unsigned int ptbase;
+ struct rb_node *node;
+ struct kgsl_mem_entry *entry = NULL;
+ int num_mem;
+ unsigned int *data = snapshot + sizeof(*header);
+
+ ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
+ mutex_lock(&kgsl_driver.process_mutex);
+ list_for_each_entry(private, &kgsl_driver.process_list, list) {
+ if (kgsl_mmu_pt_equal(&device->mmu, private->pagetable,
+ ptbase))
+ break;
+ }
+ mutex_unlock(&kgsl_driver.process_mutex);
+ if (!private) {
+ KGSL_DRV_ERR(device,
+ "Failed to get pointer to process private structure\n");
+ return 0;
+ }
+ /* We need to know the number of memory objects that the process has */
+ spin_lock(&private->mem_lock);
+ for (node = rb_first(&private->mem_rb), num_mem = 0; node; ) {
+ entry = rb_entry(node, struct kgsl_mem_entry, node);
+ node = rb_next(&entry->node);
+ num_mem++;
+ }
+
+ if (remain < ((num_mem * 3 * sizeof(unsigned int)) +
+ sizeof(*header))) {
+ KGSL_DRV_ERR(device,
+ "snapshot: Not enough memory for the mem list section");
+ spin_unlock(&private->mem_lock);
+ return 0;
+ }
+ header->num_entries = num_mem;
+ header->ptbase = ptbase;
+ /*
+ * Walk throught the memory list and store the
+ * tuples(gpuaddr, size, memtype) in snapshot
+ */
+ for (node = rb_first(&private->mem_rb); node; ) {
+ entry = rb_entry(node, struct kgsl_mem_entry, node);
+ node = rb_next(&entry->node);
+
+ *data++ = entry->memdesc.gpuaddr;
+ *data++ = entry->memdesc.size;
+ *data++ = (entry->memdesc.priv & KGSL_MEMTYPE_MASK) >>
+ KGSL_MEMTYPE_SHIFT;
+ }
+ spin_unlock(&private->mem_lock);
+ return sizeof(*header) + (num_mem * 3 * sizeof(unsigned int));
+}
+
/* Snapshot the memory for an indirect buffer */
static int snapshot_ib(struct kgsl_device *device, void *snapshot,
int remain, void *priv)
@@ -889,6 +979,13 @@
snapshot, remain, snapshot_rb, NULL);
/*
+ * Add a section that lists (gpuaddr, size, memtype) tuples of the
+ * hanging process
+ */
+ snapshot = kgsl_snapshot_add_section(device,
+ KGSL_SNAPSHOT_SECTION_MEMLIST, snapshot, remain,
+ snapshot_capture_mem_list, NULL);
+ /*
* Make sure that the last IB1 that was being executed is dumped.
* Since this was the last IB1 that was processed, we should have
* already added it to the list during the ringbuffer parse but we
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e2869d4..af25a3f 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -671,9 +671,10 @@
if (kgsl_mmu_enabled())
{
unsigned long pt_name;
+ struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu;
pt_name = task_tgid_nr(current);
- private->pagetable = kgsl_mmu_getpagetable(pt_name);
+ private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name);
if (private->pagetable == NULL) {
kfree(private);
private = NULL;
@@ -821,12 +822,14 @@
kgsl_sharedmem_set(&device->memstore, 0, 0,
device->memstore.size);
- result = device->ftbl->start(device, true);
-
- if (result) {
- mutex_unlock(&device->mutex);
+ result = device->ftbl->init(device);
+ if (result)
goto err_freedevpriv;
- }
+
+ result = device->ftbl->start(device);
+ if (result)
+ goto err_freedevpriv;
+
kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
}
device->open_count++;
@@ -856,8 +859,8 @@
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
}
- mutex_unlock(&device->mutex);
err_freedevpriv:
+ mutex_unlock(&device->mutex);
filep->private_data = NULL;
kfree(dev_priv);
err_pmruntime:
@@ -872,7 +875,7 @@
{
struct rb_node *node = private->mem_rb.rb_node;
- if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
+ if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
return NULL;
while (node != NULL) {
@@ -925,7 +928,7 @@
struct rb_node *node = private->mem_rb.rb_node;
- if (!kgsl_mmu_gpuaddr_in_range(gpuaddr))
+ if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr))
return 0;
/* don't overflow */
@@ -1193,7 +1196,9 @@
}
for (i = 0; i < param->numibs; i++) {
- if (!kgsl_mmu_gpuaddr_in_range(ibdesc[i].gpuaddr)) {
+ struct kgsl_pagetable *pt = dev_priv->process_priv->pagetable;
+
+ if (!kgsl_mmu_gpuaddr_in_range(pt, ibdesc[i].gpuaddr)) {
result = -ERANGE;
KGSL_DRV_ERR(dev_priv->device,
"invalid ib base GPU virtual addr %x\n",
@@ -1767,13 +1772,6 @@
return -ENOMEM;
}
-static inline int
-can_use_cpu_map(void)
-{
- return (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
- && kgsl_mmu_is_perprocess());
-}
-
static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -1805,7 +1803,7 @@
| KGSL_MEMFLAGS_USE_CPU_MAP;
entry->memdesc.flags = param->flags;
- if (!can_use_cpu_map())
+ if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
switch (memtype) {
@@ -2092,7 +2090,7 @@
struct kgsl_mem_entry *entry = NULL;
int result;
- if (!can_use_cpu_map())
+ if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu))
param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP;
result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags);
@@ -3047,21 +3045,21 @@
kgsl_idle(device);
}
- KGSL_LOG_DUMP(device, "|%s| Dump Started\n", device->name);
- KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
+
+ if (device->pm_dump_enable) {
+
+ KGSL_LOG_DUMP(device,
+ "POWER: NAP ALLOWED = %d | START_STOP_SLEEP_WAKE = %d\n"
+ , pwr->nap_allowed, pwr->strtstp_sleepwake);
+
+ KGSL_LOG_DUMP(device,
+ "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
pwr->power_flags, pwr->active_pwrlevel);
- KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
- pwr->interval_timeout);
+ KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
+ pwr->interval_timeout);
- KGSL_LOG_DUMP(device, "POWER: NAP ALLOWED = %d | START_STOP_SLEEP_WAKE = %d\n",
- pwr->nap_allowed, pwr->strtstp_sleepwake);
-
- KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
- kgsl_get_clkrate(pwr->grp_clks[0]));
-
- KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
- kgsl_get_clkrate(pwr->ebi1_clk));
+ }
/* Disable the idle timer so we don't get interrupted */
del_timer_sync(&device->idle_timer);
@@ -3089,7 +3087,7 @@
/* On a manual trigger, turn on the interrupts and put
the clocks to sleep. They will recover themselves
on the next event. For a hang, leave things as they
- are until recovery kicks in. */
+ are until fault tolerance kicks in. */
if (manual) {
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
@@ -3099,8 +3097,6 @@
kgsl_pwrctrl_sleep(device);
}
- KGSL_LOG_DUMP(device, "|%s| Dump Finished\n", device->name);
-
return 0;
}
EXPORT_SYMBOL(kgsl_postmortem_dump);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 76998db..9dfda32 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -70,6 +70,20 @@
return 0;
}
+static int pm_enabled_set(void *data, u64 val)
+{
+ struct kgsl_device *device = data;
+ device->pm_dump_enable = val;
+ return 0;
+}
+
+static int pm_enabled_get(void *data, u64 *val)
+{
+ struct kgsl_device *device = data;
+ *val = device->pm_dump_enable;
+ return 0;
+}
+
DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
pm_regs_enabled_get,
@@ -79,6 +93,10 @@
pm_ib_enabled_get,
pm_ib_enabled_set, "%llu\n");
+DEFINE_SIMPLE_ATTRIBUTE(pm_enabled_fops,
+ pm_enabled_get,
+ pm_enabled_set, "%llu\n");
+
static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
{
*log_val = min((unsigned int)val, (unsigned int)KGSL_LOG_LEVEL_MAX);
@@ -105,6 +123,7 @@
KGSL_DEBUGFS_LOG(ctxt_log);
KGSL_DEBUGFS_LOG(mem_log);
KGSL_DEBUGFS_LOG(pwr_log);
+KGSL_DEBUGFS_LOG(ft_log);
static int memfree_hist_print(struct seq_file *s, void *unused)
{
@@ -166,6 +185,7 @@
device->drv_log = KGSL_LOG_LEVEL_DEFAULT;
device->mem_log = KGSL_LOG_LEVEL_DEFAULT;
device->pwr_log = KGSL_LOG_LEVEL_DEFAULT;
+ device->ft_log = KGSL_LOG_LEVEL_DEFAULT;
debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device,
&cmd_log_fops);
@@ -179,6 +199,8 @@
&pwr_log_fops);
debugfs_create_file("memfree_history", 0444, device->d_debugfs, device,
&memfree_hist_fops);
+ debugfs_create_file("log_level_ft", 0644, device->d_debugfs, device,
+ &ft_log_fops);
/* Create postmortem dump control files */
@@ -193,6 +215,9 @@
&pm_regs_enabled_fops);
debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
&pm_ib_enabled_fops);
+ device->pm_dump_enable = 0;
+ debugfs_create_file("enable", 0644, pm_d_debugfs, device,
+ &pm_enabled_fops);
}
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 66390fc..37b5730 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -24,9 +24,10 @@
#include "kgsl_pwrscale.h"
#include <linux/sync.h>
-#define KGSL_TIMEOUT_NONE 0
-#define KGSL_TIMEOUT_DEFAULT 0xFFFFFFFF
-#define KGSL_TIMEOUT_PART 50 /* 50 msec */
+#define KGSL_TIMEOUT_NONE 0
+#define KGSL_TIMEOUT_DEFAULT 0xFFFFFFFF
+#define KGSL_TIMEOUT_PART 50 /* 50 msec */
+#define KGSL_TIMEOUT_LONG_IB_DETECTION 2000 /* 2 sec*/
#define FIRST_TIMEOUT (HZ / 2)
@@ -46,7 +47,7 @@
#define KGSL_STATE_SLEEP 0x00000008
#define KGSL_STATE_SUSPEND 0x00000010
#define KGSL_STATE_HUNG 0x00000020
-#define KGSL_STATE_DUMP_AND_RECOVER 0x00000040
+#define KGSL_STATE_DUMP_AND_FT 0x00000040
#define KGSL_STATE_SLUMBER 0x00000080
#define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK 0x1000000
@@ -72,7 +73,8 @@
int (*idle) (struct kgsl_device *device);
unsigned int (*isidle) (struct kgsl_device *device);
int (*suspend_context) (struct kgsl_device *device);
- int (*start) (struct kgsl_device *device, unsigned int init_ram);
+ int (*init) (struct kgsl_device *device);
+ int (*start) (struct kgsl_device *device);
int (*stop) (struct kgsl_device *device);
int (*getproperty) (struct kgsl_device *device,
enum kgsl_property_type type, void *value,
@@ -185,7 +187,7 @@
wait_queue_head_t wait_queue;
struct workqueue_struct *work_queue;
struct device *parentdev;
- struct completion recovery_gate;
+ struct completion ft_gate;
struct dentry *d_debugfs;
struct idr context_idr;
struct early_suspend display_off;
@@ -211,6 +213,8 @@
int drv_log;
int mem_log;
int pwr_log;
+ int ft_log;
+ int pm_dump_enable;
struct kgsl_pwrscale pwrscale;
struct kobject pwrscale_kobj;
struct work_struct ts_expired_ws;
@@ -230,7 +234,7 @@
#define KGSL_DEVICE_COMMON_INIT(_dev) \
.hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\
.suspend_gate = COMPLETION_INITIALIZER((_dev).suspend_gate),\
- .recovery_gate = COMPLETION_INITIALIZER((_dev).recovery_gate),\
+ .ft_gate = COMPLETION_INITIALIZER((_dev).ft_gate),\
.idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\
kgsl_idle_check),\
.ts_expired_ws = __WORK_INITIALIZER((_dev).ts_expired_ws,\
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 9a1a431..5cc0dff 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -19,9 +19,11 @@
#include "kgsl.h"
#include "kgsl_mmu.h"
+#include "kgsl_gpummu.h"
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
#include "kgsl_trace.h"
+#include "adreno.h"
#define KGSL_PAGETABLE_SIZE \
ALIGN(KGSL_PAGETABLE_ENTRIES(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE) * \
@@ -363,10 +365,9 @@
return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
}
-void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
+void kgsl_gpummu_destroy_pagetable(struct kgsl_pagetable *pt)
{
- struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *)
- mmu_specific_pt;
+ struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
kgsl_ptpool_free((struct kgsl_ptpool *)kgsl_driver.ptpool,
gpummu_pt->base.hostptr);
@@ -403,11 +404,22 @@
{
unsigned int reg;
unsigned int ptbase;
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
+ unsigned int no_page_fault_log = 0;
- kgsl_regread(mmu->device, MH_MMU_PAGE_FAULT, ®);
- kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
+ device = mmu->device;
+ adreno_dev = ADRENO_DEVICE(device);
- KGSL_MEM_CRIT(mmu->device,
+ kgsl_regread(device, MH_MMU_PAGE_FAULT, ®);
+ kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+
+
+ if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE)
+ no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, reg);
+
+ if (!no_page_fault_log)
+ KGSL_MEM_CRIT(mmu->device,
"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
reg & ~(PAGE_SIZE - 1),
kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
@@ -516,6 +528,11 @@
*/
int status = 0;
+ mmu->pt_base = KGSL_PAGETABLE_BASE;
+ mmu->pt_size = CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
+ mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT;
+ mmu->use_cpu_map = false;
+
/* sub-client MMU lookups require address translation */
if ((mmu->config & ~0x1) > 0) {
/*make sure virtual address range is a multiple of 64Kb */
@@ -572,7 +589,7 @@
if (mmu->defaultpagetable == NULL)
mmu->defaultpagetable =
- kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+ kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
/* Return error if the default pagetable doesn't exist */
if (mmu->defaultpagetable == NULL)
@@ -592,14 +609,14 @@
}
static int
-kgsl_gpummu_unmap(void *mmu_specific_pt,
+kgsl_gpummu_unmap(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int *tlb_flags)
{
unsigned int numpages;
unsigned int pte, ptefirst, ptelast, superpte;
unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
- struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
+ struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
/* All GPU addresses as assigned are page aligned, but some
functions purturb the gpuaddr with an offset, so apply the
@@ -641,13 +658,13 @@
GSL_TLBFLUSH_FILTER_ISDIRTY((_p) / GSL_PT_SUPER_PTE))
static int
-kgsl_gpummu_map(void *mmu_specific_pt,
+kgsl_gpummu_map(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int protflags,
unsigned int *tlb_flags)
{
unsigned int pte;
- struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt;
+ struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
struct scatterlist *s;
int flushtlb = 0;
int i;
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index cc01d37..f327c04 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -21,6 +21,7 @@
#include <mach/socinfo.h>
#include <mach/msm_iomap.h>
#include <mach/board.h>
+#include <mach/iommu_domains.h>
#include <stddef.h>
#include "kgsl.h"
@@ -283,10 +284,16 @@
struct kgsl_iommu_device *iommu_dev;
unsigned int ptbase, fsr;
unsigned int pid;
-
struct _mem_entry prev, next;
unsigned int fsynr0, fsynr1;
int write;
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
+ unsigned int no_page_fault_log = 0;
+ unsigned int curr_context_id = 0;
+ unsigned int curr_global_ts = 0;
+ static struct adreno_context *curr_context;
+ static struct kgsl_context *context;
ret = get_iommu_unit(dev, &mmu, &iommu_unit);
if (ret)
@@ -298,6 +305,8 @@
goto done;
}
iommu = mmu->priv;
+ device = mmu->device;
+ adreno_dev = ADRENO_DEVICE(device);
ptbase = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
iommu_dev->ctx_id, TTBR0);
@@ -324,27 +333,55 @@
iommu_dev->ctx_id, fsr, fsynr0, fsynr1,
write ? "write" : "read");
- _check_if_freed(iommu_dev, addr, pid);
+ if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE)
+ no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, addr);
- KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n");
+ if (!no_page_fault_log) {
+ KGSL_MEM_CRIT(iommu_dev->kgsldev,
+ "GPU PAGE FAULT: addr = %lX pid = %d\n",
+ addr, kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase));
+ KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
+ iommu_dev->ctx_id, fsr);
- _find_mem_entries(mmu, addr, ptbase, &prev, &next);
+ _check_if_freed(iommu_dev, addr, pid);
- if (prev.gpuaddr)
- _print_entry(iommu_dev->kgsldev, &prev);
- else
- KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n");
+ KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n");
- KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr);
+ _find_mem_entries(mmu, addr, ptbase, &prev, &next);
- if (next.gpuaddr != 0xFFFFFFFF)
- _print_entry(iommu_dev->kgsldev, &next);
- else
- KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n");
+ if (prev.gpuaddr)
+ _print_entry(iommu_dev->kgsldev, &prev);
+ else
+ KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n");
+
+ KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr);
+
+ if (next.gpuaddr != 0xFFFFFFFF)
+ _print_entry(iommu_dev->kgsldev, &next);
+ else
+ KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n");
+
+ }
mmu->fault = 1;
iommu_dev->fault = 1;
+ kgsl_sharedmem_readl(&device->memstore, &curr_context_id,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
+ context = idr_find(&device->context_idr, curr_context_id);
+ if (context != NULL)
+ curr_context = context->devctxt;
+
+ kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp));
+
+ /*
+ * Store pagefault's timestamp in adreno context,
+ * this information will be used in GFT
+ */
+ curr_context->pagefault = 1;
+ curr_context->pagefault_ts = curr_global_ts;
+
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
write ? "write" : "read");
@@ -355,7 +392,8 @@
* the GPU and trigger a snapshot. To stall the transaction return
* EBUSY error.
*/
- ret = -EBUSY;
+ if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
+ ret = -EBUSY;
done:
return ret;
}
@@ -566,9 +604,9 @@
*
* Return - void
*/
-static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
+static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
{
- struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+ struct kgsl_iommu_pt *iommu_pt = pt->priv;
if (iommu_pt->domain)
iommu_domain_free(iommu_pt->domain);
kfree(iommu_pt);
@@ -583,8 +621,20 @@
*/
void *kgsl_iommu_create_pagetable(void)
{
+ int domain_num;
struct kgsl_iommu_pt *iommu_pt;
+ struct msm_iova_partition kgsl_partition = {
+ .start = 0,
+ .size = 0xFFFFFFFF,
+ };
+ struct msm_iova_layout kgsl_layout = {
+ .partitions = &kgsl_partition,
+ .npartitions = 1,
+ .client_name = "kgsl",
+ .domain_flags = 0,
+ };
+
iommu_pt = kzalloc(sizeof(struct kgsl_iommu_pt), GFP_KERNEL);
if (!iommu_pt) {
KGSL_CORE_ERR("kzalloc(%d) failed\n",
@@ -593,18 +643,17 @@
}
/* L2 redirect is not stable on IOMMU v1 */
if (msm_soc_version_supports_iommu_v0())
- iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
- MSM_IOMMU_DOMAIN_PT_CACHEABLE);
- else
- iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
- 0);
- if (!iommu_pt->domain) {
+ kgsl_layout.domain_flags = MSM_IOMMU_DOMAIN_PT_CACHEABLE;
+
+ domain_num = msm_register_domain(&kgsl_layout);
+ if (domain_num >= 0) {
+ iommu_pt->domain = msm_get_iommu_domain(domain_num);
+ iommu_set_fault_handler(iommu_pt->domain,
+ kgsl_iommu_fault_handler, NULL);
+ } else {
KGSL_CORE_ERR("Failed to create iommu domain\n");
kfree(iommu_pt);
return NULL;
- } else {
- iommu_set_fault_handler(iommu_pt->domain,
- kgsl_iommu_fault_handler, NULL);
}
return iommu_pt;
@@ -780,7 +829,7 @@
if (KGSL_DEVICE_3D0 != mmu->device->id ||
!msm_soc_version_supports_iommu_v0() ||
- !kgsl_mmu_is_perprocess() ||
+ !kgsl_mmu_is_perprocess(mmu) ||
iommu->sync_lock_vars)
return 0;
@@ -821,7 +870,7 @@
uint32_t page_offset = 0;
if (!msm_soc_version_supports_iommu_v0() ||
- !kgsl_mmu_is_perprocess())
+ !kgsl_mmu_is_perprocess(mmu))
return status;
/*
@@ -1219,6 +1268,32 @@
if (status)
goto done;
+ /* We presently do not support per-process for IOMMU-v1 */
+ mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT &&
+ msm_soc_version_supports_iommu_v0();
+
+ /*
+ * For IOMMU per-process pagetables, the allocatable range
+ * and the kernel global range must both be outside
+ * the userspace address range. There is a 1Mb gap
+ * between these address ranges to make overrun
+ * detection easier.
+ * For the shared pagetable case use 2GB and because
+ * mirroring the CPU address space is not possible and
+ * we're better off with extra room.
+ */
+ if (mmu->pt_per_process) {
+ mmu->pt_base = PAGE_OFFSET;
+ mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE
+ - kgsl_mmu_get_base_addr(mmu) - SZ_1M;
+ mmu->use_cpu_map = true;
+ } else {
+ mmu->pt_base = KGSL_PAGETABLE_BASE;
+ mmu->pt_size = SZ_2G;
+ mmu->use_cpu_map = false;
+ }
+
+
iommu->iommu_reg_list = kgsl_iommuv0_reg;
iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0;
@@ -1272,7 +1347,8 @@
* switching on the 3D side for which a separate table is allocated */
if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v0()) {
mmu->priv_bank_table =
- kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME);
+ kgsl_mmu_getpagetable(mmu,
+ KGSL_MMU_PRIV_BANK_TABLE_NAME);
if (mmu->priv_bank_table == NULL) {
status = -ENOMEM;
goto err;
@@ -1281,7 +1357,7 @@
if (status)
goto err;
}
- mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+ mmu->defaultpagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT);
/* Return error if the default pagetable doesn't exist */
if (mmu->defaultpagetable == NULL) {
status = -ENOMEM;
@@ -1485,13 +1561,13 @@
}
static int
-kgsl_iommu_unmap(void *mmu_specific_pt,
+kgsl_iommu_unmap(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int *tlb_flags)
{
int ret;
unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen);
- struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+ struct kgsl_iommu_pt *iommu_pt = pt->priv;
/* All GPU addresses as assigned are page aligned, but some
functions purturb the gpuaddr with an offset, so apply the
@@ -1512,20 +1588,20 @@
* Flushing only required if per process pagetables are used. With
* global case, flushing will happen inside iommu_map function
*/
- if (!ret && kgsl_mmu_is_perprocess())
+ if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
*tlb_flags = UINT_MAX;
return 0;
}
static int
-kgsl_iommu_map(void *mmu_specific_pt,
+kgsl_iommu_map(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int protflags,
unsigned int *tlb_flags)
{
int ret;
unsigned int iommu_virt_addr;
- struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
+ struct kgsl_iommu_pt *iommu_pt = pt->priv;
int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
BUG_ON(NULL == iommu_pt);
diff --git a/drivers/gpu/msm/kgsl_log.h b/drivers/gpu/msm/kgsl_log.h
index 81a35e0..a7832e4 100644
--- a/drivers/gpu/msm/kgsl_log.h
+++ b/drivers/gpu/msm/kgsl_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2011,2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -103,6 +103,15 @@
#define KGSL_PWR_CRIT(_dev, fmt, args...) \
KGSL_LOG_CRIT(_dev->dev, _dev->pwr_log, fmt, ##args)
+#define KGSL_FT_INFO(_dev, fmt, args...) \
+KGSL_LOG_INFO(_dev->dev, _dev->ft_log, fmt, ##args)
+#define KGSL_FT_WARN(_dev, fmt, args...) \
+KGSL_LOG_WARN(_dev->dev, _dev->ft_log, fmt, ##args)
+#define KGSL_FT_ERR(_dev, fmt, args...) \
+KGSL_LOG_ERR(_dev->dev, _dev->ft_log, fmt, ##args)
+#define KGSL_FT_CRIT(_dev, fmt, args...) \
+KGSL_LOG_CRIT(_dev->dev, _dev->ft_log, fmt, ##args)
+
/* Core error messages - these are for core KGSL functions that have
no device associated with them (such as memory) */
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 01b255c..4e95373 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -23,6 +23,7 @@
#include "kgsl.h"
#include "kgsl_mmu.h"
+#include "kgsl_gpummu.h"
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
#include "adreno.h"
@@ -103,7 +104,7 @@
if (pagetable->pool)
gen_pool_destroy(pagetable->pool);
- pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
+ pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
kfree(pagetable);
}
@@ -193,7 +194,7 @@
if (pt) {
ret += snprintf(buf, PAGE_SIZE, "0x%x\n",
- kgsl_mmu_get_ptsize());
+ kgsl_mmu_get_ptsize(pt->mmu));
}
kgsl_put_pagetable(pt);
@@ -333,6 +334,35 @@
}
EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
+unsigned int
+kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base,
+ unsigned int addr)
+{
+ struct kgsl_pagetable *pt;
+ unsigned int ret = 0;
+
+ if (!mmu->mmu_ops || !mmu->mmu_ops->mmu_pt_equal)
+ return 0;
+ spin_lock(&kgsl_driver.ptlock);
+ list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
+ if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
+ if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) {
+ ret = 1;
+ break;
+ } else {
+ pt->fault_addr = (addr & ~(PAGE_SIZE-1));
+ ret = 0;
+ break;
+ }
+
+ }
+ }
+ spin_unlock(&kgsl_driver.ptlock);
+
+ return ret;
+}
+EXPORT_SYMBOL(kgsl_mmu_log_fault_addr);
+
int kgsl_mmu_init(struct kgsl_device *device)
{
int status = 0;
@@ -415,7 +445,8 @@
}
EXPORT_SYMBOL(kgsl_mh_intrcallback);
-static struct kgsl_pagetable *kgsl_mmu_createpagetableobject(
+static struct kgsl_pagetable *
+kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu,
unsigned int name)
{
int status = 0;
@@ -434,10 +465,11 @@
spin_lock_init(&pagetable->lock);
- ptsize = kgsl_mmu_get_ptsize();
-
+ ptsize = kgsl_mmu_get_ptsize(mmu);
+ pagetable->mmu = mmu;
pagetable->name = name;
pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize);
+ pagetable->fault_addr = 0xFFFFFFFF;
/*
* create a separate kgsl pool for IOMMU, global mappings can be mapped
@@ -467,7 +499,7 @@
goto err_kgsl_pool;
}
- if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(),
+ if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(mmu),
ptsize, -1)) {
KGSL_CORE_ERR("gen_pool_add failed\n");
goto err_pool;
@@ -496,7 +528,7 @@
return pagetable;
err_mmu_create:
- pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv);
+ pagetable->pt_ops->mmu_destroy_pagetable(pagetable);
err_pool:
gen_pool_destroy(pagetable->pool);
err_kgsl_pool:
@@ -508,20 +540,21 @@
return NULL;
}
-struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name)
+struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *mmu,
+ unsigned long name)
{
struct kgsl_pagetable *pt;
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return (void *)(-1);
- if (!kgsl_mmu_is_perprocess())
+ if (!kgsl_mmu_is_perprocess(mmu))
name = KGSL_MMU_GLOBAL_PT;
pt = kgsl_get_pagetable(name);
if (pt == NULL)
- pt = kgsl_mmu_createpagetableobject(name);
+ pt = kgsl_mmu_createpagetableobject(mmu, name);
return pt;
}
@@ -658,7 +691,7 @@
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
- ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags,
+ ret = pagetable->pt_ops->mmu_map(pagetable, memdesc, protflags,
&pagetable->tlb_flags);
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
@@ -693,6 +726,8 @@
{
struct gen_pool *pool;
int size;
+ unsigned int start_addr = 0;
+ unsigned int end_addr = 0;
if (memdesc->size == 0 || memdesc->gpuaddr == 0)
return 0;
@@ -704,10 +739,19 @@
size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
+ start_addr = memdesc->gpuaddr;
+ end_addr = (memdesc->gpuaddr + size);
+
if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
- pagetable->pt_ops->mmu_unmap(pagetable->priv, memdesc,
+ pagetable->pt_ops->mmu_unmap(pagetable, memdesc,
&pagetable->tlb_flags);
+
+ /* If buffer is unmapped 0 fault addr */
+ if ((pagetable->fault_addr >= start_addr) &&
+ (pagetable->fault_addr < end_addr))
+ pagetable->fault_addr = 0;
+
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
spin_lock(&pagetable->lock);
/* Remove the statistics */
@@ -853,15 +897,16 @@
}
EXPORT_SYMBOL(kgsl_mmu_set_mmutype);
-int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
+int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr)
{
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
return 1;
- if (gpuaddr >= kgsl_mmu_get_base_addr() &&
- gpuaddr < kgsl_mmu_get_base_addr() + kgsl_mmu_get_ptsize())
+ if (gpuaddr >= kgsl_mmu_get_base_addr(pt->mmu) &&
+ gpuaddr < kgsl_mmu_get_base_addr(pt->mmu) +
+ kgsl_mmu_get_ptsize(pt->mmu))
return 1;
if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU
- && kgsl_mmu_is_perprocess())
+ && kgsl_mmu_is_perprocess(pt->mmu))
return (gpuaddr > 0 && gpuaddr < TASK_SIZE);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 0458a13..d7d9516 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -24,6 +24,13 @@
#define KGSL_MMU_ALIGN_MASK (~((1 << PAGE_SHIFT) - 1))
+/* defconfig option for disabling per process pagetables */
+#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
+#define KGSL_MMU_USE_PER_PROCESS_PT true
+#else
+#define KGSL_MMU_USE_PER_PROCESS_PT false
+#endif
+
/* Identifier for the global page table */
/* Per process page tables will probably pass in the thread group
as an identifier */
@@ -114,7 +121,9 @@
} stats;
const struct kgsl_mmu_pt_ops *pt_ops;
unsigned int tlb_flags;
+ unsigned int fault_addr;
void *priv;
+ struct kgsl_mmu *mmu;
};
struct kgsl_mmu;
@@ -159,15 +168,15 @@
};
struct kgsl_mmu_pt_ops {
- int (*mmu_map) (void *mmu_pt,
+ int (*mmu_map) (struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int protflags,
unsigned int *tlb_flags);
- int (*mmu_unmap) (void *mmu_pt,
+ int (*mmu_unmap) (struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc,
unsigned int *tlb_flags);
void *(*mmu_create_pagetable) (void);
- void (*mmu_destroy_pagetable) (void *pt);
+ void (*mmu_destroy_pagetable) (struct kgsl_pagetable *);
};
#define KGSL_MMU_FLAGS_IOMMU_SYNC BIT(31)
@@ -186,14 +195,19 @@
const struct kgsl_mmu_ops *mmu_ops;
void *priv;
int fault;
+ unsigned long pt_base;
+ unsigned long pt_size;
+ bool pt_per_process;
+ bool use_cpu_map;
};
-#include "kgsl_gpummu.h"
-
extern struct kgsl_mmu_ops iommu_ops;
extern struct kgsl_mmu_pt_ops iommu_pt_ops;
+extern struct kgsl_mmu_ops gpummu_ops;
+extern struct kgsl_mmu_pt_ops gpummu_pt_ops;
-struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name);
+struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *,
+ unsigned long name);
void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
void kgsl_mh_start(struct kgsl_device *device);
void kgsl_mh_intrcallback(struct kgsl_device *device);
@@ -211,6 +225,8 @@
uint32_t flags);
int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu,
unsigned int pt_base);
+unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
+ unsigned int pt_base, unsigned int addr);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id);
void kgsl_mmu_ptpool_destroy(void *ptpool);
@@ -218,7 +234,7 @@
int kgsl_mmu_enabled(void);
void kgsl_mmu_set_mmutype(char *mmutype);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
-int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
+int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr);
/*
* Static inline functions of MMU that simply call the SMMU specific
@@ -332,75 +348,51 @@
/*
* kgsl_mmu_is_perprocess() - Runtime check for per-process
* pagetables.
+ * @mmu: the mmu
*
- * Returns non-zero if per-process pagetables are enabled,
- * 0 if not.
+ * Returns true if per-process pagetables are enabled,
+ * false if not.
*/
-#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
-static inline int kgsl_mmu_is_perprocess(void)
+static inline int kgsl_mmu_is_perprocess(struct kgsl_mmu *mmu)
{
+ return mmu->pt_per_process;
+}
- /* We presently do not support per-process for IOMMU-v1 */
- return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU)
- || msm_soc_version_supports_iommu_v0();
-}
-#else
-static inline int kgsl_mmu_is_perprocess(void)
+/*
+ * kgsl_mmu_use_cpu_map() - Runtime check for matching the CPU
+ * address space on the GPU.
+ * @mmu: the mmu
+ *
+ * Returns true if supported false if not.
+ */
+static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu)
{
- return 0;
+ return mmu->pt_per_process;
}
-#endif
/*
* kgsl_mmu_base_addr() - Get gpu virtual address base.
+ * @mmu: the mmu
*
* Returns the start address of the allocatable gpu
* virtual address space. Other mappings that mirror
* the CPU address space are possible outside this range.
*/
-static inline unsigned int kgsl_mmu_get_base_addr(void)
+static inline unsigned int kgsl_mmu_get_base_addr(struct kgsl_mmu *mmu)
{
- if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype()
- || !kgsl_mmu_is_perprocess())
- return KGSL_PAGETABLE_BASE;
- /*
- * This is the start of the kernel address
- * space, so allocations from this range will
- * never conflict with userpace addresses
- */
- return PAGE_OFFSET;
+ return mmu->pt_base;
}
/*
* kgsl_mmu_get_ptsize() - Get gpu pagetable size
+ * @mmu: the mmu
*
* Returns the usable size of the gpu allocatable
* address space.
*/
-static inline unsigned int kgsl_mmu_get_ptsize(void)
+static inline unsigned int kgsl_mmu_get_ptsize(struct kgsl_mmu *mmu)
{
- /*
- * For IOMMU per-process pagetables, the allocatable range
- * and the kernel global range must both be outside
- * the userspace address range. There is a 1Mb gap
- * between these address ranges to make overrun
- * detection easier.
- * For the shared pagetable case use 2GB and because
- * mirroring the CPU address space is not possible and
- * we're better off with extra room.
- */
- enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype();
-
- if (KGSL_MMU_TYPE_GPU == mmu_type)
- return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
- else if (KGSL_MMU_TYPE_IOMMU == mmu_type) {
- if (kgsl_mmu_is_perprocess())
- return KGSL_IOMMU_GLOBAL_MEM_BASE
- - kgsl_mmu_get_base_addr() - SZ_1M;
- else
- return SZ_2G;
- }
- return 0;
+ return mmu->pt_size;
}
static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index d9dbad8..2f8d93e 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1081,7 +1081,7 @@
}
}
} else if (device->state & (KGSL_STATE_HUNG |
- KGSL_STATE_DUMP_AND_RECOVER)) {
+ KGSL_STATE_DUMP_AND_FT)) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
}
@@ -1120,7 +1120,7 @@
break;
case KGSL_STATE_INIT:
case KGSL_STATE_HUNG:
- case KGSL_STATE_DUMP_AND_RECOVER:
+ case KGSL_STATE_DUMP_AND_FT:
if (test_bit(KGSL_PWRFLAGS_CLK_ON,
&device->pwrctrl.power_flags))
break;
@@ -1144,9 +1144,9 @@
mutex_unlock(&device->mutex);
wait_for_completion(&device->hwaccess_gate);
mutex_lock(&device->mutex);
- } else if (device->state == KGSL_STATE_DUMP_AND_RECOVER) {
+ } else if (device->state == KGSL_STATE_DUMP_AND_FT) {
mutex_unlock(&device->mutex);
- wait_for_completion(&device->recovery_gate);
+ wait_for_completion(&device->ft_gate);
mutex_lock(&device->mutex);
} else if (device->state == KGSL_STATE_SLUMBER)
kgsl_pwrctrl_wake(device);
@@ -1289,7 +1289,7 @@
kgsl_pwrctrl_request_state(device, KGSL_STATE_ACTIVE);
switch (device->state) {
case KGSL_STATE_SLUMBER:
- status = device->ftbl->start(device, 0);
+ status = device->ftbl->start(device);
if (status) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
KGSL_DRV_ERR(device, "start failed %d\n", status);
@@ -1385,7 +1385,7 @@
return "SUSPEND";
case KGSL_STATE_HUNG:
return "HUNG";
- case KGSL_STATE_DUMP_AND_RECOVER:
+ case KGSL_STATE_DUMP_AND_FT:
return "DNR";
case KGSL_STATE_SLUMBER:
return "SLUMBER";
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index c4647a1..296de11 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -169,8 +169,9 @@
header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
header->busclk = kgsl_get_clkrate(pwr->ebi1_clk);
- /* Future proof for per-context timestamps */
- header->current_context = -1;
+ /* Save the last active context */
+ kgsl_sharedmem_readl(&device->memstore, &header->current_context,
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
/* Get the current PT base */
header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
@@ -375,8 +376,8 @@
/* If the buffer is already on the list, skip it */
list_for_each_entry(obj, &device->snapshot_obj_list, node) {
if (obj->gpuaddr == gpuaddr && obj->ptbase == ptbase) {
- /* If the size is different, use the new size */
- if (obj->size != size)
+ /* If the size is different, use the bigger size */
+ if (obj->size < size)
obj->size = size;
return 0;
@@ -572,10 +573,9 @@
/* Freeze the snapshot on a hang until it gets read */
device->snapshot_frozen = (hang) ? 1 : 0;
- /* log buffer info to aid in ramdump recovery */
- KGSL_DRV_ERR(device, "snapshot created at va %p pa %lx size %d\n",
- device->snapshot, __pa(device->snapshot),
- device->snapshot_size);
+ /* log buffer info to aid in ramdump fault tolerance */
+ KGSL_DRV_ERR(device, "snapshot created at pa %lx size %d\n",
+ __pa(device->snapshot), device->snapshot_size);
if (hang)
sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
return 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index 327d18a..4db2815 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -52,6 +52,7 @@
#define KGSL_SNAPSHOT_SECTION_DEBUG 0x0901
#define KGSL_SNAPSHOT_SECTION_DEBUGBUS 0x0A01
#define KGSL_SNAPSHOT_SECTION_GPU_OBJECT 0x0B01
+#define KGSL_SNAPSHOT_SECTION_MEMLIST 0x0E01
#define KGSL_SNAPSHOT_SECTION_END 0xFFFF
@@ -103,6 +104,17 @@
int count; /* Number of dwords in the dump */
} __packed;
+/* Replay or Memory list section, both sections have same header */
+struct kgsl_snapshot_replay_mem_list {
+ /*
+ * Number of IBs to replay for replay section or
+ * number of memory list entries for mem list section
+ */
+ int num_entries;
+ /* Pagetable base to which the replay IBs or memory entries belong */
+ __u32 ptbase;
+} __packed;
+
/* Indirect buffer sub-section header */
struct kgsl_snapshot_ib {
__u32 gpuaddr; /* GPU address of the the IB */
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index f0410d6..b78c6fe 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -93,7 +93,8 @@
#define Z180_CMDWINDOW_TARGET_SHIFT 0
#define Z180_CMDWINDOW_ADDR_SHIFT 8
-static int z180_start(struct kgsl_device *device, unsigned int init_ram);
+static int z180_init(struct kgsl_device *device);
+static int z180_start(struct kgsl_device *device);
static int z180_stop(struct kgsl_device *device);
static int z180_wait(struct kgsl_device *device,
struct kgsl_context *context,
@@ -319,16 +320,11 @@
*p++ = ADDR_VGV3_LAST << 24;
}
-static void z180_cmdstream_start(struct kgsl_device *device, int init_ram)
+static void z180_cmdstream_start(struct kgsl_device *device)
{
struct z180_device *z180_dev = Z180_DEVICE(device);
unsigned int cmd = VGV3_NEXTCMD_JUMP << VGV3_NEXTCMD_NEXTCMD_FSHIFT;
- if (init_ram) {
- z180_dev->timestamp = 0;
- z180_dev->current_timestamp = 0;
- }
-
addmarker(&z180_dev->ringbuffer, 0);
z180_cmdwindow_write(device, ADDR_VGV3_MODE, 4);
@@ -552,7 +548,17 @@
return 0;
}
-static int z180_start(struct kgsl_device *device, unsigned int init_ram)
+static int z180_init(struct kgsl_device *device)
+{
+ struct z180_device *z180_dev = Z180_DEVICE(device);
+
+ z180_dev->timestamp = 0;
+ z180_dev->current_timestamp = 0;
+
+ return 0;
+}
+
+static int z180_start(struct kgsl_device *device)
{
int status = 0;
@@ -569,7 +575,7 @@
if (status)
goto error_clk_off;
- z180_cmdstream_start(device, init_ram);
+ z180_cmdstream_start(device);
mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
@@ -919,6 +925,7 @@
.idle = z180_idle,
.isidle = z180_isidle,
.suspend_context = z180_suspend_context,
+ .init = z180_init,
.start = z180_start,
.stop = z180_stop,
.getproperty = z180_getproperty,
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index ecd4bbb..60c2da3 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -212,7 +212,7 @@
bool descending = 1;
uint32_t i = 0;
- if ((pts == NULL) || (output == NULL))
+ if (pts == NULL)
return -EINVAL;
/* Check if table is descending or ascending */
@@ -258,7 +258,7 @@
bool descending = 1;
uint32_t i = 0;
- if ((pts == NULL) || (output == NULL))
+ if (pts == NULL)
return -EINVAL;
/* Check if table is descending or ascending */
@@ -367,7 +367,42 @@
}
EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
-/* Scales the ADC code to 0.001 degrees C using the map
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+ struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold)
+{
+ struct qpnp_vadc_linear_graph btm_param;
+ int64_t low_output = 0, high_output = 0;
+ int rc = 0;
+
+ rc = qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_ABSOLUTE);
+ if (rc < 0) {
+ pr_err("Could not acquire gain and offset\n");
+ return rc;
+ }
+
+ /* Convert to Kelvin and account for voltage to be written as 2mV/K */
+ low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
+ /* Convert to voltage threshold */
+ low_output *= btm_param.dy;
+ do_div(low_output, btm_param.adc_vref);
+ low_output += btm_param.adc_gnd;
+
+ /* Convert to Kelvin and account for voltage to be written as 2mV/K */
+ high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
+ /* Convert to voltage threshold */
+ high_output *= btm_param.dy;
+ do_div(high_output, btm_param.adc_vref);
+ high_output += btm_param.adc_gnd;
+
+ *low_threshold = low_output;
+ *high_threshold = high_output;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
+
+/* Scales the ADC code to degC using the mapping
* table for the XO thermistor.
*/
int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
@@ -577,7 +612,7 @@
}
EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{
struct qpnp_vadc_linear_graph usb_param;
@@ -592,46 +627,81 @@
do_div(*high_threshold, usb_param.adc_vref);
*high_threshold += usb_param.adc_gnd;
+ pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+ param->low_thr);
return 0;
}
EXPORT_SYMBOL_GPL(qpnp_adc_usb_scaler);
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold)
+{
+ struct qpnp_vadc_linear_graph vbatt_param;
+
+ qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+
+ *low_threshold = param->low_thr * vbatt_param.dy;
+ do_div(*low_threshold, vbatt_param.adc_vref);
+ *low_threshold += vbatt_param.adc_gnd;
+
+ *high_threshold = param->high_thr * vbatt_param.dy;
+ do_div(*high_threshold, vbatt_param.adc_vref);
+ *high_threshold += vbatt_param.adc_gnd;
+
+ pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+ param->low_thr);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_vbatt_rscaler);
+
int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{
struct qpnp_vadc_linear_graph btm_param;
- int64_t *low_output = 0, *high_output = 0;
+ int64_t low_output = 0, high_output = 0;
int rc = 0;
qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_RATIOMETRIC);
- rc = qpnp_adc_map_temp_voltage(
+ pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
+ param->low_temp);
+ rc = qpnp_adc_map_voltage_temp(
adcmap_btm_threshold,
ARRAY_SIZE(adcmap_btm_threshold),
(param->low_temp),
- low_output);
- if (rc)
+ &low_output);
+ if (rc) {
+ pr_debug("low_temp mapping failed with %d\n", rc);
return rc;
+ }
- *low_output *= btm_param.dy;
- do_div(*low_output, btm_param.adc_vref);
- *low_output += btm_param.adc_gnd;
+ pr_debug("low_output:%lld\n", low_output);
+ low_output *= btm_param.dy;
+ do_div(low_output, btm_param.adc_vref);
+ low_output += btm_param.adc_gnd;
- rc = qpnp_adc_map_temp_voltage(
+ rc = qpnp_adc_map_voltage_temp(
adcmap_btm_threshold,
ARRAY_SIZE(adcmap_btm_threshold),
(param->high_temp),
- high_output);
- if (rc)
+ &high_output);
+ if (rc) {
+ pr_debug("high temp mapping failed with %d\n", rc);
return rc;
+ }
- *high_output *= btm_param.dy;
- do_div(*high_output, btm_param.adc_vref);
- *high_output += btm_param.adc_gnd;
+ pr_debug("high_output:%lld\n", high_output);
+ high_output *= btm_param.dy;
+ do_div(high_output, btm_param.adc_vref);
+ high_output += btm_param.adc_gnd;
- low_threshold = (uint32_t *) low_output;
- high_threshold = (uint32_t *) high_output;
+ /* btm low temperature correspondes to high voltage threshold */
+ *low_threshold = high_output;
+ /* btm high temperature correspondes to low voltage threshold */
+ *high_threshold = low_output;
+ pr_debug("high_volt:%d, low_volt:%d\n", *high_threshold,
+ *low_threshold);
return 0;
}
EXPORT_SYMBOL_GPL(qpnp_adc_btm_scaler);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 2017c8d..60dcada 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -404,6 +404,8 @@
iadc->adc->calib.gain_uv = (num * QPNP_ADC_GAIN_NV)/
(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+ pr_debug("gain_uv:%d offset_uv:%d\n",
+ iadc->adc->calib.gain_uv, iadc->adc->calib.offset_uv);
return 0;
}
@@ -439,6 +441,9 @@
goto fail;
}
+ pr_debug("raw gain:0x%x, raw offset:0x%x\n",
+ iadc->adc->calib.gain_raw, iadc->adc->calib.offset_raw);
+
rc = qpnp_convert_raw_offset_voltage();
if (rc < 0) {
pr_err("qpnp raw_voltage conversion failed\n");
@@ -449,6 +454,8 @@
QPNP_BIT_SHIFT_8;
rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;
+ pr_debug("trim values:lsb:0x%x and msb:0x%x\n", rslt_lsb, rslt_msb);
+
rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
QPNP_IADC_SEC_ACCESS_DATA);
if (rc < 0) {
@@ -545,6 +552,8 @@
return rc;
}
+ pr_debug("rsense:0%x\n", rslt_rsense);
+
if (rslt_rsense & QPNP_RSENSE_MSB_SIGN_CHECK)
sign_bit = 1;
@@ -610,6 +619,8 @@
}
rc = qpnp_iadc_get_rsense(&rsense_n_ohms);
+ pr_debug("current raw:0%x and rsense:%d\n",
+ raw_data, rsense_n_ohms);
num = raw_data - iadc->adc->calib.offset_raw;
if (num < 0) {
@@ -658,6 +669,10 @@
result->ideal_offset_uv =
QPNP_OFFSET_CALIBRATION_SHORT_CADC_LEADS_IDEAL;
result->offset_uv = iadc->adc->calib.offset_uv;
+ pr_debug("raw gain:0%x, raw offset:0%x\n",
+ result->gain_raw, result->offset_raw);
+ pr_debug("gain_uv:%d offset_uv:%d\n",
+ result->gain_uv, result->offset_uv);
mutex_unlock(&iadc->adc->adc_lock);
return 0;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index edbde44..0470a62 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -491,6 +491,9 @@
goto calib_fail;
}
+ pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
+ calib_read_1, calib_read_2);
+
vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
(calib_read_1 - calib_read_2);
@@ -555,6 +558,8 @@
goto calib_fail;
}
+ pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
+ calib_read_1, calib_read_2);
vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
(calib_read_1 - calib_read_2);
vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 9ed3d53..41f79be 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -693,8 +693,8 @@
spin_lock_irq(&client->buffer_lock);
client->use_wake_lock = false;
- wake_lock_destroy(&client->wake_lock);
spin_unlock_irq(&client->buffer_lock);
+ wake_lock_destroy(&client->wake_lock);
return 0;
}
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 6bf0220..de35f9a 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -29,6 +29,7 @@
#include <mach/iommu_perfmon.h>
#include <mach/iommu_hw-v0.h>
+#include <mach/msm_iommu_priv.h>
#include <mach/iommu.h>
#include <mach/msm_smsm.h>
@@ -131,12 +132,6 @@
return msm_iommu_remote_lock.lock;
}
-struct msm_priv {
- unsigned long *pgtable;
- int redirect;
- struct list_head list_attached;
-};
-
static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
{
int ret;
@@ -198,7 +193,7 @@
static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
@@ -235,7 +230,7 @@
static int __flush_iotlb(struct iommu_domain *domain)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
@@ -396,26 +391,27 @@
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
{
- struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ struct msm_iommu_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
goto fail_nomem;
INIT_LIST_HEAD(&priv->list_attached);
- priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
+ priv->pt.fl_table = (unsigned long *)__get_free_pages(GFP_KERNEL,
get_order(SZ_16K));
- if (!priv->pgtable)
+ if (!priv->pt.fl_table)
goto fail_nomem;
#ifdef CONFIG_IOMMU_PGTABLES_L2
- priv->redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE;
+ priv->pt.redirect = flags & MSM_IOMMU_DOMAIN_PT_CACHEABLE;
#endif
- memset(priv->pgtable, 0, SZ_16K);
+ memset(priv->pt.fl_table, 0, SZ_16K);
domain->priv = priv;
- clean_pte(priv->pgtable, priv->pgtable + NUM_FL_PTE, priv->redirect);
+ clean_pte(priv->pt.fl_table, priv->pt.fl_table + NUM_FL_PTE,
+ priv->pt.redirect);
return 0;
@@ -426,7 +422,7 @@
static void msm_iommu_domain_destroy(struct iommu_domain *domain)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
unsigned long *fl_table;
int i;
@@ -435,15 +431,15 @@
domain->priv = NULL;
if (priv) {
- fl_table = priv->pgtable;
+ fl_table = priv->pt.fl_table;
for (i = 0; i < NUM_FL_PTE; i++)
if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
free_page((unsigned long) __va(((fl_table[i]) &
FL_BASE_MASK)));
- free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
- priv->pgtable = NULL;
+ free_pages((unsigned long)priv->pt.fl_table, get_order(SZ_16K));
+ priv->pt.fl_table = NULL;
}
kfree(priv);
@@ -452,7 +448,7 @@
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -497,7 +493,7 @@
__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
ctx_drvdata->num, iommu_drvdata->ncb,
- __pa(priv->pgtable), priv->redirect,
+ __pa(priv->pt.fl_table), priv->pt.redirect,
iommu_drvdata->ttbr_split);
__disable_clocks(iommu_drvdata);
@@ -517,7 +513,7 @@
static void msm_iommu_detach_dev(struct iommu_domain *domain,
struct device *dev)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret;
@@ -605,7 +601,7 @@
return pgprot;
}
-static unsigned long *make_second_level(struct msm_priv *priv,
+static unsigned long *make_second_level(struct msm_iommu_priv *priv,
unsigned long *fl_pte)
{
unsigned long *sl;
@@ -617,12 +613,12 @@
goto fail;
}
memset(sl, 0, SZ_4K);
- clean_pte(sl, sl + NUM_SL_PTE, priv->redirect);
+ clean_pte(sl, sl + NUM_SL_PTE, priv->pt.redirect);
*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | \
FL_TYPE_TABLE);
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
fail:
return sl;
}
@@ -694,7 +690,7 @@
static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
phys_addr_t pa, size_t len, int prot)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
unsigned long *fl_table;
unsigned long *fl_pte;
unsigned long fl_offset;
@@ -712,7 +708,7 @@
goto fail;
}
- fl_table = priv->pgtable;
+ fl_table = priv->pt.fl_table;
if (len != SZ_16M && len != SZ_1M &&
len != SZ_64K && len != SZ_4K) {
@@ -741,14 +737,14 @@
ret = fl_16m(fl_pte, pa, pgprot);
if (ret)
goto fail;
- clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 16, priv->pt.redirect);
}
if (len == SZ_1M) {
ret = fl_1m(fl_pte, pa, pgprot);
if (ret)
goto fail;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
}
/* Need a 2nd level table */
@@ -776,14 +772,14 @@
if (ret)
goto fail;
- clean_pte(sl_pte, sl_pte + 1, priv->redirect);
+ clean_pte(sl_pte, sl_pte + 1, priv->pt.redirect);
}
if (len == SZ_64K) {
ret = sl_64k(sl_pte, pa, pgprot);
if (ret)
goto fail;
- clean_pte(sl_pte, sl_pte + 16, priv->redirect);
+ clean_pte(sl_pte, sl_pte + 16, priv->pt.redirect);
}
ret = __flush_iotlb_va(domain, va);
@@ -795,7 +791,7 @@
static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
size_t len)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
unsigned long *fl_table;
unsigned long *fl_pte;
unsigned long fl_offset;
@@ -811,7 +807,7 @@
if (!priv)
goto fail;
- fl_table = priv->pgtable;
+ fl_table = priv->pt.fl_table;
if (len != SZ_16M && len != SZ_1M &&
len != SZ_64K && len != SZ_4K) {
@@ -837,13 +833,13 @@
for (i = 0; i < 16; i++)
*(fl_pte+i) = 0;
- clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 16, priv->pt.redirect);
}
if (len == SZ_1M) {
*fl_pte = 0;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
}
sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
@@ -854,13 +850,13 @@
for (i = 0; i < 16; i++)
*(sl_pte+i) = 0;
- clean_pte(sl_pte, sl_pte + 16, priv->redirect);
+ clean_pte(sl_pte, sl_pte + 16, priv->pt.redirect);
}
if (len == SZ_4K) {
*sl_pte = 0;
- clean_pte(sl_pte, sl_pte + 1, priv->redirect);
+ clean_pte(sl_pte, sl_pte + 1, priv->pt.redirect);
}
if (len == SZ_4K || len == SZ_64K) {
@@ -873,7 +869,7 @@
free_page((unsigned long)sl_table);
*fl_pte = 0;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
}
}
@@ -969,7 +965,7 @@
unsigned long sl_offset, sl_start;
unsigned int chunk_size, chunk_offset = 0;
int ret = 0;
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
unsigned int pgprot4k, pgprot64k, pgprot1m, pgprot16m;
mutex_lock(&msm_iommu_lock);
@@ -977,7 +973,7 @@
BUG_ON(len & (SZ_4K - 1));
priv = domain->priv;
- fl_table = priv->pgtable;
+ fl_table = priv->pt.fl_table;
pgprot4k = __get_pgprot(prot, SZ_4K);
pgprot64k = __get_pgprot(prot, SZ_64K);
@@ -1013,13 +1009,15 @@
ret = fl_16m(fl_pte, pa, pgprot16m);
if (ret)
goto fail;
- clean_pte(fl_pte, fl_pte + 16, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 16,
+ priv->pt.redirect);
fl_pte += 16;
} else if (chunk_size == SZ_1M) {
ret = fl_1m(fl_pte, pa, pgprot1m);
if (ret)
goto fail;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1,
+ priv->pt.redirect);
fl_pte++;
}
@@ -1101,7 +1099,7 @@
}
clean_pte(sl_table + sl_start, sl_table + sl_offset,
- priv->redirect);
+ priv->pt.redirect);
fl_pte++;
sl_offset = 0;
@@ -1123,14 +1121,14 @@
unsigned long *sl_table;
unsigned long sl_start, sl_end;
int used, i;
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
mutex_lock(&msm_iommu_lock);
BUG_ON(len & (SZ_4K - 1));
priv = domain->priv;
- fl_table = priv->pgtable;
+ fl_table = priv->pt.fl_table;
fl_offset = FL_OFFSET(va); /* Upper 12 bits */
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
@@ -1146,7 +1144,7 @@
memset(sl_table + sl_start, 0, (sl_end - sl_start) * 4);
clean_pte(sl_table + sl_start, sl_table + sl_end,
- priv->redirect);
+ priv->pt.redirect);
offset += (sl_end - sl_start) * SZ_4K;
va += (sl_end - sl_start) * SZ_4K;
@@ -1171,13 +1169,14 @@
free_page((unsigned long)sl_table);
*fl_pte = 0;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1,
+ priv->pt.redirect);
}
sl_start = 0;
} else {
*fl_pte = 0;
- clean_pte(fl_pte, fl_pte + 1, priv->redirect);
+ clean_pte(fl_pte, fl_pte + 1, priv->pt.redirect);
va += SZ_1M;
offset += SZ_1M;
sl_start = 0;
@@ -1193,7 +1192,7 @@
static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long va)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
unsigned int par;
@@ -1339,8 +1338,8 @@
static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain)
{
- struct msm_priv *priv = domain->priv;
- return __pa(priv->pgtable);
+ struct msm_iommu_priv *priv = domain->priv;
+ return __pa(priv->pt.fl_table);
}
static struct iommu_ops msm_iommu_ops = {
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 24d2854..f552474 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -30,6 +30,7 @@
#include <mach/iommu_hw-v1.h>
#include <mach/iommu.h>
+#include <mach/msm_iommu_priv.h>
#include <mach/iommu_perfmon.h>
#include "msm_iommu_pagetable.h"
@@ -38,11 +39,6 @@
static DEFINE_MUTEX(msm_iommu_lock);
-struct msm_priv {
- struct iommu_pt pt;
- struct list_head list_attached;
-};
-
static int __enable_regulators(struct msm_iommu_drvdata *drvdata)
{
int ret = regulator_enable(drvdata->gdsc);
@@ -198,7 +194,7 @@
static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
@@ -226,7 +222,7 @@
static int __flush_iotlb(struct iommu_domain *domain)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
@@ -335,7 +331,7 @@
static void msm_iommu_assign_ASID(const struct msm_iommu_drvdata *iommu_drvdata,
struct msm_iommu_ctx_drvdata *curr_ctx,
- struct msm_priv *priv)
+ struct msm_iommu_priv *priv)
{
unsigned int found = 0;
void __iomem *base = iommu_drvdata->base;
@@ -374,7 +370,7 @@
static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
struct msm_iommu_ctx_drvdata *ctx_drvdata,
- struct msm_priv *priv, bool is_secure)
+ struct msm_iommu_priv *priv, bool is_secure)
{
unsigned int prrr, nmrr;
unsigned int pn;
@@ -469,7 +465,7 @@
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -493,7 +489,7 @@
static void msm_iommu_domain_destroy(struct iommu_domain *domain)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
mutex_lock(&msm_iommu_lock);
priv = domain->priv;
@@ -508,7 +504,7 @@
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -596,7 +592,7 @@
static void msm_iommu_detach_dev(struct iommu_domain *domain,
struct device *dev)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret;
@@ -649,7 +645,7 @@
static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
phys_addr_t pa, size_t len, int prot)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
int ret = 0;
mutex_lock(&msm_iommu_lock);
@@ -673,7 +669,7 @@
static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
size_t len)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
int ret = -ENODEV;
mutex_lock(&msm_iommu_lock);
@@ -700,7 +696,7 @@
int prot)
{
int ret;
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
mutex_lock(&msm_iommu_lock);
@@ -724,7 +720,7 @@
static int msm_iommu_unmap_range(struct iommu_domain *domain, unsigned int va,
unsigned int len)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
mutex_lock(&msm_iommu_lock);
@@ -739,7 +735,7 @@
static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
unsigned long va)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
unsigned int par;
@@ -876,7 +872,7 @@
static phys_addr_t msm_iommu_get_pt_base_addr(struct iommu_domain *domain)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
return __pa(priv->pt.fl_table);
}
diff --git a/drivers/iommu/msm_iommu_pagetable.c b/drivers/iommu/msm_iommu_pagetable.c
index b32bd26..b62bb76 100644
--- a/drivers/iommu/msm_iommu_pagetable.c
+++ b/drivers/iommu/msm_iommu_pagetable.c
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <mach/iommu.h>
+#include <mach/msm_iommu_priv.h>
#include "msm_iommu_pagetable.h"
/* Sharability attributes of MSM IOMMU mappings */
@@ -41,7 +42,7 @@
dmac_flush_range(start, end);
}
-int msm_iommu_pagetable_alloc(struct iommu_pt *pt)
+int msm_iommu_pagetable_alloc(struct msm_iommu_pt *pt)
{
pt->fl_table = (unsigned long *)__get_free_pages(GFP_KERNEL,
get_order(SZ_16K));
@@ -54,7 +55,7 @@
return 0;
}
-void msm_iommu_pagetable_free(struct iommu_pt *pt)
+void msm_iommu_pagetable_free(struct msm_iommu_pt *pt)
{
unsigned long *fl_table;
int i;
@@ -110,7 +111,7 @@
return pgprot;
}
-static unsigned long *make_second_level(struct iommu_pt *pt,
+static unsigned long *make_second_level(struct msm_iommu_pt *pt,
unsigned long *fl_pte)
{
unsigned long *sl;
@@ -194,7 +195,7 @@
return ret;
}
-int msm_iommu_pagetable_map(struct iommu_pt *pt, unsigned long va,
+int msm_iommu_pagetable_map(struct msm_iommu_pt *pt, unsigned long va,
phys_addr_t pa, size_t len, int prot)
{
unsigned long *fl_pte;
@@ -279,7 +280,7 @@
return ret;
}
-size_t msm_iommu_pagetable_unmap(struct iommu_pt *pt, unsigned long va,
+size_t msm_iommu_pagetable_unmap(struct msm_iommu_pt *pt, unsigned long va,
size_t len)
{
unsigned long *fl_pte;
@@ -370,6 +371,55 @@
return pa;
}
+static int check_range(unsigned long *fl_table, unsigned int va,
+ unsigned int len)
+{
+ unsigned int offset = 0;
+ unsigned long *fl_pte;
+ unsigned long fl_offset;
+ unsigned long *sl_table;
+ unsigned long sl_start, sl_end;
+ int i;
+
+ fl_offset = FL_OFFSET(va); /* Upper 12 bits */
+ fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
+
+ while (offset < len) {
+ if (*fl_pte & FL_TYPE_TABLE) {
+ sl_start = SL_OFFSET(va);
+ sl_table = __va(((*fl_pte) & FL_BASE_MASK));
+ sl_end = ((len - offset) / SZ_4K) + sl_start;
+
+ if (sl_end > NUM_SL_PTE)
+ sl_end = NUM_SL_PTE;
+
+ for (i = sl_start; i < sl_end; i++) {
+ if (sl_table[i] != 0) {
+ pr_err("%08x - %08x already mapped\n",
+ va, va + SZ_4K);
+ return -EBUSY;
+ }
+ offset += SZ_4K;
+ va += SZ_4K;
+ }
+
+
+ sl_start = 0;
+ } else {
+ if (*fl_pte != 0) {
+ pr_err("%08x - %08x already mapped\n",
+ va, va + SZ_1M);
+ return -EBUSY;
+ }
+ va += SZ_1M;
+ offset += SZ_1M;
+ sl_start = 0;
+ }
+ fl_pte++;
+ }
+ return 0;
+}
+
static inline int is_fully_aligned(unsigned int va, phys_addr_t pa, size_t len,
int align)
{
@@ -377,7 +427,7 @@
&& (len >= align);
}
-int msm_iommu_pagetable_map_range(struct iommu_pt *pt, unsigned int va,
+int msm_iommu_pagetable_map_range(struct msm_iommu_pt *pt, unsigned int va,
struct scatterlist *sg, unsigned int len, int prot)
{
phys_addr_t pa;
@@ -405,6 +455,10 @@
fl_pte = pt->fl_table + fl_offset; /* int pointers, 4 bytes */
pa = get_phys_addr(sg);
+ ret = check_range(pt->fl_table, va, len);
+ if (ret)
+ goto fail;
+
while (offset < len) {
chunk_size = SZ_4K;
@@ -518,7 +572,7 @@
return ret;
}
-void msm_iommu_pagetable_unmap_range(struct iommu_pt *pt, unsigned int va,
+void msm_iommu_pagetable_unmap_range(struct msm_iommu_pt *pt, unsigned int va,
unsigned int len)
{
unsigned int offset = 0;
diff --git a/drivers/iommu/msm_iommu_pagetable.h b/drivers/iommu/msm_iommu_pagetable.h
index 3266681..7513aa5 100644
--- a/drivers/iommu/msm_iommu_pagetable.h
+++ b/drivers/iommu/msm_iommu_pagetable.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -71,20 +71,17 @@
#define RCP15_PRRR(reg) MRC(reg, p15, 0, c10, c2, 0)
#define RCP15_NMRR(reg) MRC(reg, p15, 0, c10, c2, 1)
-struct iommu_pt {
- unsigned long *fl_table;
- int redirect;
-};
+struct iommu_pt;
void msm_iommu_pagetable_init(void);
-int msm_iommu_pagetable_alloc(struct iommu_pt *pt);
-void msm_iommu_pagetable_free(struct iommu_pt *pt);
-int msm_iommu_pagetable_map(struct iommu_pt *pt, unsigned long va,
+int msm_iommu_pagetable_alloc(struct msm_iommu_pt *pt);
+void msm_iommu_pagetable_free(struct msm_iommu_pt *pt);
+int msm_iommu_pagetable_map(struct msm_iommu_pt *pt, unsigned long va,
phys_addr_t pa, size_t len, int prot);
-size_t msm_iommu_pagetable_unmap(struct iommu_pt *pt, unsigned long va,
+size_t msm_iommu_pagetable_unmap(struct msm_iommu_pt *pt, unsigned long va,
size_t len);
-int msm_iommu_pagetable_map_range(struct iommu_pt *pt, unsigned int va,
+int msm_iommu_pagetable_map_range(struct msm_iommu_pt *pt, unsigned int va,
struct scatterlist *sg, unsigned int len, int prot);
-void msm_iommu_pagetable_unmap_range(struct iommu_pt *pt, unsigned int va,
+void msm_iommu_pagetable_unmap_range(struct msm_iommu_pt *pt, unsigned int va,
unsigned int len);
#endif
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 29cf0c1..5ca6fd9 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -31,6 +31,7 @@
#include <mach/iommu_perfmon.h>
#include <mach/iommu_hw-v1.h>
+#include <mach/msm_iommu_priv.h>
#include <mach/iommu.h>
#include <mach/scm.h>
@@ -45,10 +46,6 @@
static DEFINE_MUTEX(msm_iommu_lock);
-struct msm_priv {
- struct list_head list_attached;
-};
-
struct msm_scm_paddr_list {
unsigned int list;
unsigned int list_size;
@@ -88,7 +85,7 @@
return 0;
of_node_put(np);
- ret = scm_call(SCM_SVC_CP, IOMMU_SECURE_PTBL_SIZE, &spare,
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &spare,
sizeof(spare), psize, sizeof(psize));
if (ret) {
pr_err("scm call IOMMU_SECURE_PTBL_SIZE failed\n");
@@ -111,7 +108,7 @@
pinit.paddr = virt_to_phys(buf);
pinit.size = psize[0];
- ret = scm_call(SCM_SVC_CP, IOMMU_SECURE_PTBL_INIT, &pinit,
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_INIT, &pinit,
sizeof(pinit), &ptbl_ret, sizeof(ptbl_ret));
if (ret) {
pr_err("scm call IOMMU_SECURE_PTBL_INIT failed\n");
@@ -142,7 +139,7 @@
cfg.id = sec_id;
- ret = scm_call(SCM_SVC_CP, IOMMU_SECURE_CFG, &cfg, sizeof(cfg),
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_CFG, &cfg, sizeof(cfg),
&scm_ret, sizeof(scm_ret));
if (ret || scm_ret) {
pr_err("scm call IOMMU_SECURE_CFG failed\n");
@@ -167,7 +164,7 @@
map.info.va = va;
map.info.size = len;
- if (scm_call(SCM_SVC_CP, IOMMU_SECURE_MAP, &map, sizeof(map), &ret,
+ if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map), &ret,
sizeof(ret)))
return -EINVAL;
if (ret)
@@ -242,7 +239,7 @@
map.plist.size = SZ_1M;
}
- ret = scm_call(SCM_SVC_CP, IOMMU_SECURE_MAP, &map, sizeof(map),
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map),
&scm_ret, sizeof(scm_ret));
kfree(pa_list);
return ret;
@@ -260,7 +257,7 @@
mi.va = va;
mi.size = len;
- ret = scm_call(SCM_SVC_CP, IOMMU_SECURE_UNMAP, &mi, sizeof(mi),
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP, &mi, sizeof(mi),
&scm_ret, sizeof(scm_ret));
return ret;
}
@@ -298,7 +295,7 @@
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -311,7 +308,7 @@
static void msm_iommu_domain_destroy(struct iommu_domain *domain)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
mutex_lock(&msm_iommu_lock);
priv = domain->priv;
@@ -323,7 +320,7 @@
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
- struct msm_priv *priv;
+ struct msm_iommu_priv *priv;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
struct msm_iommu_ctx_drvdata *tmp_drvdata;
@@ -424,7 +421,7 @@
struct msm_iommu_drvdata **iommu_drvdata,
struct msm_iommu_ctx_drvdata **ctx_drvdata)
{
- struct msm_priv *priv = domain->priv;
+ struct msm_iommu_priv *priv = domain->priv;
struct msm_iommu_ctx_drvdata *ctx;
list_for_each_entry(ctx, &priv->list_attached, attached_elm) {
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 9e0a147..202edc0 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -142,6 +142,7 @@
#define RGB_LED_ENABLE_MASK 0xE0
#define RGB_LED_SRC_MASK 0x03
#define QPNP_LED_PWM_FLAGS (PM_PWM_LUT_LOOP | PM_PWM_LUT_RAMP_UP)
+#define QPNP_LUT_RAMP_STEP_DEFAULT 255
#define PWM_LUT_MAX_SIZE 63
#define RGB_LED_DISABLE 0x00
@@ -957,7 +958,7 @@
return -EINVAL;
}
rc = pwm_lut_config(led->rgb_cfg->pwm_dev,
- led->rgb_cfg->pwm_period_us,
+ PM_PWM_PERIOD_MIN, /* ignored by hardware */
led->rgb_cfg->duty_cycles->duty_pcts,
led->rgb_cfg->lut_params);
if (rc < 0) {
@@ -1227,11 +1228,13 @@
else
return rc;
- rc = of_property_read_u32(node, "qcom,pwm-us", &val);
- if (!rc)
- led->rgb_cfg->pwm_period_us = val;
- else
- return rc;
+ if (led->rgb_cfg->mode == RGB_MODE_PWM) {
+ rc = of_property_read_u32(node, "qcom,pwm-us", &val);
+ if (!rc)
+ led->rgb_cfg->pwm_period_us = val;
+ else
+ return rc;
+ }
if (led->rgb_cfg->mode == RGB_MODE_LPG) {
led->rgb_cfg->duty_cycles =
@@ -1243,12 +1246,6 @@
return -ENOMEM;
}
- rc = of_property_read_u32(node, "qcom,duty-ms", &val);
- if (!rc)
- led->rgb_cfg->duty_cycles->duty_ms = (u8) val;
- else
- return rc;
-
prop = of_find_property(node, "qcom,duty-pcts",
&led->rgb_cfg->duty_cycles->num_duty_pcts);
if (!prop) {
@@ -1294,12 +1291,37 @@
} else
return rc;
+ led->rgb_cfg->lut_params.lut_pause_hi = 0;
+ rc = of_property_read_u32(node, "qcom,pause-hi", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.lut_pause_hi = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.lut_pause_lo = 0;
+ rc = of_property_read_u32(node, "qcom,pause-lo", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.lut_pause_lo = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.ramp_step_ms =
+ QPNP_LUT_RAMP_STEP_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ramp-step-ms", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.ramp_step_ms = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
+ rc = of_property_read_u32(node, "qcom,lut-flags", &val);
+ if (!rc)
+ led->rgb_cfg->lut_params.flags = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
led->rgb_cfg->lut_params.idx_len =
led->rgb_cfg->duty_cycles->num_duty_pcts;
- led->rgb_cfg->lut_params.lut_pause_hi = 0;
- led->rgb_cfg->lut_params.lut_pause_lo = 0;
- led->rgb_cfg->lut_params.ramp_step_ms = 255;
- led->rgb_cfg->lut_params.flags = QPNP_LED_PWM_FLAGS;
}
return 0;
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 52b7994..dce37e5 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -121,6 +121,7 @@
events->notified_index = 0;
events->bytes_read_no_event = 0;
events->current_event_data_size = 0;
+ events->wakeup_events_counter = 0;
}
static inline void dvb_dmxdev_flush_output(struct dvb_ringbuffer *buffer,
@@ -222,6 +223,10 @@
int new_write_index;
int data_event;
+ /* Check if the event is disabled */
+ if (events->event_mask.disable_mask & event->type)
+ return 0;
+
/* Check if we are adding an event that user already read its data */
if (events->bytes_read_no_event) {
data_event = 1;
@@ -241,7 +246,7 @@
if (data_event) {
if (res) {
/*
- * Data relevent to this event was fully
+ * Data relevant to this event was fully
* consumed already, discard event.
*/
events->bytes_read_no_event -= res;
@@ -266,6 +271,9 @@
events->queue[events->write_index] = *event;
events->write_index = new_write_index;
+ if (!(events->event_mask.no_wakeup_mask & event->type))
+ events->wakeup_events_counter++;
+
return 0;
}
@@ -280,6 +288,9 @@
events->notified_index =
dvb_dmxdev_advance_event_idx(events->notified_index);
+ if (!(events->event_mask.no_wakeup_mask & event->type))
+ events->wakeup_events_counter--;
+
return 0;
}
@@ -291,6 +302,13 @@
int data_event;
/*
+ * If data events are not enabled on this filter,
+ * there's nothing to update.
+ */
+ if (events->data_read_event_masked)
+ return 0;
+
+ /*
* Go through all events that were notified and
* remove them from the events queue if their respective
* data was read.
@@ -364,7 +382,7 @@
if (data_event) {
if (res) {
/*
- * Data relevent to this event was
+ * Data relevant to this event was
* fully consumed, remove it from the queue.
*/
bytes_read -= res;
@@ -616,6 +634,9 @@
}
dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
dvb_dmxdev_flush_events(&dmxdev->dvr_output_events);
+ dmxdev->dvr_output_events.event_mask.disable_mask = 0;
+ dmxdev->dvr_output_events.event_mask.no_wakeup_mask = 0;
+ dmxdev->dvr_output_events.event_mask.wakeup_threshold = 1;
dmxdev->dvr_feeds_count = 0;
dmxdev->dvr_buffer_mode = DMX_BUFFER_MODE_INTERNAL;
dmxdev->dvr_priv_buff_handle = NULL;
@@ -1429,24 +1450,58 @@
static int dvb_dmxdev_reuse_decoder_buf(struct dmxdev_filter *dmxdevfilter,
int cookie)
{
- if ((dmxdevfilter->type == DMXDEV_TYPE_PES) &&
- (dmxdevfilter->params.pes.output == DMX_OUT_DECODER)) {
- struct dmxdev_feed *feed;
- int ret = -ENODEV;
+ struct dmxdev_feed *feed;
- /* Only one feed should be in the list in case of decoder */
- feed = list_first_entry(&dmxdevfilter->feed.ts,
- struct dmxdev_feed, next);
+ if ((dmxdevfilter->type != DMXDEV_TYPE_PES) ||
+ (dmxdevfilter->params.pes.output != DMX_OUT_DECODER) ||
+ (dmxdevfilter->events.event_mask.disable_mask &
+ DMX_EVENT_NEW_ES_DATA))
+ return -EPERM;
- if (feed->ts->reuse_decoder_buffer)
- ret = feed->ts->reuse_decoder_buffer(
- feed->ts,
- cookie);
+ /* Only one feed should be in the list in case of decoder */
+ feed = list_first_entry(&dmxdevfilter->feed.ts,
+ struct dmxdev_feed, next);
- return ret;
- }
+ if (feed->ts->reuse_decoder_buffer)
+ return feed->ts->reuse_decoder_buffer(feed->ts, cookie);
- return -EPERM;
+ return -ENODEV;
+}
+
+static int dvb_dmxdev_set_event_mask(struct dmxdev_filter *dmxdevfilter,
+ struct dmx_events_mask *event_mask)
+{
+ if (!event_mask ||
+ (event_mask->wakeup_threshold >= DMX_EVENT_QUEUE_SIZE))
+ return -EINVAL;
+
+ if (dmxdevfilter->state == DMXDEV_STATE_GO)
+ return -EBUSY;
+
+ /*
+ * Overflow event is not allowed to be masked.
+ * This is because if overflow occurs, demux stops outputting data
+ * until user is notified. If user is using events to read the data,
+ * the overflow event must be always enabled or otherwise we would
+ * never recover from overflow state.
+ */
+ event_mask->disable_mask &= ~(u32)DMX_EVENT_BUFFER_OVERFLOW;
+ event_mask->no_wakeup_mask &= ~(u32)DMX_EVENT_BUFFER_OVERFLOW;
+
+ dmxdevfilter->events.event_mask = *event_mask;
+
+ return 0;
+}
+
+static int dvb_dmxdev_get_event_mask(struct dmxdev_filter *dmxdevfilter,
+ struct dmx_events_mask *event_mask)
+{
+ if (!event_mask)
+ return -EINVAL;
+
+ *event_mask = dmxdevfilter->events.event_mask;
+
+ return 0;
}
static int dvb_dmxdev_ts_fullness_callback(
@@ -1708,11 +1763,13 @@
}
/*
- * Decoder filters have no data in the data buffer and their
- * events can be removed now from the queue.
+ * If no-data events are enabled on this filter,
+ * the events can be removed from the queue when
+ * user gets them.
+ * For filters with data events enabled, the event is removed
+ * from the queue only when the respective data is read.
*/
- if ((dmxdevfilter->type == DMXDEV_TYPE_PES) &&
- (dmxdevfilter->params.pes.output == DMX_OUT_DECODER))
+ if (dmxdevfilter->events.data_read_event_masked)
dmxdevfilter->events.read_index =
dvb_dmxdev_advance_event_idx(
dmxdevfilter->events.read_index);
@@ -2538,6 +2595,9 @@
(*secfilter)->filter_mask[2] = 0;
filter->todo = 0;
+ filter->events.data_read_event_masked =
+ filter->events.event_mask.disable_mask &
+ DMX_EVENT_NEW_SECTION;
ret = filter->feed.sec.feed->start_filtering(
filter->feed.sec.feed);
@@ -2558,6 +2618,21 @@
filter->params.pes.rec_chunk_size =
filter->buffer.size >> 2;
+ if (filter->params.pes.output == DMX_OUT_TS_TAP)
+ dmxdev->dvr_output_events.data_read_event_masked =
+ dmxdev->dvr_output_events.event_mask.disable_mask &
+ DMX_EVENT_NEW_REC_CHUNK;
+ else if (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP)
+ filter->events.data_read_event_masked =
+ filter->events.event_mask.disable_mask &
+ DMX_EVENT_NEW_REC_CHUNK;
+ else if (filter->params.pes.output == DMX_OUT_TAP)
+ filter->events.data_read_event_masked =
+ filter->events.event_mask.disable_mask &
+ DMX_EVENT_NEW_PES;
+ else
+ filter->events.data_read_event_masked = 1;
+
ret = 0;
list_for_each_entry(feed, &filter->feed.ts, next) {
ret = dvb_dmxdev_start_feed(dmxdev, filter, feed);
@@ -2627,6 +2702,9 @@
dmxdevfilter->priv_buff_handle = NULL;
dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
dvb_dmxdev_flush_events(&dmxdevfilter->events);
+ dmxdevfilter->events.event_mask.disable_mask = DMX_EVENT_NEW_ES_DATA;
+ dmxdevfilter->events.event_mask.no_wakeup_mask = 0;
+ dmxdevfilter->events.event_mask.wakeup_threshold = 1;
dmxdevfilter->type = DMXDEV_TYPE_NONE;
dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
@@ -3223,6 +3301,24 @@
mutex_unlock(&dmxdevfilter->mutex);
break;
+ case DMX_SET_EVENTS_MASK:
+ if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+ mutex_unlock(&dmxdev->mutex);
+ return -ERESTARTSYS;
+ }
+ ret = dvb_dmxdev_set_event_mask(dmxdevfilter, parg);
+ mutex_unlock(&dmxdevfilter->mutex);
+ break;
+
+ case DMX_GET_EVENTS_MASK:
+ if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+ mutex_unlock(&dmxdev->mutex);
+ return -ERESTARTSYS;
+ }
+ ret = dvb_dmxdev_get_event_mask(dmxdevfilter, parg);
+ mutex_unlock(&dmxdevfilter->mutex);
+ break;
+
default:
ret = -EINVAL;
break;
@@ -3258,10 +3354,9 @@
if (!dvb_ringbuffer_empty(&dmxdevfilter->buffer))
mask |= (POLLIN | POLLRDNORM);
- if (dmxdevfilter->events.notified_index !=
- dmxdevfilter->events.write_index) {
+ if (dmxdevfilter->events.wakeup_events_counter >=
+ dmxdevfilter->events.event_mask.wakeup_threshold)
mask |= POLLPRI;
- }
return mask;
}
@@ -3430,8 +3525,8 @@
if (!dvb_ringbuffer_empty(&dmxdev->dvr_buffer))
mask |= (POLLIN | POLLRDNORM);
- if (dmxdev->dvr_output_events.notified_index !=
- dmxdev->dvr_output_events.write_index)
+ if (dmxdev->dvr_output_events.wakeup_events_counter >=
+ dmxdev->dvr_output_events.event_mask.wakeup_threshold)
mask |= POLLPRI;
} else {
poll_wait(file, &dmxdev->dvr_input_buffer.queue, wait);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index a55b4f0..1443de5 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -68,8 +68,8 @@
struct dmx_section_feed *feed;
};
-struct dmxdev_events_queue {
#define DMX_EVENT_QUEUE_SIZE 500 /* number of events */
+struct dmxdev_events_queue {
/*
* indices used to manage events queue.
* read_index advanced when relevent data is read
@@ -94,6 +94,22 @@
u32 current_event_data_size;
u32 current_event_start_offset;
+ /* current setting of the events masking */
+ struct dmx_events_mask event_mask;
+
+ /*
+ * indicates if an event used for data-reading from demux
+ * filter is enabled or not. These are events on which
+ * user may wait for before calling read() on the demux filter.
+ */
+ int data_read_event_masked;
+
+ /*
+ * holds the current number of pending events in the
+ * events queue that are considered as a wake-up source
+ */
+ u32 wakeup_events_counter;
+
struct dmx_filter_event queue[DMX_EVENT_QUEUE_SIZE];
};
diff --git a/drivers/media/platform/msm/camera_v1/msm_v4l2_video.c b/drivers/media/platform/msm/camera_v1/msm_v4l2_video.c
index 96f968c..1849bf6 100644
--- a/drivers/media/platform/msm/camera_v1/msm_v4l2_video.c
+++ b/drivers/media/platform/msm/camera_v1/msm_v4l2_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -104,13 +104,22 @@
mdp_format = MDP_RGB_888;
break;
case V4L2_PIX_FMT_NV12:
- mdp_format = MDP_Y_CRCB_H2V2;
- break;
- case V4L2_PIX_FMT_NV21:
mdp_format = MDP_Y_CBCR_H2V2;
break;
+ case V4L2_PIX_FMT_NV21:
+ mdp_format = MDP_Y_CRCB_H2V2;
+ break;
case V4L2_PIX_FMT_YUV420:
- mdp_format = MDP_Y_CR_CB_H2V2;
+ mdp_format = MDP_Y_CB_CR_H2V2;
+ break;
+ case V4L2_PIX_FMT_UYVY:
+ mdp_format = MDP_CBYCRY_H2V1;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ mdp_format = MDP_YCBYCR_H2V1;
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ mdp_format = MDP_Y_CR_CB_GH2V2;
break;
default:
pr_err("%s:Unrecognized format %u\n", __func__, pixelformat);
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index e4777e6..269e538 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -100,6 +100,15 @@
hfr video at 60, 90 and 120 fps. This sensor driver does
not support auto focus.
+config OV9724
+ bool "Sensor OV9724 (BAYER 2M)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 2 MP Bayer Sensor, supports 2 mipi lanes,
+ preview and snapshot config at 1280*720 at 30 fps,
+ hfr video at 60, 90 and 120 fps. This sensor driver does
+ not support auto focus.
+
config MT9M114
bool "Sensor MT9M114 (YUV 1.26MP)"
depends on MSMB_CAMERA
@@ -109,6 +118,15 @@
1280 * 270. It does not support auto focus. It supports
few special effects like saturation.
+config OV8825
+ bool "OmniVision OV8825 (BAYER 8MP)"
+ depends on MSMB_CAMERA
+ ---help---
+ OmniVision 8 MP Bayer Sensor with auto focus.uses
+ 2 mipi lanes, preview config = 1632*1224 30 fps,
+ snapshot config = 3264 * 2448 at 18 fps.
+ 2 lanes max fps is 18, 4 lanes max fps is 24.
+
config MSM_V4L2_VIDEO_OVERLAY_DEVICE
tristate "Qualcomm MSM V4l2 video overlay device"
---help---
@@ -119,7 +137,7 @@
config MSMB_JPEG
tristate "Qualcomm MSM Jpeg Encoder Engine support"
- depends on MSMB_CAMERA && ARCH_MSM8974
+ depends on MSMB_CAMERA && (ARCH_MSM8974 || ARCH_MSM8226)
---help---
Enable support for Jpeg Encoder/Decoder
Engine for 8974.
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 6b27048..32aa4ef 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -42,7 +42,7 @@
};
static void camera_pack_event(struct file *filep, int evt_id,
- int command, struct v4l2_event *event)
+ int command, int value, struct v4l2_event *event)
{
struct msm_v4l2_event_data *event_data =
(struct msm_v4l2_event_data *)&event->u.data[0];
@@ -55,6 +55,7 @@
event_data->command = command;
event_data->session_id = pvdev->vdev->num;
event_data->stream_id = sp->stream_id;
+ event_data->arg_value = value;
}
static int camera_check_event_status(struct v4l2_event *event)
@@ -76,7 +77,7 @@
/* can use cap->driver to make differentiation */
camera_pack_event(filep, MSM_CAMERA_GET_PARM,
- MSM_CAMERA_PRIV_QUERY_CAP, &event);
+ MSM_CAMERA_PRIV_QUERY_CAP, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -96,7 +97,7 @@
if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_S_CROP, &event);
+ MSM_CAMERA_PRIV_S_CROP, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -116,7 +117,7 @@
if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
camera_pack_event(filep, MSM_CAMERA_GET_PARM,
- MSM_CAMERA_PRIV_G_CROP, &event);
+ MSM_CAMERA_PRIV_G_CROP, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -137,7 +138,7 @@
if (ctrl->type == V4L2_CTRL_TYPE_MENU) {
camera_pack_event(filep, MSM_CAMERA_GET_PARM,
- ctrl->id, &event);
+ ctrl->id, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -156,7 +157,8 @@
struct v4l2_event event;
if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
- camera_pack_event(filep, MSM_CAMERA_GET_PARM, ctrl->id, &event);
+ camera_pack_event(filep, MSM_CAMERA_GET_PARM, ctrl->id, -1,
+ &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -173,13 +175,16 @@
{
int rc = 0;
struct v4l2_event event;
+ struct msm_v4l2_event_data *event_data;
if (ctrl->id >= V4L2_CID_PRIVATE_BASE) {
- camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id, &event);
+ camera_pack_event(filep, MSM_CAMERA_SET_PARM, ctrl->id,
+ ctrl->value, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
return rc;
-
+ event_data = (struct msm_v4l2_event_data *)event.u.data;
+ ctrl->value = event_data->ret_value;
rc = camera_check_event_status(&event);
}
@@ -225,7 +230,7 @@
rc = vb2_streamon(&sp->vb2_q, buf_type);
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_STREAM_ON, &event);
+ MSM_CAMERA_PRIV_STREAM_ON, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -243,7 +248,7 @@
struct camera_v4l2_private *sp = fh_to_private(fh);
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_STREAM_OFF, &event);
+ MSM_CAMERA_PRIV_STREAM_OFF, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -263,7 +268,7 @@
struct v4l2_event event;
camera_pack_event(filep, MSM_CAMERA_GET_PARM,
- MSM_CAMERA_PRIV_G_FMT, &event);
+ MSM_CAMERA_PRIV_G_FMT, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -300,7 +305,7 @@
user_fmt->plane_sizes[i]);
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_S_FMT, &event);
+ MSM_CAMERA_PRIV_S_FMT, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
@@ -342,7 +347,7 @@
struct camera_v4l2_private *sp = fh_to_private(fh);
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_NEW_STREAM, &event);
+ MSM_CAMERA_PRIV_NEW_STREAM, -1, &event);
rc = msm_create_stream(event_data->session_id,
event_data->stream_id, &sp->vb2_q);
@@ -510,7 +515,7 @@
if (rc < 0)
goto command_ack_q_fail;
- camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, &event);
+ camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);
rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
if (rc < 0)
goto post_fail;
@@ -568,7 +573,7 @@
if (atomic_read(&pvdev->opened) == 0) {
- camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, &event);
+ camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, -1, &event);
/* Donot wait, imaging server may have crashed */
msm_post_event(&event, -1);
@@ -579,7 +584,7 @@
} else {
camera_pack_event(filep, MSM_CAMERA_SET_PARM,
- MSM_CAMERA_PRIV_DEL_STREAM, &event);
+ MSM_CAMERA_PRIV_DEL_STREAM, -1, &event);
/* Donot wait, imaging server may have crashed */
msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 3a24428..22e8400 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -169,6 +169,8 @@
struct msm_isp_qbuf_info *info, struct vb2_buffer *vb2_buf)
{
int rc = -1;
+ unsigned long flags;
+ struct msm_isp_bufq *bufq = NULL;
struct msm_isp_buffer *buf_info = NULL;
struct v4l2_buffer *buf = NULL;
struct v4l2_plane *plane = NULL;
@@ -180,14 +182,26 @@
return rc;
}
- if (buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED)
- return buf_info->state;
+ bufq = msm_isp_get_bufq(buf_mgr, buf_info->bufq_handle);
+ if (!bufq) {
+ pr_err("%s: Invalid bufq\n", __func__);
+ return rc;
+ }
+
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
+ if (buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
+ rc = buf_info->state;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
+ return rc;
+ }
if (buf_info->state != MSM_ISP_BUFFER_STATE_INITIALIZED) {
pr_err("%s: Invalid buffer state: %d\n",
__func__, buf_info->state);
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
return rc;
}
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
if (vb2_buf) {
buf = &vb2_buf->v4l2_buf;
@@ -217,7 +231,9 @@
kfree(plane);
return rc;
}
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
buf_info->state = MSM_ISP_BUFFER_STATE_PREPARED;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
kfree(plane);
return rc;
}
@@ -245,10 +261,11 @@
return 0;
}
-static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr,
+static int msm_isp_get_buf(struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
uint32_t bufq_handle, struct msm_isp_buffer **buf_info)
{
int rc = -1;
+ unsigned long flags;
struct msm_isp_buffer *temp_buf_info;
struct msm_isp_bufq *bufq = NULL;
struct vb2_buffer *vb2_buf = NULL;
@@ -259,6 +276,25 @@
}
*buf_info = NULL;
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ list_for_each_entry(temp_buf_info,
+ &bufq->share_head, share_list) {
+ if (!temp_buf_info->buf_used[id]) {
+ *buf_info = temp_buf_info;
+ temp_buf_info->buf_used[id] = 1;
+ temp_buf_info->buf_get_count++;
+ if (temp_buf_info->buf_get_count ==
+ bufq->buf_client_count)
+ list_del_init(
+ &temp_buf_info->share_list);
+ spin_unlock_irqrestore(
+ &bufq->bufq_lock, flags);
+ return 0;
+ }
+ }
+ }
+
if (BUF_SRC(bufq->stream_id)) {
list_for_each_entry(temp_buf_info, &bufq->head, list) {
if (temp_buf_info->state ==
@@ -280,16 +316,26 @@
} else {
pr_err("%s: Incorrect buf index %d\n",
__func__, vb2_buf->v4l2_buf.index);
- return -EINVAL;
+ rc = -EINVAL;
}
}
}
- if (!(*buf_info))
+ if (!(*buf_info)) {
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
return rc;
-
+ }
(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ memset((*buf_info)->buf_used, 0,
+ sizeof(uint8_t) * bufq->buf_client_count);
+ (*buf_info)->buf_used[id] = 1;
+ (*buf_info)->buf_get_count = 1;
+ (*buf_info)->buf_put_count = 0;
+ list_add_tail(&(*buf_info)->share_list, &bufq->share_head);
+ }
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
return 0;
}
@@ -297,6 +343,7 @@
uint32_t bufq_handle, uint32_t buf_index)
{
int rc = -1;
+ unsigned long flags;
struct msm_isp_bufq *bufq = NULL;
struct msm_isp_buffer *buf_info = NULL;
@@ -312,6 +359,7 @@
return rc;
}
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
switch (buf_info->state) {
case MSM_ISP_BUFFER_STATE_PREPARED:
case MSM_ISP_BUFFER_STATE_DEQUEUED:
@@ -330,6 +378,7 @@
__func__, buf_info->state);
break;
}
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
return rc;
}
@@ -339,8 +388,10 @@
struct timeval *tv, uint32_t frame_id)
{
int rc = -1;
+ unsigned long flags;
struct msm_isp_bufq *bufq = NULL;
struct msm_isp_buffer *buf_info = NULL;
+ enum msm_isp_buffer_state state;
bufq = msm_isp_get_bufq(buf_mgr, bufq_handle);
if (!bufq) {
@@ -354,9 +405,23 @@
return rc;
}
- if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
- buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
+ state = buf_info->state;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
+
+ if (state == MSM_ISP_BUFFER_STATE_DEQUEUED ||
+ state == MSM_ISP_BUFFER_STATE_DIVERTED) {
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ buf_info->buf_put_count++;
+ if (buf_info->buf_put_count != ISP_SHARE_BUF_CLIENT) {
+ rc = buf_info->buf_put_count;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
+ return rc;
+ }
+ }
buf_info->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
if ((BUF_SRC(bufq->stream_id))) {
rc = msm_isp_put_buf(buf_mgr, buf_info->bufq_handle,
buf_info->buf_idx);
@@ -379,6 +444,7 @@
uint32_t bufq_handle, enum msm_isp_buffer_flush_t flush_type)
{
int rc = -1, i;
+ unsigned long flags;
struct msm_isp_bufq *bufq = NULL;
struct msm_isp_buffer *buf_info = NULL;
@@ -395,6 +461,7 @@
continue;
}
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
if (flush_type == MSM_ISP_BUFFER_FLUSH_DIVERTED &&
buf_info->state == MSM_ISP_BUFFER_STATE_DIVERTED) {
buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
@@ -404,6 +471,7 @@
buf_info->state == MSM_ISP_BUFFER_STATE_DISPATCHED)) {
buf_info->state = MSM_ISP_BUFFER_STATE_QUEUED;
}
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
}
return 0;
}
@@ -413,6 +481,7 @@
struct timeval *tv, uint32_t frame_id)
{
int rc = -1;
+ unsigned long flags;
struct msm_isp_bufq *bufq = NULL;
struct msm_isp_buffer *buf_info = NULL;
@@ -428,11 +497,22 @@
return rc;
}
+ spin_lock_irqsave(&bufq->bufq_lock, flags);
+ if (bufq->buf_type == ISP_SHARE_BUF) {
+ buf_info->buf_put_count++;
+ if (buf_info->buf_put_count != ISP_SHARE_BUF_CLIENT) {
+ rc = buf_info->buf_put_count;
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
+ return rc;
+ }
+ }
+
if (buf_info->state == MSM_ISP_BUFFER_STATE_DEQUEUED) {
buf_info->state = MSM_ISP_BUFFER_STATE_DIVERTED;
buf_info->tv = tv;
buf_info->frame_id = frame_id;
}
+ spin_unlock_irqrestore(&bufq->bufq_lock, flags);
return 0;
}
@@ -516,11 +596,16 @@
return rc;
}
+ spin_lock_init(&bufq->bufq_lock);
bufq->bufq_handle = buf_request->handle;
bufq->session_id = buf_request->session_id;
bufq->stream_id = buf_request->stream_id;
bufq->num_bufs = buf_request->num_buf;
+ bufq->buf_type = buf_request->buf_type;
+ if (bufq->buf_type == ISP_SHARE_BUF)
+ bufq->buf_client_count = ISP_SHARE_BUF_CLIENT;
INIT_LIST_HEAD(&bufq->head);
+ INIT_LIST_HEAD(&bufq->share_head);
for (i = 0; i < buf_request->num_buf; i++) {
bufq->bufs[i].state = MSM_ISP_BUFFER_STATE_INITIALIZED;
bufq->bufs[i].bufq_handle = bufq->bufq_handle;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
index c3b97d9..d4e7c88 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h
@@ -19,6 +19,7 @@
/*Buffer source can be from userspace / HAL*/
#define BUF_SRC(id) (id & ISP_NATIVE_BUF_BIT)
+#define ISP_SHARE_BUF_CLIENT 2
struct msm_isp_buf_mgr;
@@ -59,6 +60,11 @@
/*Vb2 buffer data*/
struct vb2_buffer *vb2_buf;
+ /*Share buffer cache state*/
+ struct list_head share_list;
+ uint8_t buf_used[ISP_SHARE_BUF_CLIENT];
+ uint8_t buf_get_count;
+ uint8_t buf_put_count;
};
struct msm_isp_bufq {
@@ -66,10 +72,15 @@
uint32_t stream_id;
uint32_t num_bufs;
uint32_t bufq_handle;
+ enum msm_isp_buf_type buf_type;
struct msm_isp_buffer *bufs;
+ spinlock_t bufq_lock;
/*Native buffer queue*/
struct list_head head;
+ /*Share buffer cache queue*/
+ struct list_head share_head;
+ uint8_t buf_client_count;
};
struct msm_isp_buf_ops {
@@ -85,7 +96,7 @@
int (*get_bufq_handle) (struct msm_isp_buf_mgr *buf_mgr,
uint32_t session_id, uint32_t stream_id);
- int (*get_buf) (struct msm_isp_buf_mgr *buf_mgr,
+ int (*get_buf) (struct msm_isp_buf_mgr *buf_mgr, uint32_t id,
uint32_t bufq_handle, struct msm_isp_buffer **buf_info);
int (*put_buf) (struct msm_isp_buf_mgr *buf_mgr,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 38130db..cfbe29c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -228,6 +228,7 @@
enum msm_vfe_axi_stream_src stream_src;
uint8_t num_planes;
uint8_t wm[MAX_PLANES_PER_STREAM];
+ uint32_t plane_offset[MAX_PLANES_PER_STREAM];
uint8_t comp_mask_index;
struct msm_isp_buffer *buf[2];
uint32_t session_id;
@@ -312,6 +313,7 @@
uint32_t framedrop_pattern;
uint32_t irq_subsample_pattern;
+ uint32_t buffer_offset;
struct msm_isp_buffer *buf[2];
uint32_t bufq_handle;
};
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index f08644f..f1bfd68 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -64,7 +64,7 @@
int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data,
struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
{
- int rc = -1;
+ int rc = -1, i;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
(stream_cfg_cmd->axi_stream_handle & 0xFF)];
@@ -98,6 +98,8 @@
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
stream_info->num_planes = 2;
break;
/*TD: Add more image format*/
@@ -129,6 +131,10 @@
return rc;
}
+ for (i = 0; i < stream_info->num_planes; i++)
+ stream_info->plane_offset[i] =
+ stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+
stream_info->stream_src = stream_cfg_cmd->stream_src;
stream_info->frame_based = stream_cfg_cmd->frame_base;
return 0;
@@ -184,6 +190,11 @@
size = plane_cfg[plane_idx].output_height *
plane_cfg[plane_idx].output_width / 2;
break;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ size = plane_cfg[plane_idx].output_height *
+ plane_cfg[plane_idx].output_width;
+ break;
/*TD: Add more image format*/
default:
pr_err("%s: Invalid output format\n", __func__);
@@ -596,8 +607,9 @@
struct msm_isp_buffer *buf = stream_info->buf[1];
for (i = 0; i < stream_info->num_planes; i++)
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
- vfe_dev, stream_info->wm[i],
- VFE_PING_FLAG, buf->mapped_info[i].paddr);
+ vfe_dev, stream_info->wm[i],
+ VFE_PING_FLAG, buf->mapped_info[i].paddr +
+ stream_info->plane_offset[i]);
stream_info->buf[0] = buf;
}
@@ -626,8 +638,8 @@
uint32_t bufq_handle = stream_info->bufq_handle;
uint32_t stream_idx = stream_info->stream_handle & 0xFF;
- rc = vfe_dev->buf_mgr->ops->get_buf(
- vfe_dev->buf_mgr, bufq_handle, &buf);
+ rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
+ vfe_dev->pdev->id, bufq_handle, &buf);
if (rc < 0) {
vfe_dev->error_info.
stream_framedrop_count[stream_idx]++;
@@ -642,8 +654,9 @@
for (i = 0; i < stream_info->num_planes; i++)
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
- vfe_dev, stream_info->wm[i],
- pingpong_status, buf->mapped_info[i].paddr);
+ vfe_dev, stream_info->wm[i],
+ pingpong_status, buf->mapped_info[i].paddr +
+ stream_info->plane_offset[i]);
pingpong_bit = (~(pingpong_status >> stream_info->wm[0]) & 0x1);
stream_info->buf[pingpong_bit] = buf;
@@ -658,6 +671,7 @@
struct msm_vfe_axi_stream *stream_info, struct msm_isp_buffer *buf,
struct msm_isp_timestamp *ts)
{
+ int rc;
struct msm_isp_event_data buf_event;
uint32_t stream_idx = stream_info->stream_handle & 0xFF;
uint32_t frame_id = vfe_dev->axi_data.
@@ -665,20 +679,27 @@
if (buf && ts) {
if (stream_info->buf_divert) {
- vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
+ rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
buf->bufq_handle, buf->buf_idx,
&ts->buf_time, frame_id);
- buf_event.frame_id = frame_id;
- buf_event.timestamp = ts->buf_time;
- buf_event.u.buf_done.session_id =
- stream_info->session_id;
- buf_event.u.buf_done.stream_id =
- stream_info->stream_id;
- buf_event.u.buf_done.handle =
- stream_info->bufq_handle;
- buf_event.u.buf_done.buf_idx = buf->buf_idx;
- msm_isp_send_event(vfe_dev, ISP_EVENT_BUF_DIVERT +
- stream_idx, &buf_event);
+ /* Buf divert return value represent whether the buf
+ * can be diverted. A positive return value means
+ * other ISP hardware is still processing the frame.
+ */
+ if (rc == 0) {
+ buf_event.frame_id = frame_id;
+ buf_event.timestamp = ts->buf_time;
+ buf_event.u.buf_done.session_id =
+ stream_info->session_id;
+ buf_event.u.buf_done.stream_id =
+ stream_info->stream_id;
+ buf_event.u.buf_done.handle =
+ stream_info->bufq_handle;
+ buf_event.u.buf_done.buf_idx = buf->buf_idx;
+ msm_isp_send_event(vfe_dev,
+ ISP_EVENT_BUF_DIVERT + stream_idx,
+ &buf_event);
+ }
} else {
vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
buf->bufq_handle, buf->buf_idx,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index a29fe9c..c47209f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -27,8 +27,8 @@
vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset;
pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);
- rc = vfe_dev->buf_mgr->ops->get_buf(
- vfe_dev->buf_mgr, bufq_handle, &buf);
+ rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
+ vfe_dev->pdev->id, bufq_handle, &buf);
if (rc < 0) {
vfe_dev->error_info.stats_framedrop_count[
STATS_IDX(stream_info->stream_handle)]++;
@@ -43,7 +43,8 @@
vfe_dev->hw_info->vfe_ops.stats_ops.update_ping_pong_addr(
vfe_dev, stream_info,
- pingpong_status, buf->mapped_info[0].paddr);
+ pingpong_status, buf->mapped_info[0].paddr +
+ stream_info->buffer_offset);
if (stream_info->buf[pingpong_bit] && done_buf)
*done_buf = stream_info->buf[pingpong_bit];
@@ -60,7 +61,7 @@
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
{
- int i;
+ int i, rc;
struct msm_isp_event_data buf_event;
struct msm_isp_stats_event *stats_event = &buf_event.u.stats;
struct msm_isp_buffer *done_buf;
@@ -93,13 +94,17 @@
msm_isp_stats_cfg_ping_pong_address(vfe_dev,
stream_info, pingpong_status, &done_buf);
if (done_buf) {
- stats_event->stats_mask |= 1 << stream_info->stats_type;
- stats_event->stats_buf_idxs[stream_info->stats_type] =
- done_buf->buf_idx;
- vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
+ rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
done_buf->bufq_handle, done_buf->buf_idx,
&ts->buf_time, vfe_dev->axi_data.
src_info[VFE_PIX_0].frame_id);
+ if (rc == 0) {
+ stats_event->stats_mask |=
+ 1 << stream_info->stats_type;
+ stats_event->stats_buf_idxs[
+ stream_info->stats_type] =
+ done_buf->buf_idx;
+ }
}
}
@@ -166,6 +171,7 @@
stream_info->session_id = stream_req_cmd->session_id;
stream_info->stream_id = stream_req_cmd->stream_id;
stream_info->stats_type = stream_req_cmd->stats_type;
+ stream_info->buffer_offset = stream_req_cmd->buffer_offset;
stream_info->framedrop_pattern = stream_req_cmd->framedrop_pattern;
stream_info->irq_subsample_pattern =
stream_req_cmd->irq_subsample_pattern;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index f337e27..ae89500 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -418,6 +418,8 @@
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
val = CAL_WORD(pixel_per_line, 1, 8);
break;
/*TD: Add more image format*/
@@ -461,6 +463,9 @@
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
return 8;
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ return 16;
/*TD: Add more image format*/
default:
pr_err("%s: Invalid output format\n", __func__);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 691edc3..85788e9 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -19,6 +19,7 @@
#include <linux/videodev2.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <media/msmb_isp.h>
#include "msm_ispif.h"
#include "msm.h"
@@ -59,6 +60,79 @@
false : true;
}
+static struct msm_cam_clk_info ispif_8960_clk_info[] = {
+ {"csi_pix_clk", 0},
+ {"csi_rdi_clk", 0},
+ {"csi_pix1_clk", 0},
+ {"csi_rdi1_clk", 0},
+ {"csi_rdi2_clk", 0},
+};
+
+static struct msm_cam_clk_info ispif_8974_clk_info_vfe0[] = {
+ {"camss_vfe_vfe_clk", -1},
+ {"camss_csi_vfe_clk", -1},
+};
+
+static struct msm_cam_clk_info ispif_8974_clk_info_vfe1[] = {
+ {"camss_vfe_vfe_clk1", -1},
+ {"camss_csi_vfe_clk1", -1},
+};
+
+static int msm_ispif_clk_enable(struct ispif_device *ispif,
+ enum msm_ispif_vfe_intf vfe_intf, int enable)
+{
+ int rc = 0;
+
+ if (enable)
+ pr_debug("enable clk for VFE%d\n", vfe_intf);
+ else
+ pr_debug("disable clk for VFE%d\n", vfe_intf);
+
+ if (ispif->csid_version < CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk[vfe_intf], 2, enable);
+ if (rc) {
+ pr_err("%s: cannot enable clock, error = %d\n",
+ __func__, rc);
+ goto end;
+ }
+ } else if (ispif->csid_version == CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk[vfe_intf],
+ ARRAY_SIZE(ispif_8960_clk_info),
+ enable);
+ if (rc) {
+ pr_err("%s: cannot enable clock, error = %d\n",
+ __func__, rc);
+ goto end;
+ }
+ } else if (ispif->csid_version >= CSID_VERSION_V3) {
+ if (vfe_intf == VFE0) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_clk_info_vfe0,
+ ispif->ispif_clk[vfe_intf],
+ ARRAY_SIZE(ispif_8974_clk_info_vfe0), enable);
+ } else {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_clk_info_vfe1,
+ ispif->ispif_clk[vfe_intf],
+ ARRAY_SIZE(ispif_8974_clk_info_vfe1), enable);
+ }
+ if (rc) {
+ pr_err("%s: cannot enable clock, error = %d\n",
+ __func__, rc);
+ goto end;
+ }
+ } else {
+ pr_err("%s: unsupported version=%d\n", __func__,
+ ispif->csid_version);
+ goto end;
+ }
+
+end:
+ return rc;
+}
+
static int msm_ispif_intf_reset(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
@@ -97,8 +171,8 @@
unsigned long flags;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout = 0;
- init_completion(&ispif->reset_complete);
+ ispif->wait_timeout[params->vfe_intf] = 0;
+ init_completion(&ispif->reset_complete[params->vfe_intf]);
spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
if (params->vfe_intf == VFE0)
@@ -106,14 +180,15 @@
else
msm_camera_io_w(data, ispif->base +
ISPIF_RST_CMD_1_ADDR);
+
lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete, jiffes);
+ &ispif->reset_complete[params->vfe_intf], jiffes);
if (lrc < 0 || !lrc) {
pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout = 1;
+ ispif->wait_timeout[params->vfe_intf] = 1;
spin_unlock_irqrestore(
&ispif->auto_complete_lock, flags);
}
@@ -129,8 +204,13 @@
unsigned long flags;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout = 0;
- init_completion(&ispif->reset_complete);
+ ispif->wait_timeout[VFE0] = 0;
+ init_completion(&ispif->reset_complete[VFE0]);
+ if (ispif->csid_version >= CSID_VERSION_V3 &&
+ ispif->vfe_info.num_vfe > 1) {
+ ispif->wait_timeout[VFE1] = 0;
+ init_completion(&ispif->reset_complete[VFE1]);
+ }
spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
BUG_ON(!ispif);
@@ -139,22 +219,41 @@
msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
- if (ispif->csid_version >= CSID_VERSION_V3)
- msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base +
- ISPIF_RST_CMD_1_ADDR);
-
lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete, jiffes);
+ &ispif->reset_complete[VFE0], jiffes);
if (lrc < 0 || !lrc) {
pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout = 1;
+ ispif->wait_timeout[VFE0] = 1;
spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
+
+ goto end;
}
+ if (ispif->csid_version >= CSID_VERSION_V3 &&
+ ispif->vfe_info.num_vfe > 1) {
+ msm_camera_io_w_mb(ISPIF_RST_CMD_1_MASK, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
+
+ lrc = wait_for_completion_interruptible_timeout(
+ &ispif->reset_complete[VFE1], jiffes);
+
+ if (lrc < 0 || !lrc) {
+ pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+ rc = -EIO;
+
+ spin_lock_irqsave(&ispif->auto_complete_lock, flags);
+ ispif->wait_timeout[VFE1] = 1;
+ spin_unlock_irqrestore(&ispif->auto_complete_lock,
+ flags);
+ }
+
+ }
+
+end:
return rc;
}
@@ -181,20 +280,19 @@
}
if (ispif->csid_version <= CSID_VERSION_V2) {
- if (ispif->ispif_clk[intftype] == NULL) {
+ if (ispif->ispif_clk[vfe_intf][intftype] == NULL) {
CDBG("%s: ispif NULL clk\n", __func__);
return;
}
- rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+ rc = clk_set_rate(ispif->ispif_clk[vfe_intf][intftype], csid);
if (rc) {
pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
return;
}
}
- data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
- (0x200 * vfe_intf));
+ data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_INPUT_SEL(vfe_intf));
switch (intftype) {
case PIX0:
data &= ~(BIT(1) | BIT(0));
@@ -218,8 +316,8 @@
break;
}
if (data)
- msm_camera_io_w_mb(data, ispif->base + ISPIF_INPUT_SEL_ADDR +
- (0x200 * vfe_intf));
+ msm_camera_io_w_mb(data, ispif->base +
+ ISPIF_VFE_m_INPUT_SEL(vfe_intf));
}
static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
@@ -236,19 +334,19 @@
switch (intftype) {
case PIX0:
- intf_addr = ISPIF_PIX_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
+ intf_addr = ISPIF_VFE_m_PIX_INTF_n_CID_MASK(vfe_intf, 0);
break;
case RDI0:
- intf_addr = ISPIF_RDI_0_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 0);
break;
case PIX1:
- intf_addr = ISPIF_PIX_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
+ intf_addr = ISPIF_VFE_m_PIX_INTF_n_CID_MASK(vfe_intf, 1);
break;
case RDI1:
- intf_addr = ISPIF_RDI_1_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 1);
break;
case RDI2:
- intf_addr = ISPIF_RDI_2_INTF_CID_MASK_ADDR + (0x200 * vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_CID_MASK(vfe_intf, 2);
break;
default:
pr_err("%s: invalid intftype=%d\n", __func__, intftype);
@@ -280,23 +378,23 @@
switch (intftype) {
case PIX0:
data = msm_camera_io_r(ispif->base +
- ISPIF_PIX_0_STATUS_ADDR + (0x200 * vfe_intf));
+ ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 0));
break;
case RDI0:
data = msm_camera_io_r(ispif->base +
- ISPIF_RDI_0_STATUS_ADDR + (0x200 * vfe_intf));
+ ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 0));
break;
case PIX1:
data = msm_camera_io_r(ispif->base +
- ISPIF_PIX_1_STATUS_ADDR + (0x200 * vfe_intf));
+ ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1));
break;
case RDI1:
data = msm_camera_io_r(ispif->base +
- ISPIF_RDI_1_STATUS_ADDR + (0x200 * vfe_intf));
+ ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 1));
break;
case RDI2:
data = msm_camera_io_r(ispif->base +
- ISPIF_RDI_2_STATUS_ADDR + (0x200 * vfe_intf));
+ ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 2));
break;
}
if ((data & 0xf) != 0xf)
@@ -330,14 +428,22 @@
BUG_ON(!params);
vfe_intf = params->vfe_intf;
+
+ rc = msm_ispif_clk_enable(ispif, vfe_intf, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks for VFE%d", __func__,
+ vfe_intf);
+ return rc;
+ }
+
if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
pr_err("%s: invalid interface type\n", __func__);
return -EINVAL;
}
- msm_camera_io_w(0x0, ispif->base + ISPIF_IRQ_MASK_ADDR);
- msm_camera_io_w(0x0, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
- msm_camera_io_w_mb(0x0, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
+ msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
+ msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
+ msm_camera_io_w_mb(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
for (i = 0; i < params->num; i++) {
intftype = params->entries[i].intftype;
@@ -347,7 +453,8 @@
CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
intftype, vfe_intf, params->entries[i].csid);
- if ((intftype >= INTF_MAX) || (vfe_intf >= VFE_MAX) ||
+ if ((intftype >= INTF_MAX) ||
+ (vfe_intf >= ispif->vfe_info.num_vfe) ||
(ispif->csid_version <= CSID_VERSION_V2 &&
(vfe_intf > VFE0))) {
pr_err("%s: VFEID %d and CSID version %d mismatch\n",
@@ -371,26 +478,29 @@
}
msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_IRQ_MASK_ADDR);
+ ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_IRQ_CLEAR_ADDR);
+ ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf));
msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_IRQ_MASK_1_ADDR);
+ ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_IRQ_CLEAR_1_ADDR);
+ ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf));
msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_IRQ_MASK_2_ADDR);
+ ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_IRQ_CLEAR_2_ADDR);
+ ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf));
msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+
+ rc = msm_ispif_clk_enable(ispif, vfe_intf, 0);
+
return rc;
}
@@ -436,14 +546,12 @@
/* cmd for PIX0, PIX1, RDI0, RDI1 */
if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF) {
msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd,
- ispif->base + ISPIF_INTF_CMD_ADDR +
- (0x200 * vfe_intf));
+ ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf));
}
/* cmd for RDI2 */
if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
- ispif->base + ISPIF_INTF_CMD_1_ADDR +
- (0x200 * vfe_intf));
+ ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf));
}
static int msm_ispif_stop_immediately(struct ispif_device *ispif,
@@ -464,6 +572,7 @@
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
cid_mask, params->vfe_intf, 0);
}
+
return rc;
}
@@ -472,6 +581,13 @@
{
int rc;
+ rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks for VFE%d", __func__,
+ params->vfe_intf);
+ return rc;
+ }
+
rc = msm_ispif_intf_reset(ispif, params);
if (rc) {
pr_err("%s: msm_ispif_intf_reset failed. rc=%d\n",
@@ -480,6 +596,9 @@
}
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
+
+ msm_ispif_clk_enable(ispif, params->vfe_intf, 0);
+
return rc;
}
@@ -489,11 +608,21 @@
int i, rc = 0;
uint16_t cid_mask = 0;
uint32_t intf_addr;
+ enum msm_ispif_vfe_intf vfe_intf;
BUG_ON(!ispif);
BUG_ON(!params);
- if (!msm_ispif_is_intf_valid(ispif->csid_version, params->vfe_intf)) {
+ vfe_intf = params->vfe_intf;
+
+ rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks for VFE%d", __func__,
+ params->vfe_intf);
+ return rc;
+ }
+
+ if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
pr_err("%s: invalid interface type\n", __func__);
return -EINVAL;
}
@@ -507,24 +636,19 @@
switch (params->entries[i].intftype) {
case PIX0:
- intf_addr = ISPIF_PIX_0_STATUS_ADDR +
- (0x200 * params->vfe_intf);
+ intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 0);
break;
case RDI0:
- intf_addr = ISPIF_RDI_0_STATUS_ADDR +
- (0x200 * params->vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 0);
break;
case PIX1:
- intf_addr = ISPIF_PIX_1_STATUS_ADDR +
- (0x200 * params->vfe_intf);
+ intf_addr = ISPIF_VFE_m_PIX_INTF_n_STATUS(vfe_intf, 1);
break;
case RDI1:
- intf_addr = ISPIF_RDI_1_STATUS_ADDR +
- (0x200 * params->vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 1);
break;
case RDI2:
- intf_addr = ISPIF_RDI_2_STATUS_ADDR +
- (0x200 * params->vfe_intf);
+ intf_addr = ISPIF_VFE_m_RDI_INTF_n_STATUS(vfe_intf, 2);
break;
default:
pr_err("%s: invalid intftype=%d\n", __func__,
@@ -539,8 +663,11 @@
/* disable CIDs in CID_MASK register */
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
- cid_mask, params->vfe_intf, 0);
+ cid_mask, vfe_intf, 0);
}
+
+ msm_ispif_clk_enable(ispif, vfe_intf, 0);
+
return rc;
}
@@ -577,26 +704,26 @@
BUG_ON(!out);
out[VFE0].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_ADDR);
+ ISPIF_VFE_m_IRQ_STATUS_0(VFE0));
msm_camera_io_w(out[VFE0].ispifIrqStatus0,
- ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE0));
out[VFE0].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_1_ADDR);
+ ISPIF_VFE_m_IRQ_STATUS_1(VFE0));
msm_camera_io_w(out[VFE0].ispifIrqStatus1,
- ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE0));
out[VFE0].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_2_ADDR);
+ ISPIF_VFE_m_IRQ_STATUS_2(VFE0));
msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2,
- ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE0));
if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ) {
unsigned long flags;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- if (ispif->wait_timeout == 0)
- complete(&ispif->reset_complete);
+ if (ispif->wait_timeout[VFE0] == 0)
+ complete(&ispif->reset_complete[VFE0]);
spin_unlock_irqrestore(
&ispif->auto_complete_lock, flags);
}
@@ -615,21 +742,32 @@
ispif_process_irq(ispif, out, VFE0);
}
- if (ispif->csid_version >= CSID_VERSION_V3) {
+ if (ispif->csid_version >= CSID_VERSION_V3 &&
+ ispif->vfe_info.num_vfe > 1) {
out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_ADDR + 0x200);
+ ISPIF_VFE_m_IRQ_STATUS_0(VFE1));
msm_camera_io_w(out[VFE1].ispifIrqStatus0,
- ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1));
out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_1_ADDR + 0x200);
+ ISPIF_VFE_m_IRQ_STATUS_1(VFE1));
msm_camera_io_w(out[VFE1].ispifIrqStatus1,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1));
- ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
- ISPIF_IRQ_STATUS_2_ADDR + 0x200);
+ ISPIF_VFE_m_IRQ_STATUS_2(VFE1));
msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
- ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1));
+
+
+ if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ) {
+ unsigned long flags;
+ spin_lock_irqsave(&ispif->auto_complete_lock, flags);
+ if (ispif->wait_timeout[VFE1] == 0)
+ complete(&ispif->reset_complete[VFE1]);
+ spin_unlock_irqrestore(
+ &ispif->auto_complete_lock, flags);
+ }
if (out[VFE1].ispifIrqStatus0 & PIX_INTF_0_OVERFLOW_IRQ)
pr_err("%s: VFE1 pix0 overflow.\n", __func__);
@@ -657,19 +795,13 @@
return IRQ_HANDLED;
}
-static struct msm_cam_clk_info ispif_8960_clk_info[] = {
- {"csi_pix_clk", 0},
- {"csi_rdi_clk", 0},
- {"csi_pix1_clk", 0},
- {"csi_rdi1_clk", 0},
- {"csi_rdi2_clk", 0},
-};
-static struct msm_cam_clk_info ispif_8974_clk_info[] = {
- {"camss_vfe_vfe_clk", -1},
- {"camss_csi_vfe_clk", -1},
- {"camss_vfe_vfe_clk1", -1},
- {"camss_csi_vfe_clk1", -1},
-};
+static int msm_ispif_set_vfe_info(struct ispif_device *ispif,
+ struct msm_ispif_vfe_info *vfe_info)
+{
+ memcpy(&ispif->vfe_info, vfe_info, sizeof(struct msm_ispif_vfe_info));
+
+ return 0;
+}
static int msm_ispif_init(struct ispif_device *ispif,
uint32_t csid_version)
@@ -693,41 +825,28 @@
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
ispif->csid_version = csid_version;
- if (ispif->csid_version < CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, 2, 1);
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
- goto end;
- }
- } else if (ispif->csid_version == CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
- goto end;
- }
- } else if (ispif->csid_version >= CSID_VERSION_V3) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 1);
- if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
- goto end;
- }
- } else {
- pr_err("%s: unsupported version=%d\n", __func__,
- ispif->csid_version);
- goto end;
+ rc = msm_ispif_clk_enable(ispif, VFE0, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks for VFE0", __func__);
+ goto error_clk0;
}
+
+ if (ispif->csid_version >= CSID_VERSION_V3 &&
+ ispif->vfe_info.num_vfe > 1) {
+ rc = msm_ispif_clk_enable(ispif, VFE1, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks for VFE1",
+ __func__);
+ goto error_clk1;
+ }
+ }
+
ispif->base = ioremap(ispif->mem->start,
resource_size(ispif->mem));
if (!ispif->base) {
rc = -ENOMEM;
pr_err("%s: nomem\n", __func__);
- goto error_clk;
+ goto end;
}
rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
IRQF_TRIGGER_RISING, "ispif", ispif);
@@ -745,23 +864,22 @@
free_irq(ispif->irq->start, ispif);
error_irq:
iounmap(ispif->base);
-error_clk:
- if (ispif->csid_version < CSID_VERSION_V2) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, 2, 0);
- } else if (ispif->csid_version == CSID_VERSION_V2) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
- } else if (ispif->csid_version >= CSID_VERSION_V3) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 0);
- }
+
end:
+ if (ispif->csid_version >= CSID_VERSION_V3 &&
+ ispif->vfe_info.num_vfe > 1)
+ msm_ispif_clk_enable(ispif, VFE1, 0);
+
+error_clk1:
+ msm_ispif_clk_enable(ispif, VFE0, 0);
+
+error_clk0:
return rc;
}
static void msm_ispif_release(struct ispif_device *ispif)
{
+ int i;
BUG_ON(!ispif);
if (ispif->ispif_state != ISPIF_POWER_UP) {
@@ -770,6 +888,9 @@
return;
}
+ for (i = 0; i < ispif->vfe_info.num_vfe; i++)
+ msm_ispif_clk_enable(ispif, i, 1);
+
/* make sure no streaming going on */
msm_ispif_reset(ispif);
@@ -777,16 +898,9 @@
iounmap(ispif->base);
- if (ispif->csid_version < CSID_VERSION_V2) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, 2, 0);
- } else if (ispif->csid_version == CSID_VERSION_V2) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
- } else if (ispif->csid_version >= CSID_VERSION_V3) {
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_8974_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_8974_clk_info), 0);
- }
+ for (i = 0; i < ispif->vfe_info.num_vfe; i++)
+ msm_ispif_clk_enable(ispif, i, 0);
+
ispif->ispif_state = ISPIF_POWER_DOWN;
}
@@ -801,7 +915,6 @@
BUG_ON(!pcdata);
mutex_lock(&ispif->mutex);
-
switch (pcdata->cfg_type) {
case ISPIF_ENABLE_REG_DUMP:
ispif->enb_dump_reg = pcdata->reg_dump; /* save dump config */
@@ -829,6 +942,9 @@
case ISPIF_RELEASE:
msm_ispif_release(ispif);
break;
+ case ISPIF_SET_VFE_INFO:
+ rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info);
+ break;
default:
pr_err("%s: invalid cfg_type\n", __func__);
rc = -EINVAL;
@@ -903,6 +1019,7 @@
{
int rc;
struct ispif_device *ispif;
+ int i;
ispif = kzalloc(sizeof(struct ispif_device), GFP_KERNEL);
if (!ispif) {
@@ -961,7 +1078,9 @@
ispif->ispif_state = ISPIF_POWER_DOWN;
ispif->open_cnt = 0;
spin_lock_init(&ispif->auto_complete_lock);
- ispif->wait_timeout = 0;
+ for (i = 0; i < VFE_MAX; i++)
+ ispif->wait_timeout[i] = 0;
+
return 0;
error:
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
index f8c3cce..2c77292 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
@@ -47,15 +47,16 @@
void __iomem *base;
struct mutex mutex;
uint8_t start_ack_pending;
- struct completion reset_complete;
+ struct completion reset_complete[VFE_MAX];
spinlock_t auto_complete_lock;
- uint8_t wait_timeout;
+ uint8_t wait_timeout[VFE_MAX];
uint32_t csid_version;
int enb_dump_reg;
uint32_t open_cnt;
struct ispif_sof_count sof_count[VFE_MAX];
struct ispif_intf_cmd applied_intf_cmd[VFE_MAX];
enum msm_ispif_state_t ispif_state;
- struct clk *ispif_clk[INTF_MAX];
+ struct clk *ispif_clk[VFE_MAX][INTF_MAX];
+ struct msm_ispif_vfe_info vfe_info;
};
#endif
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index cdbebea..afd91d1 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -14,32 +14,41 @@
#define __MSM_ISPIF_HWREG_V1_H__
/* common registers */
-#define ISPIF_RST_CMD_ADDR 0x0000
-#define ISPIF_RST_CMD_1_ADDR 0x0000 /* undefined */
-#define ISPIF_INTF_CMD_ADDR 0x0004
-#define ISPIF_INTF_CMD_1_ADDR 0x0030
-#define ISPIF_CTRL_ADDR 0x0008
-#define ISPIF_INPUT_SEL_ADDR 0x000C
-#define ISPIF_PIX_0_INTF_CID_MASK_ADDR 0x0010
-#define ISPIF_RDI_0_INTF_CID_MASK_ADDR 0x0014
-#define ISPIF_PIX_1_INTF_CID_MASK_ADDR 0x0038
-#define ISPIF_RDI_1_INTF_CID_MASK_ADDR 0x003C
-#define ISPIF_RDI_2_INTF_CID_MASK_ADDR 0x0044
-#define ISPIF_PIX_0_STATUS_ADDR 0x0024
-#define ISPIF_RDI_0_STATUS_ADDR 0x0028
-#define ISPIF_PIX_1_STATUS_ADDR 0x0060
-#define ISPIF_RDI_1_STATUS_ADDR 0x0064
-#define ISPIF_RDI_2_STATUS_ADDR 0x006C
-#define ISPIF_IRQ_MASK_ADDR 0x0100
-#define ISPIF_IRQ_CLEAR_ADDR 0x0104
-#define ISPIF_IRQ_STATUS_ADDR 0x0108
-#define ISPIF_IRQ_MASK_1_ADDR 0x010C
-#define ISPIF_IRQ_CLEAR_1_ADDR 0x0110
-#define ISPIF_IRQ_STATUS_1_ADDR 0x0114
-#define ISPIF_IRQ_MASK_2_ADDR 0x0118
-#define ISPIF_IRQ_CLEAR_2_ADDR 0x011C
-#define ISPIF_IRQ_STATUS_2_ADDR 0x0120
-#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x0124
+#define ISPIF_RST_CMD_ADDR 0x0000
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x0124
+
+#define ISPIF_VFE(m) (0x0)
+
+#define ISPIF_VFE_m_CTRL_0(m) (0x0008 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_0(m) (0x0100 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_1(m) (0x010C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_2(m) (0x0118 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_0(m) (0x0108 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_1(m) (0x0114 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_2(m) (0x0120 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_0(m) (0x0104 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_1(m) (0x0110 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_2(m) (0x011C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INPUT_SEL(m) (0x000C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INTF_CMD_0(m) (0x0004 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INTF_CMD_1(m) (0x0030 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_PIX_INTF_n_CID_MASK(m, n) (0x0010 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_CID_MASK(m, n) (0x0014 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_PIX_OUTPUT_n_MISR(m, n) (0x0290 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_0(m, n) (0x0298 + ISPIF_VFE(m) + 8*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_1(m, n) (0x029C + ISPIF_VFE(m) + 8*(n))
+#define ISPIF_VFE_m_PIX_INTF_n_STATUS(m, n) (0x0024 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_STATUS(m, n) (0x0028 + ISPIF_VFE(m) + 4*(n))
+
+/* Defines for compatibility with newer ISPIF versions */
+#define ISPIF_RST_CMD_1_ADDR (0x0000)
+#define ISPIF_VFE_m_PIX_INTF_n_CROP(m, n) (0x0000 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_3D_THRESHOLD(m) (0x0000 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_OUTPUT_SEL(m) (0x0000 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_3D_DESKEW_SIZE(m) (0x0000 + ISPIF_VFE(m))
+
+
+
/*ISPIF RESET BITS*/
#define VFE_CLK_DOMAIN_RST BIT(31)
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 37b19f5..80b32d4 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -16,42 +16,34 @@
/* common registers */
#define ISPIF_RST_CMD_ADDR 0x008
#define ISPIF_RST_CMD_1_ADDR 0x00C
-#define ISPIF_INTF_CMD_ADDR 0x248
-#define ISPIF_INTF_CMD_1_ADDR 0x24C
-#define ISPIF_CTRL_ADDR 0x008
-#define ISPIF_INPUT_SEL_ADDR 0x244
-#define ISPIF_PIX_0_INTF_CID_MASK_ADDR 0x254
-#define ISPIF_RDI_0_INTF_CID_MASK_ADDR 0x264
-#define ISPIF_PIX_1_INTF_CID_MASK_ADDR 0x258
-#define ISPIF_RDI_1_INTF_CID_MASK_ADDR 0x268
-#define ISPIF_RDI_2_INTF_CID_MASK_ADDR 0x26C
-#define ISPIF_PIX_0_STATUS_ADDR 0x2C0
-#define ISPIF_RDI_0_STATUS_ADDR 0x2D0
-#define ISPIF_PIX_1_STATUS_ADDR 0x2C4
-#define ISPIF_RDI_1_STATUS_ADDR 0x2D4
-#define ISPIF_RDI_2_STATUS_ADDR 0x2D8
-#define ISPIF_IRQ_MASK_ADDR 0x208
-#define ISPIF_IRQ_CLEAR_ADDR 0x230
-#define ISPIF_IRQ_STATUS_ADDR 0x21C
-#define ISPIF_IRQ_MASK_1_ADDR 0x20C
-#define ISPIF_IRQ_CLEAR_1_ADDR 0x234
-#define ISPIF_IRQ_STATUS_1_ADDR 0x220
-#define ISPIF_IRQ_MASK_2_ADDR 0x210
-#define ISPIF_IRQ_CLEAR_2_ADDR 0x238
-#define ISPIF_IRQ_STATUS_2_ADDR 0x224
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x01C
-/* new */
-#define ISPIF_VFE_m_CTRL_0_ADDR 0x200
-#define ISPIF_VFE_m_IRQ_MASK_0 0x208
-#define ISPIF_VFE_m_IRQ_MASK_1 0x20C
-#define ISPIF_VFE_m_IRQ_MASK_2 0x210
-#define ISPIF_VFE_m_IRQ_STATUS_0 0x21C
-#define ISPIF_VFE_m_IRQ_STATUS_1 0x220
-#define ISPIF_VFE_m_IRQ_STATUS_2 0x224
-#define ISPIF_VFE_m_IRQ_CLEAR_0 0x230
-#define ISPIF_VFE_m_IRQ_CLEAR_1 0x234
-#define ISPIF_VFE_m_IRQ_CLEAR_2 0x238
+#define ISPIF_VFE(m) ((m) * 0x200)
+
+#define ISPIF_VFE_m_CTRL_0(m) (0x200 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_0(m) (0x208 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_1(m) (0x20C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_MASK_2(m) (0x210 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_0(m) (0x21C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_1(m) (0x220 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_STATUS_2(m) (0x224 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_0(m) (0x230 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_1(m) (0x234 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_IRQ_CLEAR_2(m) (0x238 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INPUT_SEL(m) (0x244 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INTF_CMD_0(m) (0x248 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_INTF_CMD_1(m) (0x24C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_PIX_INTF_n_CID_MASK(m, n) (0x254 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_CID_MASK(m, n) (0x264 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_PIX_INTF_n_CROP(m, n) (0x278 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_3D_THRESHOLD(m) (0x288 + ISPIF_VFE(m))
+#define ISPIF_VFE_m_OUTPUT_SEL(m) (0x28C + ISPIF_VFE(m))
+#define ISPIF_VFE_m_PIX_OUTPUT_n_MISR(m, n) (0x290 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_0(m, n) (0x298 + ISPIF_VFE(m) + 8*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_1(m, n) (0x29C + ISPIF_VFE(m) + 8*(n))
+#define ISPIF_VFE_m_PIX_INTF_n_STATUS(m, n) (0x2C0 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_STATUS(m, n) (0x2D0 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_3D_DESKEW_SIZE(m) (0x2E4 + ISPIF_VFE(m))
/*ISPIF RESET BITS*/
#define VFE_CLK_DOMAIN_RST BIT(31)
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index b1253fa..59b9746 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -73,7 +73,6 @@
{"core_clk", 228570000},
{"iface_clk", -1},
{"bus_clk0", -1},
- {"alt_bus_clk", -1},
{"camss_top_ahb_clk", -1},
};
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 6418f21..fbc2b93 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -355,7 +355,7 @@
if (WARN_ON(!msm_subdev))
return -EINVAL;
- if (WARN_ON(!msm_v4l2_dev) && WARN_ON(!msm_v4l2_dev->dev))
+ if (WARN_ON(!msm_v4l2_dev) || WARN_ON(!msm_v4l2_dev->dev))
return -EIO;
return __msm_sd_register_subdev(&msm_subdev->sd);
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index ca5e646..8f63d33 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -563,6 +563,44 @@
return 0;
}
+static int msm_cpp_flush_frames(struct cpp_device *cpp_dev)
+{
+ struct v4l2_event v4l2_evt;
+ struct msm_queue_cmd *frame_qcmd;
+ struct msm_cpp_frame_info_t *process_frame;
+ struct msm_device_queue *queue;
+ struct msm_queue_cmd *event_qcmd;
+
+ do {
+ if (cpp_dev->realtime_q.len != 0) {
+ queue = &cpp_dev->realtime_q;
+ } else if (cpp_dev->offline_q.len != 0) {
+ queue = &cpp_dev->offline_q;
+ } else {
+ pr_debug("All frames flushed\n");
+ break;
+ }
+ frame_qcmd = msm_dequeue(queue, list_frame);
+ process_frame = frame_qcmd->command;
+ kfree(frame_qcmd);
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
+ if (!event_qcmd) {
+ pr_err("Insufficient memory. return");
+ return -ENOMEM;
+ }
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = process_frame;
+ CPP_DBG("fid %d\n", process_frame->frame_id);
+ msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
+
+ v4l2_evt.id = process_frame->inst_id;
+ v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
+ v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
+ } while ((cpp_dev->realtime_q.len != 0) ||
+ (cpp_dev->offline_q.len != 0));
+ return 0;
+}
+
static int msm_cpp_cfg(struct cpp_device *cpp_dev,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
{
@@ -755,7 +793,7 @@
rc = msm_cpp_cfg(cpp_dev, ioctl_ptr);
break;
case VIDIOC_MSM_CPP_FLUSH_QUEUE:
- rc = msm_cpp_send_frame_to_hardware(cpp_dev);
+ rc = msm_cpp_flush_frames(cpp_dev);
break;
case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
struct msm_device_queue *queue = &cpp_dev->eventData_q;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index 6f941f7..b6708a3 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -7,5 +7,7 @@
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
obj-$(CONFIG_IMX135) += imx135.o
+obj-$(CONFIG_OV8825) += ov8825.o
obj-$(CONFIG_OV2720) += ov2720.o
+obj-$(CONFIG_OV9724) += ov9724.o
obj-$(CONFIG_MT9M114) += mt9m114.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index e939c2b..e1b978f 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -27,7 +27,6 @@
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#endif
-static struct msm_actuator_ctrl_t msm_actuator_t;
static struct msm_actuator msm_vcm_actuator_table;
static struct msm_actuator msm_piezo_actuator_table;
@@ -618,103 +617,21 @@
.close = msm_actuator_close,
};
-static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
{
- int rc = 0;
- struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+ struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
+ void __user *argp = (void __user *)arg;
CDBG("Enter\n");
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- pr_err("i2c_check_functionality failed\n");
- goto probe_failure;
+ CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ return msm_actuator_get_subdev_id(a_ctrl, argp);
+ case VIDIOC_MSM_ACTUATOR_CFG:
+ return msm_actuator_config(a_ctrl, argp);
+ default:
+ return -ENOIOCTLCMD;
}
-
- act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
- CDBG("client = %x\n", (unsigned int) client);
- act_ctrl_t->i2c_client.client = client;
- /* Set device type as I2C */
- act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
- act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
-
- /* Assign name for sub device */
- snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
- "%s", act_ctrl_t->i2c_driver->driver.name);
-
- /* Initialize sub device */
- v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
- act_ctrl_t->i2c_client.client,
- act_ctrl_t->act_v4l2_subdev_ops);
- v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
- act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
- act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
- act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
- act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
- msm_sd_register(&act_ctrl_t->msm_sd);
- CDBG("succeeded\n");
- CDBG("Exit\n");
-
-probe_failure:
- return rc;
-}
-
-static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
-{
- int32_t rc = 0;
- struct msm_camera_cci_client *cci_client = NULL;
- CDBG("Enter\n");
-
- if (!pdev->dev.of_node) {
- pr_err("of_node NULL\n");
- return -EINVAL;
- }
-
- rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
- &pdev->id);
- CDBG("cell-index %d, rc %d\n", pdev->id, rc);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- return rc;
- }
-
- rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
- &msm_actuator_t.cci_master);
- CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t.cci_master, rc);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- return rc;
- }
-
- msm_actuator_t.cam_name = pdev->id;
-
- /* Set platform device handle */
- msm_actuator_t.pdev = pdev;
- /* Set device type as platform device */
- msm_actuator_t.act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
- msm_actuator_t.i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
- msm_actuator_t.i2c_client.cci_client = kzalloc(sizeof(
- struct msm_camera_cci_client), GFP_KERNEL);
- if (!msm_actuator_t.i2c_client.cci_client) {
- pr_err("failed no memory\n");
- return -ENOMEM;
- }
-
- cci_client = msm_actuator_t.i2c_client.cci_client;
- cci_client->cci_subdev = msm_cci_get_subdev();
- v4l2_subdev_init(&msm_actuator_t.msm_sd.sd,
- msm_actuator_t.act_v4l2_subdev_ops);
- v4l2_set_subdevdata(&msm_actuator_t.msm_sd.sd, &msm_actuator_t);
- msm_actuator_t.msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
- msm_actuator_t.msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
- snprintf(msm_actuator_t.msm_sd.sd.name,
- ARRAY_SIZE(msm_actuator_t.msm_sd.sd.name), "msm_actuator");
- media_entity_init(&msm_actuator_t.msm_sd.sd.entity, 0, NULL, 0);
- msm_actuator_t.msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
- msm_actuator_t.msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
- msm_sd_register(&msm_actuator_t.msm_sd);
- CDBG("Exit\n");
- return rc;
}
static int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
@@ -735,64 +652,6 @@
return rc;
}
-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 const struct of_device_id msm_actuator_dt_match[] = {
- {.compatible = "qcom,actuator", .data = &msm_actuator_t},
- {}
-};
-
-MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
-
-static struct platform_driver msm_actuator_platform_driver = {
- .driver = {
- .name = "qcom,actuator",
- .owner = THIS_MODULE,
- .of_match_table = msm_actuator_dt_match,
- },
-};
-
-static int __init msm_actuator_init_module(void)
-{
- int32_t rc = 0;
- CDBG("Enter\n");
- rc = platform_driver_probe(msm_actuator_t.pdriver,
- msm_actuator_platform_probe);
- if (!rc)
- return rc;
- CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
- return i2c_add_driver(msm_actuator_t.i2c_driver);
-}
-
-static long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int cmd, void *arg)
-{
- struct msm_actuator_ctrl_t *a_ctrl = v4l2_get_subdevdata(sd);
- void __user *argp = (void __user *)arg;
- CDBG("Enter\n");
- CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, a_ctrl, argp);
- switch (cmd) {
- case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
- return msm_actuator_get_subdev_id(a_ctrl, argp);
- case VIDIOC_MSM_ACTUATOR_CFG:
- return msm_actuator_config(a_ctrl, argp);
- default:
- return -ENOIOCTLCMD;
- }
-}
-
static int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
{
int rc = 0;
@@ -817,17 +676,156 @@
.core = &msm_actuator_subdev_core_ops,
};
-static struct msm_actuator_ctrl_t msm_actuator_t = {
- .i2c_driver = &msm_actuator_i2c_driver,
- .pdriver = &msm_actuator_platform_driver,
- .act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
+static int32_t msm_actuator_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct msm_actuator_ctrl_t *act_ctrl_t = NULL;
+ CDBG("Enter\n");
- .curr_step_pos = 0,
- .curr_region_index = 0,
- .actuator_mutex = &msm_actuator_mutex,
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("i2c_check_functionality failed\n");
+ goto probe_failure;
+ }
+ act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
+ CDBG("client = %x\n", (unsigned int) client);
+ act_ctrl_t->i2c_client.client = client;
+ /* Set device type as I2C */
+ act_ctrl_t->act_device_type = MSM_CAMERA_I2C_DEVICE;
+ act_ctrl_t->i2c_client.i2c_func_tbl = &msm_sensor_qup_func_tbl;
+ act_ctrl_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+ act_ctrl_t->actuator_mutex = &msm_actuator_mutex;
+ /* Assign name for sub device */
+ snprintf(act_ctrl_t->msm_sd.sd.name, sizeof(act_ctrl_t->msm_sd.sd.name),
+ "%s", act_ctrl_t->i2c_driver->driver.name);
+
+ /* Initialize sub device */
+ v4l2_i2c_subdev_init(&act_ctrl_t->msm_sd.sd,
+ act_ctrl_t->i2c_client.client,
+ act_ctrl_t->act_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&act_ctrl_t->msm_sd.sd, act_ctrl_t);
+ act_ctrl_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+ act_ctrl_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&act_ctrl_t->msm_sd.sd.entity, 0, NULL, 0);
+ act_ctrl_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ act_ctrl_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ msm_sd_register(&act_ctrl_t->msm_sd);
+ CDBG("succeeded\n");
+ CDBG("Exit\n");
+
+probe_failure:
+ return rc;
+}
+
+static int32_t msm_actuator_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ struct msm_camera_cci_client *cci_client = NULL;
+ struct msm_actuator_ctrl_t *msm_actuator_t = NULL;
+ CDBG("Enter\n");
+
+ if (!pdev->dev.of_node) {
+ pr_err("of_node NULL\n");
+ return -EINVAL;
+ }
+
+ msm_actuator_t = kzalloc(sizeof(struct msm_actuator_ctrl_t),
+ GFP_KERNEL);
+ if (!msm_actuator_t) {
+ pr_err("%s:%d failed no memory\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ rc = of_property_read_u32((&pdev->dev)->of_node, "cell-index",
+ &pdev->id);
+ CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32((&pdev->dev)->of_node, "qcom,cci-master",
+ &msm_actuator_t->cci_master);
+ CDBG("qcom,cci-master %d, rc %d\n", msm_actuator_t->cci_master, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ msm_actuator_t->act_v4l2_subdev_ops = &msm_actuator_subdev_ops;
+ msm_actuator_t->actuator_mutex = &msm_actuator_mutex;
+ msm_actuator_t->cam_name = pdev->id;
+
+ /* Set platform device handle */
+ msm_actuator_t->pdev = pdev;
+ /* Set device type as platform device */
+ msm_actuator_t->act_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+ msm_actuator_t->i2c_client.i2c_func_tbl = &msm_sensor_cci_func_tbl;
+ msm_actuator_t->i2c_client.cci_client = kzalloc(sizeof(
+ struct msm_camera_cci_client), GFP_KERNEL);
+ if (!msm_actuator_t->i2c_client.cci_client) {
+ pr_err("failed no memory\n");
+ return -ENOMEM;
+ }
+
+ cci_client = msm_actuator_t->i2c_client.cci_client;
+ cci_client->cci_subdev = msm_cci_get_subdev();
+ v4l2_subdev_init(&msm_actuator_t->msm_sd.sd,
+ msm_actuator_t->act_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&msm_actuator_t->msm_sd.sd, msm_actuator_t);
+ msm_actuator_t->msm_sd.sd.internal_ops = &msm_actuator_internal_ops;
+ msm_actuator_t->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(msm_actuator_t->msm_sd.sd.name,
+ ARRAY_SIZE(msm_actuator_t->msm_sd.sd.name), "msm_actuator");
+ media_entity_init(&msm_actuator_t->msm_sd.sd.entity, 0, NULL, 0);
+ msm_actuator_t->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ msm_actuator_t->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_ACTUATOR;
+ msm_sd_register(&msm_actuator_t->msm_sd);
+ CDBG("Exit\n");
+ return rc;
+}
+
+static const struct i2c_device_id msm_actuator_i2c_id[] = {
+ {"msm_actuator", (kernel_ulong_t)NULL},
+ { }
};
+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 const struct of_device_id msm_actuator_dt_match[] = {
+ {.compatible = "qcom,actuator", .data = NULL},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, msm_actuator_dt_match);
+
+static struct platform_driver msm_actuator_platform_driver = {
+ .driver = {
+ .name = "qcom,actuator",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_actuator_dt_match,
+ },
+};
+
+static int __init msm_actuator_init_module(void)
+{
+ int32_t rc = 0;
+ CDBG("Enter\n");
+ rc = platform_driver_probe(&msm_actuator_platform_driver,
+ msm_actuator_platform_probe);
+ if (!rc)
+ return rc;
+ CDBG("%s:%d rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&msm_actuator_i2c_driver);
+}
+
static struct msm_actuator msm_vcm_actuator_table = {
.act_type = ACTUATOR_VCM,
.func_tbl = {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 2c8c8b8..0df0488 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -244,8 +244,8 @@
{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
};
-static struct camera_vreg_t csid_8974_vreg_info[] = {
- {"mipi_csi_vdd", REG_LDO, 1800000, 1800000, 12000},
+static struct camera_vreg_t csid_vreg_info[] = {
+ {"qcom,mipi-csi-vdd", REG_LDO, 0, 0, 12000},
};
static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
@@ -309,7 +309,7 @@
} else if (CSID_VERSION >= CSID_VERSION_V3) {
CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
if (rc < 0) {
pr_err("%s: regulator on failed\n", __func__);
@@ -318,7 +318,7 @@
CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
if (rc < 0) {
pr_err("%s: regulator enable failed\n", __func__);
@@ -382,7 +382,7 @@
NULL, 0, &csid_dev->csi_vdd, 0);
} else if (CSID_VERSION >= CSID_VERSION_V3) {
msm_camera_enable_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 0);
}
vreg_enable_failed:
@@ -392,7 +392,7 @@
NULL, 0, &csid_dev->csi_vdd, 0);
} else if (CSID_VERSION >= CSID_VERSION_V3) {
msm_camera_config_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 0);
}
vreg_config_failed:
@@ -442,11 +442,11 @@
csid_8974_clk_info[0].num_clk_info, 0);
msm_camera_enable_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 0);
msm_camera_config_vreg(&csid_dev->pdev->dev,
- csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 0);
}
@@ -576,7 +576,7 @@
static int __devinit csid_probe(struct platform_device *pdev)
{
struct csid_device *new_csid_dev;
-
+ uint32_t csi_vdd_voltage = 0;
int rc = 0;
CDBG("%s:%d called\n", __func__, __LINE__);
new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
@@ -590,11 +590,30 @@
platform_set_drvdata(pdev, &new_csid_dev->msm_sd.sd);
mutex_init(&new_csid_dev->mutex);
- if (pdev->dev.of_node)
- of_property_read_u32((&pdev->dev)->of_node,
+ if (pdev->dev.of_node) {
+ rc = of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
+ if (rc < 0) {
+ pr_err("%s:%d failed to read cell-index\n", __func__,
+ __LINE__);
+ goto csid_no_resource;
+ }
+ CDBG("%s device id %d\n", __func__, pdev->id);
- CDBG("%s device id %d\n", __func__, pdev->id);
+ rc = of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,csi-vdd-voltage", &csi_vdd_voltage);
+ if (rc < 0) {
+ pr_err("%s:%d failed to read qcom,csi-vdd-voltage\n",
+ __func__, __LINE__);
+ goto csid_no_resource;
+ }
+ CDBG("%s:%d reading mipi_csi_vdd is %d\n", __func__, __LINE__,
+ csi_vdd_voltage);
+
+ csid_vreg_info[0].min_voltage = csi_vdd_voltage;
+ csid_vreg_info[0].max_voltage = csi_vdd_voltage;
+ }
+
new_csid_dev->mem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "csid");
if (!new_csid_dev->mem) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov8825.c b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
new file mode 100644
index 0000000..b56eb10
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov8825.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+#define OV8825_SENSOR_NAME "ov8825"
+DEFINE_MSM_MUTEX(ov8825_mut);
+
+static struct msm_sensor_ctrl_t ov8825_s_ctrl;
+
+static struct msm_sensor_power_setting ov8825_power_setting[] = {
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VIO,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VANA,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VDIG,
+ .config_val = 0,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VAF,
+ .config_val = 0,
+ .delay = 15,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 15,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 40,
+ },
+ {
+ .seq_type = SENSOR_CLK,
+ .seq_val = SENSOR_CAM_MCLK,
+ .config_val = 24000000,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_I2C_MUX,
+ .seq_val = 0,
+ .config_val = 0,
+ .delay = 0,
+ },
+};
+
+static struct v4l2_subdev_info ov8825_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+};
+
+static const struct i2c_device_id ov8825_i2c_id[] = {
+ {OV8825_SENSOR_NAME, (kernel_ulong_t)&ov8825_s_ctrl},
+ { }
+};
+
+static struct i2c_driver ov8825_i2c_driver = {
+ .id_table = ov8825_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = OV8825_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov8825_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id ov8825_dt_match[] = {
+ {.compatible = "qcom,ov8825", .data = &ov8825_s_ctrl},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, ov8825_dt_match);
+
+static struct platform_driver ov8825_platform_driver = {
+ .driver = {
+ .name = "qcom,ov8825",
+ .owner = THIS_MODULE,
+ .of_match_table = ov8825_dt_match,
+ },
+};
+
+static int32_t ov8825_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ const struct of_device_id *match;
+ match = of_match_device(ov8825_dt_match, &pdev->dev);
+ rc = msm_sensor_platform_probe(pdev, match->data);
+ return rc;
+}
+
+static int __init ov8825_init_module(void)
+{
+ int32_t rc = 0;
+ pr_info("%s:%d\n", __func__, __LINE__);
+ rc = platform_driver_probe(&ov8825_platform_driver,
+ ov8825_platform_probe);
+ if (!rc)
+ return rc;
+ pr_err("%s:%d rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&ov8825_i2c_driver);
+}
+
+static void __exit ov8825_exit_module(void)
+{
+ pr_info("%s:%d\n", __func__, __LINE__);
+ if (ov8825_s_ctrl.pdev) {
+ msm_sensor_free_sensor_data(&ov8825_s_ctrl);
+ platform_driver_unregister(&ov8825_platform_driver);
+ } else
+ i2c_del_driver(&ov8825_i2c_driver);
+ return;
+}
+
+static struct msm_sensor_ctrl_t ov8825_s_ctrl = {
+ .sensor_i2c_client = &ov8825_sensor_i2c_client,
+ .power_setting_array.power_setting = ov8825_power_setting,
+ .power_setting_array.size = ARRAY_SIZE(ov8825_power_setting),
+ .msm_sensor_mutex = &ov8825_mut,
+ .sensor_v4l2_subdev_info = ov8825_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov8825_subdev_info),
+};
+
+module_init(ov8825_init_module);
+module_exit(ov8825_exit_module);
+MODULE_DESCRIPTION("ov8825");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ov9724.c b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
new file mode 100644
index 0000000..981cc10
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/ov9724.c
@@ -0,0 +1,161 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "msm_sensor.h"
+
+#define OV9724_SENSOR_NAME "ov9724"
+DEFINE_MSM_MUTEX(ov9724_mut);
+
+static struct msm_sensor_ctrl_t ov9724_s_ctrl;
+
+static struct msm_sensor_power_setting ov9724_power_setting[] = {
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VANA,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VIO,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VDIG,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_CLK,
+ .seq_val = SENSOR_CAM_MCLK,
+ .config_val = 24000000,
+ .delay = 5,
+ },
+ {
+ .seq_type = SENSOR_I2C_MUX,
+ .seq_val = 0,
+ .config_val = 0,
+ .delay = 0,
+ },
+};
+
+static struct v4l2_subdev_info ov9724_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+};
+
+static const struct i2c_device_id ov9724_i2c_id[] = {
+ {OV9724_SENSOR_NAME, (kernel_ulong_t)&ov9724_s_ctrl},
+ { }
+};
+
+static struct i2c_driver ov9724_i2c_driver = {
+ .id_table = ov9724_i2c_id,
+ .probe = msm_sensor_i2c_probe,
+ .driver = {
+ .name = OV9724_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client ov9724_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static struct msm_sensor_ctrl_t ov9724_s_ctrl = {
+ .sensor_i2c_client = &ov9724_sensor_i2c_client,
+ .power_setting_array.power_setting = ov9724_power_setting,
+ .power_setting_array.size = ARRAY_SIZE(ov9724_power_setting),
+ .msm_sensor_mutex = &ov9724_mut,
+ .sensor_v4l2_subdev_info = ov9724_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(ov9724_subdev_info),
+};
+
+static const struct of_device_id ov9724_dt_match[] = {
+ {.compatible = "qcom,ov9724", .data = &ov9724_s_ctrl},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, ov9724_dt_match);
+
+static struct platform_driver ov9724_platform_driver = {
+ .driver = {
+ .name = "qcom,ov9724",
+ .owner = THIS_MODULE,
+ .of_match_table = ov9724_dt_match,
+ },
+};
+
+static int32_t ov9724_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ const struct of_device_id *match;
+
+ match = of_match_device(ov9724_dt_match, &pdev->dev);
+ rc = msm_sensor_platform_probe(pdev, match->data);
+ return rc;
+}
+
+static int __init ov9724_init_module(void)
+{
+ int32_t rc = 0;
+
+ rc = platform_driver_probe(&ov9724_platform_driver,
+ ov9724_platform_probe);
+ if (!rc)
+ return rc;
+ return i2c_add_driver(&ov9724_i2c_driver);
+}
+
+static void __exit ov9724_exit_module(void)
+{
+ if (ov9724_s_ctrl.pdev) {
+ msm_sensor_free_sensor_data(&ov9724_s_ctrl);
+ platform_driver_unregister(&ov9724_platform_driver);
+ } else
+ i2c_del_driver(&ov9724_i2c_driver);
+ return;
+}
+
+module_init(ov9724_init_module);
+module_exit(ov9724_exit_module);
+MODULE_DESCRIPTION("ov9724");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c b/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
index 6ec1994..76ce0c0 100644
--- a/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
+++ b/drivers/media/platform/msm/dvb/adapter/mpq_stream_buffer.c
@@ -19,8 +19,6 @@
#include "mpq_stream_buffer.h"
-
-
int mpq_streambuffer_init(
struct mpq_streambuffer *sbuff,
enum mpq_streambuffer_mode mode,
@@ -29,7 +27,8 @@
void *packet_buff,
size_t packet_buff_size)
{
- if ((NULL == sbuff) || (NULL == data_buffers) || (NULL == packet_buff))
+ if ((NULL == sbuff) || (NULL == data_buffers) ||
+ (NULL == packet_buff) || (data_buff_num == 0))
return -EINVAL;
if (data_buff_num > 1) {
@@ -41,7 +40,7 @@
data_buffers,
data_buff_num *
sizeof(struct mpq_streambuffer_buffer_desc));
- } else if (data_buff_num == 1) {
+ } else {
if (mode != MPQ_STREAMBUFFER_BUFFER_MODE_RING)
return -EINVAL;
/* Single ring-buffer */
@@ -58,12 +57,38 @@
}
EXPORT_SYMBOL(mpq_streambuffer_init);
+void mpq_streambuffer_terminate(struct mpq_streambuffer *sbuff)
+{
+ spin_lock(&sbuff->packet_data.lock);
+ spin_lock(&sbuff->raw_data.lock);
+ sbuff->packet_data.error = -ENODEV;
+ sbuff->raw_data.error = -ENODEV;
+ spin_unlock(&sbuff->raw_data.lock);
+ spin_unlock(&sbuff->packet_data.lock);
+
+ wake_up_all(&sbuff->raw_data.queue);
+ wake_up_all(&sbuff->packet_data.queue);
+}
+EXPORT_SYMBOL(mpq_streambuffer_terminate);
ssize_t mpq_streambuffer_pkt_next(
struct mpq_streambuffer *sbuff,
ssize_t idx, size_t *pktlen)
{
- return dvb_ringbuffer_pkt_next(&sbuff->packet_data, idx, pktlen);
+ ssize_t packet_idx;
+
+ spin_lock(&sbuff->packet_data.lock);
+
+ /* buffer was released, return no packet available */
+ if (sbuff->packet_data.error == -ENODEV) {
+ spin_unlock(&sbuff->packet_data.lock);
+ return -ENODEV;
+ }
+
+ packet_idx = dvb_ringbuffer_pkt_next(&sbuff->packet_data, idx, pktlen);
+ spin_unlock(&sbuff->packet_data.lock);
+
+ return packet_idx;
}
EXPORT_SYMBOL(mpq_streambuffer_pkt_next);
@@ -77,6 +102,14 @@
size_t ret;
size_t read_len;
+ spin_lock(&sbuff->packet_data.lock);
+
+ /* buffer was released, return no packet available */
+ if (sbuff->packet_data.error == -ENODEV) {
+ spin_unlock(&sbuff->packet_data.lock);
+ return -ENODEV;
+ }
+
/* read-out the packet header first */
ret = dvb_ringbuffer_pkt_read(
&sbuff->packet_data, idx, 0,
@@ -84,8 +117,10 @@
sizeof(struct mpq_streambuffer_packet_header));
/* verify length, at least packet header should exist */
- if (ret != sizeof(struct mpq_streambuffer_packet_header))
+ if (ret != sizeof(struct mpq_streambuffer_packet_header)) {
+ spin_unlock(&sbuff->packet_data.lock);
return -EINVAL;
+ }
read_len = ret;
@@ -98,12 +133,16 @@
user_data,
packet->user_data_len);
- if (ret < 0)
+ if (ret < 0) {
+ spin_unlock(&sbuff->packet_data.lock);
return ret;
+ }
read_len += ret;
}
+ spin_unlock(&sbuff->packet_data.lock);
+
return read_len;
}
EXPORT_SYMBOL(mpq_streambuffer_pkt_read);
@@ -120,12 +159,22 @@
if (NULL == sbuff)
return -EINVAL;
+ spin_lock(&sbuff->packet_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->packet_data.error == -ENODEV) {
+ spin_unlock(&sbuff->packet_data.lock);
+ return -ENODEV;
+ }
+
/* read-out the packet header first */
ret = dvb_ringbuffer_pkt_read(&sbuff->packet_data, idx,
0,
(u8 *)&packet,
sizeof(struct mpq_streambuffer_packet_header));
+ spin_unlock(&sbuff->packet_data.lock);
+
if (ret != sizeof(struct mpq_streambuffer_packet_header))
return -EINVAL;
@@ -138,6 +187,17 @@
return ret;
}
+ spin_lock(&sbuff->packet_data.lock);
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if ((sbuff->packet_data.error == -ENODEV) ||
+ (sbuff->raw_data.error == -ENODEV)) {
+ spin_unlock(&sbuff->raw_data.lock);
+ spin_unlock(&sbuff->packet_data.lock);
+ return -ENODEV;
+ }
+
/* Move read pointer to the next linear buffer for subsequent reads */
if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
(packet.raw_data_len > 0)) {
@@ -159,6 +219,9 @@
/* Now clear the packet from the packet header */
dvb_ringbuffer_pkt_dispose(&sbuff->packet_data, idx);
+ spin_unlock(&sbuff->raw_data.lock);
+ spin_unlock(&sbuff->packet_data.lock);
+
if (sbuff->cb)
sbuff->cb(sbuff, sbuff->cb_user_data);
@@ -177,12 +240,22 @@
if ((NULL == sbuff) || (NULL == packet))
return -EINVAL;
+ spin_lock(&sbuff->packet_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->packet_data.error == -ENODEV) {
+ spin_unlock(&sbuff->packet_data.lock);
+ return -ENODEV;
+ }
+
len = sizeof(struct mpq_streambuffer_packet_header) +
packet->user_data_len;
/* Make sure enough space available for packet header */
- if (dvb_ringbuffer_free(&sbuff->packet_data) < len)
+ if (dvb_ringbuffer_free(&sbuff->packet_data) < len) {
+ spin_unlock(&sbuff->packet_data.lock);
return -ENOSPC;
+ }
/* Starting writing packet header */
idx = dvb_ringbuffer_pkt_start(&sbuff->packet_data, len);
@@ -202,20 +275,22 @@
/* Move write pointer to next linear buffer for subsequent writes */
if ((MPQ_STREAMBUFFER_BUFFER_MODE_LINEAR == sbuff->mode) &&
(packet->raw_data_len > 0)) {
- if (sbuff->pending_buffers_count == sbuff->buffers_num)
+ if (sbuff->pending_buffers_count == sbuff->buffers_num) {
+ spin_unlock(&sbuff->packet_data.lock);
return -ENOSPC;
+ }
DVB_RINGBUFFER_PUSH(&sbuff->raw_data,
sizeof(struct mpq_streambuffer_buffer_desc));
sbuff->pending_buffers_count++;
}
+ spin_unlock(&sbuff->packet_data.lock);
wake_up_all(&sbuff->packet_data.queue);
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_pkt_write);
-
ssize_t mpq_streambuffer_data_write(
struct mpq_streambuffer *sbuff,
const u8 *buf, size_t len)
@@ -225,15 +300,27 @@
if ((NULL == sbuff) || (NULL == buf))
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
- if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
+ if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len)) {
+ spin_unlock(&sbuff->raw_data.lock);
return -ENOSPC;
+ }
/*
* Secure buffers are not permitted to be mapped into kernel
* memory, and so buffer base address may be NULL
*/
- if (NULL == sbuff->raw_data.data)
+ if (NULL == sbuff->raw_data.data) {
+ spin_unlock(&sbuff->raw_data.lock);
return -EPERM;
+ }
res = dvb_ringbuffer_write(&sbuff->raw_data, buf, len);
wake_up_all(&sbuff->raw_data.queue);
} else {
@@ -247,8 +334,10 @@
* Secure buffers are not permitted to be mapped into kernel
* memory, and so buffer base address may be NULL
*/
- if (NULL == desc->base)
+ if (NULL == desc->base) {
+ spin_unlock(&sbuff->raw_data.lock);
return -EPERM;
+ }
if ((sbuff->pending_buffers_count == sbuff->buffers_num) ||
((desc->size - desc->write_ptr) < len)) {
@@ -259,6 +348,7 @@
sbuff->buffers_num,
desc->write_ptr,
desc->size);
+ spin_unlock(&sbuff->raw_data.lock);
return -ENOSPC;
}
memcpy(desc->base + desc->write_ptr, buf, len);
@@ -266,6 +356,7 @@
res = len;
}
+ spin_unlock(&sbuff->raw_data.lock);
return res;
}
EXPORT_SYMBOL(mpq_streambuffer_data_write);
@@ -278,9 +369,19 @@
if (NULL == sbuff)
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
- if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len))
+ if (unlikely(dvb_ringbuffer_free(&sbuff->raw_data) < len)) {
+ spin_unlock(&sbuff->raw_data.lock);
return -ENOSPC;
+ }
DVB_RINGBUFFER_PUSH(&sbuff->raw_data, len);
wake_up_all(&sbuff->raw_data.queue);
@@ -295,11 +396,13 @@
MPQ_DVB_ERR_PRINT(
"%s: No space available!\n",
__func__);
+ spin_unlock(&sbuff->raw_data.lock);
return -ENOSPC;
}
desc->write_ptr += len;
}
+ spin_unlock(&sbuff->raw_data.lock);
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_data_write_deposit);
@@ -314,13 +417,23 @@
if ((NULL == sbuff) || (NULL == buf))
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
/*
* Secure buffers are not permitted to be mapped into kernel
* memory, and so buffer base address may be NULL
*/
- if (NULL == sbuff->raw_data.data)
+ if (NULL == sbuff->raw_data.data) {
+ spin_unlock(&sbuff->raw_data.lock);
return -EPERM;
+ }
actual_len = dvb_ringbuffer_avail(&sbuff->raw_data);
if (actual_len < len)
@@ -340,8 +453,10 @@
* Secure buffers are not permitted to be mapped into kernel
* memory, and so buffer base address may be NULL
*/
- if (NULL == desc->base)
+ if (NULL == desc->base) {
+ spin_unlock(&sbuff->raw_data.lock);
return -EPERM;
+ }
actual_len = (desc->write_ptr - desc->read_ptr);
if (actual_len < len)
@@ -350,6 +465,7 @@
desc->read_ptr += len;
}
+ spin_unlock(&sbuff->raw_data.lock);
return len;
}
EXPORT_SYMBOL(mpq_streambuffer_data_read);
@@ -364,6 +480,10 @@
if ((NULL == sbuff) || (NULL == buf))
return -EINVAL;
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV)
+ return -ENODEV;
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
/*
* Secure buffers are not permitted to be mapped into kernel
@@ -397,6 +517,7 @@
len = actual_len;
if (copy_to_user(buf, desc->base + desc->read_ptr, len))
return -EFAULT;
+
desc->read_ptr += len;
}
@@ -404,7 +525,6 @@
}
EXPORT_SYMBOL(mpq_streambuffer_data_read_user);
-
int mpq_streambuffer_data_read_dispose(
struct mpq_streambuffer *sbuff,
size_t len)
@@ -412,9 +532,19 @@
if (NULL == sbuff)
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
- if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len))
+ if (unlikely(dvb_ringbuffer_avail(&sbuff->raw_data) < len)) {
+ spin_unlock(&sbuff->raw_data.lock);
return -EINVAL;
+ }
DVB_RINGBUFFER_SKIP(&sbuff->raw_data, len);
wake_up_all(&sbuff->raw_data.queue);
@@ -429,6 +559,8 @@
desc->read_ptr += len;
}
+ spin_unlock(&sbuff->raw_data.lock);
+
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_data_read_dispose);
@@ -444,6 +576,14 @@
if ((NULL == sbuff) || (NULL == handle))
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
*handle = sbuff->buffers[0].handle;
} else {
@@ -455,6 +595,9 @@
&sbuff->raw_data.data[sbuff->raw_data.pwrite];
*handle = desc->handle;
}
+
+ spin_unlock(&sbuff->raw_data.lock);
+
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_get_buffer_handle);
@@ -484,15 +627,29 @@
if (NULL == sbuff)
return -EINVAL;
- if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
- return dvb_ringbuffer_free(&sbuff->raw_data);
+ spin_lock(&sbuff->raw_data.lock);
- if (sbuff->pending_buffers_count == sbuff->buffers_num)
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return dvb_ringbuffer_free(&sbuff->raw_data);
+ }
+
+ if (sbuff->pending_buffers_count == sbuff->buffers_num) {
+ spin_unlock(&sbuff->raw_data.lock);
return 0;
+ }
desc = (struct mpq_streambuffer_buffer_desc *)
&sbuff->raw_data.data[sbuff->raw_data.pwrite];
+ spin_unlock(&sbuff->raw_data.lock);
+
return desc->size - desc->write_ptr;
}
EXPORT_SYMBOL(mpq_streambuffer_data_free);
@@ -506,12 +663,25 @@
if (NULL == sbuff)
return -EINVAL;
- if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode)
- return dvb_ringbuffer_avail(&sbuff->raw_data);
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
+ if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
+ ssize_t avail = dvb_ringbuffer_avail(&sbuff->raw_data);
+ spin_unlock(&sbuff->raw_data.lock);
+ return avail;
+ }
desc = (struct mpq_streambuffer_buffer_desc *)
&sbuff->raw_data.data[sbuff->raw_data.pread];
+ spin_unlock(&sbuff->raw_data.lock);
+
return desc->write_ptr - desc->read_ptr;
}
EXPORT_SYMBOL(mpq_streambuffer_data_avail);
@@ -524,6 +694,14 @@
if (NULL == sbuff)
return -EINVAL;
+ spin_lock(&sbuff->raw_data.lock);
+
+ /* check if buffer was released */
+ if (sbuff->raw_data.error == -ENODEV) {
+ spin_unlock(&sbuff->raw_data.lock);
+ return -ENODEV;
+ }
+
if (MPQ_STREAMBUFFER_BUFFER_MODE_RING == sbuff->mode) {
if (read_offset)
*read_offset = sbuff->raw_data.pread;
@@ -544,6 +722,8 @@
}
}
+ spin_unlock(&sbuff->raw_data.lock);
+
return 0;
}
EXPORT_SYMBOL(mpq_streambuffer_get_data_rw_offset);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 499b36c..83b9bb3 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -75,10 +75,6 @@
module_param(video_nonsecure_ion_heap, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(video_nonsecure_ion_heap, "ION heap for non-secure video buffer allocation");
-static int generate_es_events;
-module_param(generate_es_events, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(generate_es_events, "Generate new elementary stream data events");
-
/* Value of TS packet scramble bits field for even key */
static int mpq_sdmx_scramble_even = 0x2;
module_param(mpq_sdmx_scramble_even, int, S_IRUGO | S_IWUSR);
@@ -1224,13 +1220,6 @@
{
struct mpq_demux *mpq_demux = feed->demux->priv;
- if (!generate_es_events) {
- MPQ_DVB_ERR_PRINT(
- "%s: Cannot release decoder buffer when not working with new elementary stream data events\n",
- __func__);
- return -EPERM;
- }
-
if (cookie < 0) {
MPQ_DVB_ERR_PRINT("%s: invalid cookie parameter\n", __func__);
return -EINVAL;
@@ -1480,7 +1469,6 @@
dec_buffs->buffers_size,
dec_buffs->is_linear);
- feed_data->buffer_desc.decoder_buffers_num = dec_buffs->buffers_num;
if (0 == dec_buffs->buffers_num)
ret = mpq_dmx_init_internal_buffers(
feed_data, dec_buffs, client);
@@ -1526,6 +1514,8 @@
mpq_adapter_unregister_stream_if(feed_data->stream_interface);
+ mpq_streambuffer_terminate(video_buffer);
+
vfree(video_buffer->packet_data.data);
buf_num = feed_data->buffer_desc.decoder_buffers_num;
@@ -2834,13 +2824,11 @@
__func__);
}
- if (generate_es_events) {
- mpq_dmx_prepare_es_event_data(
- &packet, &meta_data, feed_data,
- stream_buffer, &data);
+ mpq_dmx_prepare_es_event_data(
+ &packet, &meta_data, feed_data,
+ stream_buffer, &data);
- feed->data_ready_cb.ts(&feed->feed.ts, &data);
- }
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
feed_data->pending_pattern_len = 0;
mpq_streambuffer_get_data_rw_offset(
@@ -2975,15 +2963,13 @@
NULL,
&feed_data->frame_offset);
- if (generate_es_events) {
- mpq_dmx_prepare_es_event_data(
- &packet, &meta_data,
- feed_data,
- stream_buffer, &data);
+ mpq_dmx_prepare_es_event_data(
+ &packet, &meta_data,
+ feed_data,
+ stream_buffer, &data);
- feed->data_ready_cb.ts(
- &feed->feed.ts, &data);
- }
+ feed->data_ready_cb.ts(
+ &feed->feed.ts, &data);
} else {
MPQ_DVB_ERR_PRINT(
"%s: received PUSI"
@@ -4122,6 +4108,8 @@
int ret;
int pes_cnt = 0;
struct dmx_data_ready data_event;
+ struct dmx_data_ready data;
+ struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
if ((!sts->metadata_fill_count) && (!sts->data_fill_count))
goto decoder_filter_check_overflow;
@@ -4249,15 +4237,11 @@
mpq_dmx_update_decoder_stat(mpq_demux);
mpq_streambuffer_pkt_write(sbuf, &packet, (u8 *)&meta_data);
- if (generate_es_events) {
- struct dmx_data_ready data;
- struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
- mpq_dmx_prepare_es_event_data(
- &packet, &meta_data, &mpq_feed->video_info,
- sbuf, &data);
- MPQ_DVB_DBG_PRINT("%s: Notify ES Event\n", __func__);
- feed->data_ready_cb.ts(&feed->feed.ts, &data);
- }
+ mpq_dmx_prepare_es_event_data(
+ &packet, &meta_data, &mpq_feed->video_info,
+ sbuf, &data);
+ MPQ_DVB_DBG_PRINT("%s: Notify ES Event\n", __func__);
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
spin_unlock(&mpq_feed->video_info.video_buffer_lock);
}
diff --git a/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h b/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
index 3804fb2..1707c85 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_stream_buffer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -211,6 +211,18 @@
size_t packet_buff_size);
/**
+ * mpq_streambuffer_terminate - Terminate stream buffer
+ *
+ * @sbuff: The buffer to terminate
+ *
+ * The function sets the the buffers error flags to ENODEV
+ * and wakeup any waiting threads on the buffer queues.
+ * Threads waiting on the buffer queues should check if
+ * error was set.
+ */
+void mpq_streambuffer_terminate(struct mpq_streambuffer *sbuff);
+
+/**
* mpq_streambuffer_packet_next - Returns index of next available packet.
*
* @sbuff: The stream buffer
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index f8460be..addd235 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -34,6 +34,17 @@
HFI_H264_PROFILE_CONSTRAINED_HIGH,
};
+static int entropy_mode[] = {
+ [ilog2(HAL_H264_ENTROPY_CAVLC)] = HFI_H264_ENTROPY_CAVLC,
+ [ilog2(HAL_H264_ENTROPY_CABAC)] = HFI_H264_ENTROPY_CABAC,
+};
+
+static int cabac_model[] = {
+ [ilog2(HAL_H264_CABAC_MODEL_0)] = HFI_H264_CABAC_MODEL_0,
+ [ilog2(HAL_H264_CABAC_MODEL_1)] = HFI_H264_CABAC_MODEL_1,
+ [ilog2(HAL_H264_CABAC_MODEL_2)] = HFI_H264_CABAC_MODEL_2,
+};
+
static inline int hal_to_hfi_type(int property, int hal_type)
{
if (hal_type && (roundup_pow_of_two(hal_type) != hal_type)) {
@@ -49,6 +60,12 @@
case HAL_PARAM_PROFILE_LEVEL_CURRENT:
return (hal_type >= ARRAY_SIZE(profile_table)) ?
-ENOTSUPP : profile_table[hal_type];
+ case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+ return (hal_type >= ARRAY_SIZE(entropy_mode)) ?
+ -ENOTSUPP : entropy_mode[hal_type];
+ case HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL:
+ return (hal_type >= ARRAY_SIZE(cabac_model)) ?
+ -ENOTSUPP : cabac_model[hal_type];
default:
return -ENOTSUPP;
}
@@ -918,35 +935,13 @@
HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
hfi = (struct hfi_h264_entropy_control *)
&pkt->rg_property_data[1];
- switch (prop->entropy_mode) {
- case HAL_H264_ENTROPY_CAVLC:
- hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
- break;
- case HAL_H264_ENTROPY_CABAC:
- hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
- switch (prop->cabac_model) {
- case HAL_H264_CABAC_MODEL_0:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
- break;
- case HAL_H264_CABAC_MODEL_1:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
- break;
- case HAL_H264_CABAC_MODEL_2:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
- break;
- default:
- dprintk(VIDC_ERR,
- "Invalid cabac model 0x%x",
- prop->entropy_mode);
- break;
- }
- break;
- default:
- dprintk(VIDC_ERR,
- "Invalid entropy selected: 0x%x",
- prop->cabac_model);
- break;
- }
+ hfi->entropy_mode = hal_to_hfi_type(
+ HAL_PARAM_VENC_H264_ENTROPY_CONTROL,
+ prop->entropy_mode);
+ if (hfi->entropy_mode == HAL_H264_ENTROPY_CABAC)
+ hfi->cabac_model = hal_to_hfi_type(
+ HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
+ prop->cabac_model);
pkt->size += sizeof(u32) + sizeof(
struct hfi_h264_entropy_control);
break;
@@ -1165,6 +1160,16 @@
sizeof(struct hfi_index_extradata_config);
break;
}
+ case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_SLICE_DELIVERY_MODE;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hal_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
+ break;
+ }
case HAL_CONFIG_VPE_DEINTERLACE:
break;
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
@@ -1187,7 +1192,6 @@
case HAL_PARAM_VDEC_MB_QUANTIZATION:
case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
- case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
case HAL_CONFIG_VDEC_MULTI_STREAM:
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index be9458d..102e1ec 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -305,11 +305,213 @@
callback(RELEASE_RESOURCE_DONE, &cmd_done);
}
+static inline void copy_cap_prop(
+ struct hfi_capability_supported *in,
+ struct vidc_hal_session_init_done *sess_init_done)
+{
+ struct hal_capability_supported *out = NULL;
+ switch (in->capability_type) {
+ case HFI_CAPABILITY_FRAME_WIDTH:
+ out = &sess_init_done->width;
+ break;
+
+ case HFI_CAPABILITY_FRAME_HEIGHT:
+ out = &sess_init_done->height;
+ break;
+
+ case HFI_CAPABILITY_MBS_PER_FRAME:
+ out = &sess_init_done->mbs_per_frame;
+ break;
+
+ case HFI_CAPABILITY_MBS_PER_SECOND:
+ out = &sess_init_done->mbs_per_sec;
+ break;
+
+ case HFI_CAPABILITY_FRAMERATE:
+ out = &sess_init_done->frame_rate;
+ break;
+
+ case HFI_CAPABILITY_SCALE_X:
+ out = &sess_init_done->scale_x;
+ break;
+
+ case HFI_CAPABILITY_SCALE_Y:
+ out = &sess_init_done->scale_y;
+ break;
+
+ case HFI_CAPABILITY_BITRATE:
+ out = &sess_init_done->bitrate;
+ break;
+ }
+
+ if (in && out) {
+ out->capability_type =
+ (enum hal_capability)in->capability_type;
+ out->min = in->min;
+ out->max = in->max;
+ out->step_size = in->step_size;
+ }
+}
+
enum vidc_status hfi_process_sess_init_done_prop_read(
struct hfi_msg_sys_session_init_done_packet *pkt,
- struct msm_vidc_cb_cmd_done *cmddone)
+ struct vidc_hal_session_init_done *sess_init_done)
{
- return VIDC_ERR_NONE;
+ u32 rem_bytes, num_properties;
+ u8 *data_ptr;
+ u32 status = VIDC_ERR_NONE;
+ u32 prop_id, next_offset = 0;
+
+ rem_bytes = pkt->size - sizeof(struct
+ hfi_msg_sys_session_init_done_packet) + sizeof(u32);
+
+ if (rem_bytes == 0) {
+ dprintk(VIDC_ERR,
+ "hfi_msg_sys_session_init_done:missing_prop_info");
+ return VIDC_ERR_FAIL;
+ }
+
+ status = hfi_map_err_status((u32)pkt->error_type);
+
+ if (status)
+ return status;
+
+ data_ptr = (u8 *) &pkt->rg_property_data[0];
+ num_properties = pkt->num_properties;
+
+ while ((status == VIDC_ERR_NONE) && num_properties &&
+ (rem_bytes >= sizeof(u32))) {
+ prop_id = *((u32 *)data_ptr);
+ next_offset = sizeof(u32);
+
+ switch (prop_id) {
+ case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
+ {
+ struct hfi_capability_supported_info *prop =
+ (struct hfi_capability_supported_info *)
+ (data_ptr + next_offset);
+ u32 num_capabilities;
+ struct hfi_capability_supported *cap_ptr;
+
+ if ((rem_bytes - next_offset) < sizeof(*cap_ptr)) {
+ status = VIDC_ERR_BAD_PARAM;
+ break;
+ }
+
+ num_capabilities = prop->num_capabilities;
+ cap_ptr = &prop->rg_data[0];
+ next_offset += sizeof(u32);
+
+ while (num_capabilities &&
+ ((rem_bytes - next_offset) >= sizeof(u32))) {
+ copy_cap_prop(cap_ptr, sess_init_done);
+ cap_ptr++;
+ next_offset += sizeof(*cap_ptr);
+ num_capabilities--;
+ }
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+ {
+ struct hfi_uncompressed_format_supported *prop =
+ (struct hfi_uncompressed_format_supported *)
+ (data_ptr + next_offset);
+
+ u32 num_format_entries;
+ char *fmt_ptr;
+ struct hfi_uncompressed_plane_info *plane_info;
+
+ if ((rem_bytes - next_offset) < sizeof(*prop)) {
+ status = VIDC_ERR_BAD_PARAM;
+ break;
+ }
+ num_format_entries = prop->format_entries;
+ next_offset = sizeof(*prop) - sizeof(u32);
+ fmt_ptr = (char *)&prop->rg_format_info[0];
+
+ while (num_format_entries) {
+ u32 bytes_to_skip;
+ plane_info =
+ (struct hfi_uncompressed_plane_info *) fmt_ptr;
+
+ if ((rem_bytes - next_offset) <
+ sizeof(*plane_info)) {
+ status = VIDC_ERR_BAD_PARAM;
+ break;
+ }
+ bytes_to_skip = sizeof(*plane_info) -
+ sizeof(struct
+ hfi_uncompressed_plane_constraints) +
+ plane_info->num_planes *
+ sizeof(struct
+ hfi_uncompressed_plane_constraints);
+
+ fmt_ptr += bytes_to_skip;
+ next_offset += bytes_to_skip;
+ num_format_entries--;
+ }
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED:
+ {
+ struct hfi_properties_supported *prop =
+ (struct hfi_properties_supported *)
+ (data_ptr + next_offset);
+
+ next_offset += sizeof(*prop) - sizeof(u32)
+ + prop->num_properties * sizeof(u32);
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
+ {
+ struct hfi_profile_level_supported *prop =
+ (struct hfi_profile_level_supported *)
+ (data_ptr + next_offset);
+
+ next_offset += sizeof(*prop) -
+ sizeof(struct hfi_profile_level) +
+ prop->profile_count *
+ sizeof(struct hfi_profile_level);
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+ {
+ next_offset +=
+ sizeof(struct hfi_nal_stream_format_supported);
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT:
+ {
+ next_offset += sizeof(u32);
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+ {
+ next_offset += sizeof(u32);
+ num_properties--;
+ break;
+ }
+ case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH:
+ {
+ next_offset +=
+ sizeof(struct hfi_intra_refresh);
+ num_properties--;
+ break;
+ }
+ default:
+ dprintk(VIDC_DBG,
+ "%s default case - 0x%x", __func__, prop_id);
+ }
+ rem_bytes -= next_offset;
+ data_ptr += next_offset;
+ }
+ return status;
}
static void hfi_process_sess_get_prop_buf_req(
@@ -493,7 +695,7 @@
cmd_done.data = &session_init_done;
if (!cmd_done.status) {
cmd_done.status = hfi_process_sess_init_done_prop_read(
- pkt, &cmd_done);
+ pkt, &session_init_done);
}
cmd_done.size = sizeof(struct vidc_hal_session_init_done);
callback(SESSION_INIT_DONE, &cmd_done);
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 663cc40..d782227 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -682,6 +682,13 @@
{
return 0;
}
+
+static int msm_v4l2_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+{
+ struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+ return msm_vidc_enum_framesizes((void *)vidc_inst, fsize);
+}
static const struct v4l2_ioctl_ops msm_v4l2_ioctl_ops = {
.vidioc_querycap = msm_v4l2_querycap,
.vidioc_enum_fmt_vid_cap_mplane = msm_v4l2_enum_fmt,
@@ -703,7 +710,8 @@
.vidioc_decoder_cmd = msm_v4l2_decoder_cmd,
.vidioc_encoder_cmd = msm_v4l2_encoder_cmd,
.vidioc_s_parm = msm_v4l2_s_parm,
- .vidioc_g_parm = msm_v4l2_g_parm
+ .vidioc_g_parm = msm_v4l2_g_parm,
+ .vidioc_enum_framesizes = msm_v4l2_enum_framesizes,
};
static const struct v4l2_ioctl_ops msm_v4l2_enc_ioctl_ops = {
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 5966d12..2ca5008 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -20,10 +20,6 @@
#include "msm_vidc_debug.h"
#define MSM_VDEC_DVC_NAME "msm_vdec_8974"
-#define DEFAULT_HEIGHT 720
-#define DEFAULT_WIDTH 1280
-#define MAX_SUPPORTED_WIDTH 3820
-#define MAX_SUPPORTED_HEIGHT 2160
#define MIN_NUM_OUTPUT_BUFFERS 4
#define MAX_NUM_OUTPUT_BUFFERS 6
@@ -245,10 +241,10 @@
static u32 get_frame_size_compressed(int plane,
u32 height, u32 width)
{
- return (MAX_SUPPORTED_WIDTH * MAX_SUPPORTED_HEIGHT * 3/2)/2;
+ return (width * height * 3/2)/2;
}
-static const struct msm_vidc_format vdec_formats[] = {
+struct msm_vidc_format vdec_formats[] = {
{
.name = "YCbCr Semiplanar 4:2:0",
.description = "Y/CbCr 4:2:0",
@@ -306,6 +302,14 @@
.type = OUTPUT_PORT,
},
{
+ .name = "HEVC",
+ .description = "HEVC compressed format",
+ .fourcc = V4L2_PIX_FMT_HEVC,
+ .num_planes = 1,
+ .get_frame_size = get_frame_size_compressed,
+ .type = OUTPUT_PORT,
+ },
+ {
.name = "VP8",
.description = "VP8 compressed format",
.fourcc = V4L2_PIX_FMT_VP8,
@@ -582,7 +586,6 @@
int stride, scanlines;
int extra_idx = 0;
int rc = 0;
- int ret;
int i;
struct hal_buffer_requirements *buff_req_buffer;
if (!inst || !f || !inst->core || !inst->core->device) {
@@ -602,6 +605,12 @@
if (inst->in_reconfig == true) {
inst->prop.height = inst->reconfig_height;
inst->prop.width = inst->reconfig_width;
+ rc = msm_vidc_check_session_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: session not supported\n", __func__);
+ goto exit;
+ }
}
f->fmt.pix_mp.height = inst->prop.height;
f->fmt.pix_mp.width = inst->prop.width;
@@ -612,15 +621,25 @@
frame_sz.height = inst->prop.height;
dprintk(VIDC_DBG, "width = %d, height = %d\n",
frame_sz.width, frame_sz.height);
- ret = msm_comm_try_set_prop(inst,
+ rc = msm_comm_try_set_prop(inst,
HAL_PARAM_FRAME_SIZE, &frame_sz);
- ret = ret || msm_comm_try_get_bufreqs(inst);
- if (ret || (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: Failed : Frame size setting\n", __func__);
+ goto exit;
+ }
+ rc = msm_comm_try_get_bufreqs(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: Failed : Buffer requirements\n", __func__);
+ goto exit;
+ }
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
for (i = 0; i < fmt->num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
fmt->get_frame_size(i,
- f->fmt.pix_mp.height,
- f->fmt.pix_mp.width);
+ inst->capability.height.max,
+ inst->capability.width.max);
inst->bufq[OUTPUT_PORT].
vb2_bufq.plane_sizes[i] =
f->fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -680,6 +699,7 @@
f->type);
rc = -EINVAL;
}
+exit:
return rc;
}
int msm_vdec_s_parm(struct msm_vidc_inst *inst, struct v4l2_streamparm *a)
@@ -717,7 +737,7 @@
}
int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
{
- const struct msm_vidc_format *fmt = NULL;
+ struct msm_vidc_format *fmt = NULL;
struct hal_frame_size frame_sz;
int extra_idx = 0;
int rc = 0;
@@ -755,8 +775,8 @@
for (i = 0; i < fmt->num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
fmt->get_frame_size(i,
- f->fmt.pix_mp.height,
- f->fmt.pix_mp.width);
+ inst->capability.height.max,
+ inst->capability.width.max);
}
} else {
buff_req_buffer =
@@ -787,6 +807,12 @@
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
inst->prop.width = f->fmt.pix_mp.width;
inst->prop.height = f->fmt.pix_mp.height;
+ rc = msm_vidc_check_session_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: session not supported\n", __func__);
+ goto err_invalid_fmt;
+ }
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats),
f->fmt.pix_mp.pixelformat,
@@ -809,8 +835,8 @@
frame_sz.height = inst->prop.height;
msm_comm_try_set_prop(inst, HAL_PARAM_FRAME_SIZE, &frame_sz);
f->fmt.pix_mp.plane_fmt[0].sizeimage =
- fmt->get_frame_size(0, f->fmt.pix_mp.height,
- f->fmt.pix_mp.width);
+ fmt->get_frame_size(0, inst->capability.height.max,
+ inst->capability.width.max);
f->fmt.pix_mp.num_planes = fmt->num_planes;
for (i = 0; i < fmt->num_planes; ++i) {
inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i] =
@@ -903,7 +929,8 @@
*num_buffers = MIN_NUM_OUTPUT_BUFFERS;
for (i = 0; i < *num_planes; i++) {
sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
- i, inst->prop.height, inst->prop.width);
+ i, inst->capability.height.max,
+ inst->capability.width.max);
}
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
@@ -1161,6 +1188,10 @@
inst->fmts[CAPTURE_PORT] = &vdec_formats[0];
inst->prop.height = DEFAULT_HEIGHT;
inst->prop.width = DEFAULT_WIDTH;
+ inst->capability.height.min = MIN_SUPPORTED_HEIGHT;
+ inst->capability.height.max = DEFAULT_HEIGHT;
+ inst->capability.width.min = MIN_SUPPORTED_WIDTH;
+ inst->capability.width.max = DEFAULT_WIDTH;
inst->prop.fps = 30;
inst->prop.prev_time_stamp = 0;
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 072f4ab..bf29a95 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -19,10 +19,7 @@
#include "msm_vidc_debug.h"
#define MSM_VENC_DVC_NAME "msm_venc_8974"
-#define DEFAULT_HEIGHT 720
-#define DEFAULT_WIDTH 1280
#define MIN_NUM_OUTPUT_BUFFERS 4
-#define MAX_NUM_OUTPUT_BUFFERS 8
#define MIN_BIT_RATE 64000
#define MAX_BIT_RATE 160000000
#define DEFAULT_BIT_RATE 64000
@@ -88,6 +85,27 @@
"High Latency",
};
+static const char *const mpeg_video_vidc_extradata[] = {
+ "Extradata none",
+ "Extradata MB Quantization",
+ "Extradata Interlace Video",
+ "Extradata VC1 Framedisp",
+ "Extradata VC1 Seqdisp",
+ "Extradata timestamp",
+ "Extradata S3D Frame Packing",
+ "Extradata Frame Rate",
+ "Extradata Panscan Window",
+ "Extradata Recovery point SEI",
+ "Extradata Closed Caption UD",
+ "Extradata AFD UD",
+ "Extradata Multislice info",
+ "Extradata number of concealed MB",
+ "Extradata metadata filler",
+ "Extradata input crop",
+ "Extradata digital zoom",
+ "Extradata aspect ratio",
+};
+
enum msm_venc_ctrl_cluster {
MSM_VENC_CTRL_CLUSTER_QP = 1,
MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD,
@@ -439,6 +457,18 @@
.cluster = MSM_VENC_CTRL_CLUSTER_SLICING,
},
{
+ .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE,
+ .name = "Slice delivery mode",
+ .type = V4L2_CTRL_TYPE_BUTTON,
+ .minimum = 0,
+ .maximum = 1,
+ .default_value = 0,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .qmenu = NULL,
+ .cluster = MSM_VENC_CTRL_CLUSTER_SLICING,
+ },
+ {
.id = V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE,
.name = "Intra Refresh Mode",
.type = V4L2_CTRL_TYPE_MENU,
@@ -557,6 +587,36 @@
.qmenu = NULL,
.cluster = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA,
+ .name = "Extradata Type",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+ .maximum = V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+ .default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_MB_QUANTIZATION) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_INTERLACE_VIDEO) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_FRAMEDISP) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_VC1_SEQDISP) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_TIMESTAMP) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_S3D_FRAME_PACKING) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_RATE) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_PANSCAN_WINDOW) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_RECOVERY_POINT_SEI) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_CLOSED_CAPTION_UD) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_AFD_UD) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB) |
+ (1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
+ (1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
+ (1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
+ (1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO)
+ ),
+ .qmenu = mpeg_video_vidc_extradata,
+ .step = 0,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -578,7 +638,7 @@
return sz;
}
-static const struct msm_vidc_format venc_formats[] = {
+static struct msm_vidc_format venc_formats[] = {
{
.name = "YCbCr Semiplanar 4:2:0",
.description = "Y/CbCr 4:2:0",
@@ -640,6 +700,9 @@
struct hal_buffer_count_actual new_buf_count;
enum hal_property property_id;
struct hfi_device *hdev;
+ struct hal_buffer_requirements *buff_req;
+ struct v4l2_ctrl *ctrl = NULL;
+ u32 extradata = 0;
if (!q || !q->drv_priv) {
dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
return -EINVAL;
@@ -655,13 +718,33 @@
switch (q->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
*num_planes = 1;
- if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS ||
- *num_buffers > MAX_NUM_OUTPUT_BUFFERS)
- *num_buffers = MIN_NUM_OUTPUT_BUFFERS;
+ buff_req = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ *num_buffers = buff_req->buffer_count_actual =
+ max(*num_buffers, buff_req->buffer_count_actual);
+ if (*num_buffers > VIDEO_MAX_FRAME) {
+ dprintk(VIDC_ERR,
+ "Failed : No of slices requested = %d"\
+ " Max supported slices = %d",
+ *num_buffers, VIDEO_MAX_FRAME);
+ rc = -EINVAL;
+ break;
+ }
+ ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+ V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
+ if (ctrl)
+ extradata = v4l2_ctrl_g_ctrl(ctrl);
+ if (extradata)
+ *num_planes = *num_planes + 1;
+ inst->fmts[CAPTURE_PORT]->num_planes = *num_planes;
for (i = 0; i < *num_planes; i++) {
sizes[i] = inst->fmts[CAPTURE_PORT]->get_frame_size(
i, inst->prop.height, inst->prop.width);
}
+ property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+ new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
+ new_buf_count.buffer_count_actual = *num_buffers;
+ rc = call_hfi_op(hdev, session_set_property, inst->session,
+ property_id, &new_buf_count);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
@@ -957,6 +1040,26 @@
default:
goto unknown_value;
}
+ case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+ switch (value) {
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC:
+ return HAL_H264_ENTROPY_CAVLC;
+ case V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC:
+ return HAL_H264_ENTROPY_CABAC;
+ default:
+ goto unknown_value;
+ }
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
+ switch (value) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_0:
+ return HAL_H264_CABAC_MODEL_0;
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_1:
+ return HAL_H264_CABAC_MODEL_1;
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL_2:
+ return HAL_H264_CABAC_MODEL_2;
+ default:
+ goto unknown_value;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
switch (value) {
case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0:
@@ -1158,8 +1261,11 @@
property_id =
HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
- h264_entropy_control.entropy_mode = ctrl->val;
- h264_entropy_control.cabac_model = temp_ctrl->val;
+ h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+ V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+ h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+ V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+ temp_ctrl->val);
pdata = &h264_entropy_control;
break;
case V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL:
@@ -1167,8 +1273,11 @@
property_id =
HAL_PARAM_VENC_H264_ENTROPY_CONTROL;
- h264_entropy_control.cabac_model = ctrl->val;
- h264_entropy_control.entropy_mode = temp_ctrl->val;
+ h264_entropy_control.cabac_model = venc_v4l2_to_hal(
+ V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE, ctrl->val);
+ h264_entropy_control.entropy_mode = venc_v4l2_to_hal(
+ V4L2_CID_MPEG_VIDC_VIDEO_H264_CABAC_MODEL,
+ temp_ctrl->val);
pdata = &h264_entropy_control;
break;
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
@@ -1342,6 +1451,25 @@
multi_slice_control.slice_size = ctrl->val;
pdata = &multi_slice_control;
break;
+ case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE: {
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE);
+ if ((temp_ctrl->val ==
+ V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) &&
+ (inst->fmts[CAPTURE_PORT]->fourcc ==
+ V4L2_PIX_FMT_H264 ||
+ inst->fmts[CAPTURE_PORT]->fourcc ==
+ V4L2_PIX_FMT_H264_NO_SC)) {
+ property_id = HAL_PARAM_VENC_SLICE_DELIVERY_MODE;
+ enable.enable = true;
+ } else {
+ dprintk(VIDC_WARN,
+ "Failed : slice delivery mode is valid "\
+ "only for H264 encoder and MB based slicing");
+ enable.enable = false;
+ }
+ pdata = &enable;
+ break;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_INTRA_REFRESH_MODE: {
struct v4l2_ctrl *air_mbs, *air_ref, *cir_mbs;
air_mbs = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_AIR_MBS);
@@ -1452,6 +1580,15 @@
inst->mode = VIDC_SECURE;
dprintk(VIDC_INFO, "Setting secure mode to :%d\n", inst->mode);
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA:
+ {
+ struct hal_extradata_enable extra;
+ property_id = HAL_PARAM_INDEX_EXTRADATA;
+ extra.index = msm_comm_get_hal_extradata_index(ctrl->val);
+ extra.enable = 1;
+ pdata = &extra;
+ break;
+ }
default:
rc = -ENOTSUPP;
break;
@@ -1676,7 +1813,7 @@
}
int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
{
- const struct msm_vidc_format *fmt = NULL;
+ struct msm_vidc_format *fmt = NULL;
struct hal_frame_size frame_sz;
int rc = 0;
int i;
@@ -1707,6 +1844,12 @@
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
inst->prop.width = f->fmt.pix_mp.width;
inst->prop.height = f->fmt.pix_mp.height;
+ rc = msm_vidc_check_session_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: session not supported\n", __func__);
+ goto exit;
+ }
frame_sz.buffer_type = HAL_BUFFER_INPUT;
frame_sz.width = inst->prop.width;
frame_sz.height = inst->prop.height;
@@ -1768,6 +1911,7 @@
const struct msm_vidc_format *fmt = NULL;
int rc = 0;
int i;
+ int extra_idx = 0;
if (!inst || !f) {
dprintk(VIDC_ERR,
"Invalid input, inst = %p, format = %p\n", inst, f);
@@ -1788,6 +1932,16 @@
fmt->get_frame_size(i, inst->prop.height,
inst->prop.width);
}
+ extra_idx = EXTRADATA_IDX(fmt->num_planes);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ f->fmt.pix_mp.plane_fmt[extra_idx].sizeimage =
+ inst->buff_req.buffer
+ [HAL_BUFFER_EXTRADATA_OUTPUT].buffer_size;
+ }
+ for (i = 0; i < fmt->num_planes; ++i) {
+ inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] =
+ f->fmt.pix_mp.plane_fmt[i].sizeimage;
+ }
} else {
dprintk(VIDC_ERR,
"Buf type not recognized, type = %d\n", f->type);
@@ -1827,6 +1981,7 @@
int i;
struct vidc_buffer_addr_info buffer_info;
struct hfi_device *hdev;
+ int extra_idx = 0;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1839,24 +1994,41 @@
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- for (i = 0; i < b->length; i++) {
- dprintk(VIDC_DBG,
- "device_addr = %ld, size = %d\n",
+ if (b->length != inst->fmts[CAPTURE_PORT]->num_planes) {
+ dprintk(VIDC_ERR,
+ "Planes mismatch: needed: %d, allocated: %d\n",
+ inst->fmts[CAPTURE_PORT]->num_planes,
+ b->length);
+ rc = -EINVAL;
+ break;
+ }
+
+ for (i = 0; (i < b->length) && (i < VIDEO_MAX_PLANES); i++) {
+ dprintk(VIDC_DBG, "device_addr = 0x%lx, size = %d\n",
b->m.planes[i].m.userptr,
b->m.planes[i].length);
- buffer_info.buffer_size = b->m.planes[i].length;
- buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
- buffer_info.num_buffers = 1;
- buffer_info.align_device_addr =
- b->m.planes[i].m.userptr;
- buffer_info.extradata_size = 0;
- buffer_info.extradata_addr = 0;
- rc = call_hfi_op(hdev, session_set_buffers,
- (void *)inst->session, &buffer_info);
- if (rc)
- dprintk(VIDC_ERR,
- "vidc_hal_session_set_buffers failed");
}
+ buffer_info.buffer_size = b->m.planes[0].length;
+ buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
+ buffer_info.num_buffers = 1;
+ buffer_info.align_device_addr =
+ b->m.planes[0].m.userptr;
+
+ extra_idx = EXTRADATA_IDX(b->length);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ buffer_info.extradata_addr =
+ b->m.planes[extra_idx].m.userptr;
+ dprintk(VIDC_DBG, "extradata: 0x%lx\n",
+ b->m.planes[extra_idx].m.userptr);
+ buffer_info.extradata_size =
+ b->m.planes[extra_idx].length;
+ }
+
+ rc = call_hfi_op(hdev, session_set_buffers,
+ (void *)inst->session, &buffer_info);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "vidc_hal_session_set_buffers failed");
break;
default:
dprintk(VIDC_ERR,
@@ -1869,8 +2041,7 @@
int msm_venc_release_buf(struct msm_vidc_inst *inst,
struct v4l2_buffer *b)
{
- int rc = 0;
- int i;
+ int i, rc = 0, extra_idx = 0;
struct vidc_buffer_addr_info buffer_info;
struct hfi_device *hdev;
@@ -1891,24 +2062,36 @@
switch (b->type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
break;
- case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: {
+ if (b->length !=
+ inst->fmts[CAPTURE_PORT]->num_planes) {
+ dprintk(VIDC_ERR,
+ "Planes mismatch: needed: %d, to release: %d\n",
+ inst->fmts[CAPTURE_PORT]->num_planes,
+ b->length);
+ rc = -EINVAL;
+ break;
+ }
for (i = 0; i < b->length; i++) {
dprintk(VIDC_DBG,
- "Release device_addr = %ld, size = %d, %d\n",
+ "Release device_addr = 0x%lx, size = %d, %d\n",
b->m.planes[i].m.userptr,
b->m.planes[i].length, inst->state);
- buffer_info.buffer_size = b->m.planes[i].length;
- buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
- buffer_info.num_buffers = 1;
- buffer_info.align_device_addr =
- b->m.planes[i].m.userptr;
- buffer_info.extradata_size = 0;
- buffer_info.extradata_addr = 0;
- buffer_info.response_required = false;
- rc = call_hfi_op(hdev, session_release_buffers,
+ }
+ buffer_info.buffer_size = b->m.planes[0].length;
+ buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
+ buffer_info.num_buffers = 1;
+ buffer_info.align_device_addr =
+ b->m.planes[0].m.userptr;
+ extra_idx = EXTRADATA_IDX(b->length);
+ if (extra_idx && (extra_idx < VIDEO_MAX_PLANES))
+ buffer_info.extradata_addr =
+ b->m.planes[extra_idx].m.userptr;
+ buffer_info.response_required = false;
+ rc = call_hfi_op(hdev, session_release_buffers,
(void *)inst->session, &buffer_info);
- if (rc)
- dprintk(VIDC_ERR,
+ if (rc)
+ dprintk(VIDC_ERR,
"vidc_hal_session_release_buffers failed\n");
}
break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 218987e..0fbfd72 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -299,6 +299,30 @@
return -EINVAL;
}
+
+int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize)
+{
+ struct msm_vidc_inst *inst = instance;
+ struct msm_vidc_core_capability *capability = NULL;
+
+ if (!inst || !fsize) {
+ dprintk(VIDC_ERR, "%s: invalid parameter: %p %p\n",
+ __func__, inst, fsize);
+ return -EINVAL;
+ }
+ if (!inst->core)
+ return -EINVAL;
+
+ capability = &inst->capability;
+ fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+ fsize->stepwise.min_width = capability->width.min;
+ fsize->stepwise.max_width = capability->width.max;
+ fsize->stepwise.step_width = capability->width.step_size;
+ fsize->stepwise.min_height = capability->height.min;
+ fsize->stepwise.max_height = capability->height.max;
+ fsize->stepwise.step_height = capability->height.step_size;
+ return 0;
+}
static void *vidc_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
{
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index ba3e393..30530d4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -142,9 +142,10 @@
}
mutex_lock(&vidc_driver->lock);
list_for_each_entry(core, &vidc_driver->cores, list) {
- if (core && core->id == core_id)
+ if (core && core->id == core_id) {
found = 1;
break;
+ }
}
mutex_unlock(&vidc_driver->lock);
if (found)
@@ -174,8 +175,8 @@
}
return &fmt[i];
}
-const struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
- const struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type)
+struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
+ struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type)
{
int i;
if (!fmt) {
@@ -350,7 +351,15 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
if (response) {
+ struct vidc_hal_session_init_done *session_init_done =
+ (struct vidc_hal_session_init_done *) response->data;
inst = (struct msm_vidc_inst *)response->session_id;
+
+ inst->capability.width = session_init_done->width;
+ inst->capability.height = session_init_done->height;
+ inst->capability.frame_rate =
+ session_init_done->frame_rate;
+ inst->capability.capability_set = true;
signal_session_msg_receipt(cmd, inst);
} else {
dprintk(VIDC_ERR,
@@ -358,22 +367,27 @@
}
}
+static void queue_v4l2_event(struct msm_vidc_inst *inst, int event_type)
+{
+ struct v4l2_event event = {.id = 0, .type = event_type};
+ v4l2_event_queue_fh(&inst->event_handler, &event);
+ wake_up(&inst->kernel_event_queue);
+}
+
static void handle_event_change(enum command_response cmd, void *data)
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct v4l2_event dqevent;
struct v4l2_control control = {0};
struct msm_vidc_cb_event *event_notify;
+ int event = 0;
int rc = 0;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
- dqevent.id = 0;
event_notify = (struct msm_vidc_cb_event *) response->data;
switch (event_notify->hal_event_type) {
case HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES:
- dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+ event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
control.id =
V4L2_CID_MPEG_VIDC_VIDEO_CONTINUE_DATA_TRANSFER;
rc = v4l2_g_ctrl(&inst->ctrl_handler, &control);
@@ -381,21 +395,24 @@
dprintk(VIDC_WARN,
"Failed to get Smooth streamng flag\n");
if (!rc && control.value == true)
- dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
+ event = V4L2_EVENT_SEQ_CHANGED_SUFFICIENT;
break;
case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
- dqevent.type =
- V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
+ event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
break;
default:
break;
}
+
inst->reconfig_height = event_notify->height;
inst->reconfig_width = event_notify->width;
inst->in_reconfig = true;
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
- wake_up(&inst->kernel_event_queue);
+
+ rc = msm_vidc_check_session_supported(inst);
+ if (!rc) {
+ queue_v4l2_event(inst, event);
+ }
+
return;
} else {
dprintk(VIDC_ERR,
@@ -485,13 +502,9 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct v4l2_event dqevent;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
- dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
- dqevent.id = 0;
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
- wake_up(&inst->kernel_event_queue);
+ queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
} else {
dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
}
@@ -501,7 +514,6 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst = NULL;
- struct v4l2_event dqevent;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
if (inst) {
@@ -510,10 +522,7 @@
mutex_lock(&inst->sync_lock);
inst->state = MSM_VIDC_CORE_INVALID;
mutex_unlock(&inst->sync_lock);
- dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
- dqevent.id = 0;
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
- wake_up(&inst->kernel_event_queue);
+ queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
}
} else {
dprintk(VIDC_ERR,
@@ -525,7 +534,6 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst = NULL ;
struct msm_vidc_core *core = NULL;
- struct v4l2_event dqevent;
if (response) {
core = get_vidc_core(response->device_id);
dprintk(VIDC_WARN, "SYS_ERROR received for core %p\n", core);
@@ -533,18 +541,14 @@
mutex_lock(&core->lock);
core->state = VIDC_CORE_INVALID;
mutex_unlock(&core->lock);
- dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
- dqevent.id = 0;
list_for_each_entry(inst, &core->instances,
list) {
- v4l2_event_queue_fh(&inst->event_handler,
- &dqevent);
-
mutex_lock(&inst->lock);
inst->state = MSM_VIDC_CORE_INVALID;
mutex_unlock(&inst->lock);
- wake_up(&inst->kernel_event_queue);
+ queue_v4l2_event(inst,
+ V4L2_EVENT_MSM_VIDC_SYS_ERROR);
}
} else {
dprintk(VIDC_ERR,
@@ -561,7 +565,6 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
struct msm_vidc_core *core = NULL;
- struct v4l2_event dqevent;
dprintk(VIDC_ERR, "Venus Subsystem crashed\n");
core = get_vidc_core(response->device_id);
if (!core) {
@@ -572,11 +575,9 @@
mutex_lock(&core->lock);
core->state = VIDC_CORE_INVALID;
mutex_unlock(&core->lock);
- dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
- dqevent.id = 0;
list_for_each_entry(inst, &core->instances, list) {
if (inst) {
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+ queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
mutex_lock(&inst->lock);
inst->state = MSM_VIDC_CORE_INVALID;
inst->session = NULL;
@@ -589,15 +590,11 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- struct v4l2_event dqevent;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
signal_session_msg_receipt(cmd, inst);
- dqevent.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
- dqevent.id = 0;
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+ queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_CLOSE_DONE);
inst->session = NULL;
- wake_up(&inst->kernel_event_queue);
show_stats(inst);
} else {
dprintk(VIDC_ERR,
@@ -1201,6 +1198,10 @@
HAL_VIDEO_CODEC_SPARK
HAL_VIDEO_CODEC_VP6
HAL_VIDEO_CODEC_VP7*/
+ case V4L2_PIX_FMT_HEVC:
+ codec = HAL_VIDEO_CODEC_HEVC;
+ break;
+
default:
dprintk(VIDC_ERR, "Wrong codec: %d\n", fourcc);
codec = HAL_UNUSED_CODEC;
@@ -1789,6 +1790,13 @@
mutex_unlock(&inst->sync_lock);
} else {
int64_t time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
+
+ rc = msm_vidc_check_session_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: session not supported\n", __func__);
+ goto err_no_mem;
+ }
do_div(time_usec, NSEC_PER_USEC);
memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
frame_data.alloc_len = vb->v4l2_planes[0].length;
@@ -2126,7 +2134,6 @@
static void msm_comm_flush_in_invalid_state(struct msm_vidc_inst *inst)
{
- struct v4l2_event dqevent = {0};
struct list_head *ptr, *next;
struct vb2_buffer *vb;
if (!list_empty(&inst->bufq[CAPTURE_PORT].
@@ -2163,9 +2170,7 @@
}
}
}
- dqevent.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
- dqevent.id = 0;
- v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+ queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
return;
}
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
@@ -2359,3 +2364,54 @@
hdev->hfi_device_data, type);
return rc;
}
+
+int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
+{
+ struct msm_vidc_core_capability *capability;
+ int rc = 0;
+ struct v4l2_event dqevent;
+
+ if (!inst) {
+ dprintk(VIDC_WARN, "%s: Invalid parameter\n", __func__);
+ return -EINVAL;
+ }
+ capability = &inst->capability;
+
+ if (inst->capability.capability_set) {
+ if (msm_vp8_low_tier &&
+ inst->fmts[OUTPUT_PORT]->fourcc == V4L2_PIX_FMT_VP8) {
+ capability->width.max = DEFAULT_WIDTH;
+ capability->height.max = DEFAULT_HEIGHT;
+ }
+ if (inst->prop.width < capability->width.min ||
+ inst->prop.width > capability->width.max ||
+ (inst->prop.width % capability->width.step_size != 0)) {
+ dprintk(VIDC_ERR,
+ "Unsupported width = %d range min(%u) - max(%u) step_size(%u)",
+ inst->prop.width, capability->width.min,
+ capability->width.max, capability->width.step_size);
+ rc = -ENOTSUPP;
+ }
+
+ if (inst->prop.height < capability->height.min ||
+ inst->prop.height > capability->height.max ||
+ (inst->prop.height %
+ capability->height.step_size != 0)) {
+ dprintk(VIDC_ERR,
+ "Unsupported height = %d range min(%u) - max(%u) step_size(%u)",
+ inst->prop.height, capability->height.min,
+ capability->height.max, capability->height.step_size);
+ rc = -ENOTSUPP;
+ }
+ }
+ if (rc) {
+ mutex_lock(&inst->sync_lock);
+ inst->state = MSM_VIDC_CORE_INVALID;
+ mutex_unlock(&inst->sync_lock);
+ dqevent.type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
+ dqevent.id = 0;
+ v4l2_event_queue_fh(&inst->event_handler, &dqevent);
+ wake_up(&inst->kernel_event_queue);
+ }
+ return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 4f3deb6..862dfab 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -21,8 +21,8 @@
struct msm_vidc_core *get_vidc_core(int core_id);
const struct msm_vidc_format *msm_comm_get_pixel_fmt_index(
const struct msm_vidc_format fmt[], int size, int index, int fmt_type);
-const struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
- const struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type);
+struct msm_vidc_format *msm_comm_get_pixel_fmt_fourcc(
+ struct msm_vidc_format fmt[], int size, int fourcc, int fmt_type);
struct buf_queue *msm_comm_get_vb2q(
struct msm_vidc_inst *inst, enum v4l2_buf_type type);
int msm_comm_try_state(struct msm_vidc_inst *inst, int state);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 62158b0..3208df9 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -18,7 +18,8 @@
int msm_vidc_debug = 0x3;
int msm_fw_debug = 0x18;
int msm_fw_debug_mode = 0x1;
-int msm_fw_low_power_mode = 0x0;
+int msm_fw_low_power_mode = 0x1;
+int msm_vp8_low_tier = 0x1;
struct debug_buffer {
char ptr[MAX_DBG_BUF_SIZE];
@@ -165,6 +166,11 @@
dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
goto failed_create_dir;
}
+ if (!debugfs_create_u32("vp8_low_tier", S_IRUGO | S_IWUSR,
+ parent, &msm_vp8_low_tier)) {
+ dprintk(VIDC_ERR, "debugfs_create_file: fail\n");
+ goto failed_create_dir;
+ }
failed_create_dir:
return dir;
}
@@ -204,8 +210,7 @@
"Output" : "Capture");
for (j = 0; j < inst->fmts[i]->num_planes; j++)
write_str(&dbg_buf, "size for plane %d: %u\n", j,
- inst->fmts[i]->get_frame_size(j,
- inst->prop.height, inst->prop.width));
+ inst->bufq[i].vb2_bufq.plane_sizes[j]);
}
write_str(&dbg_buf, "-------------------------------\n");
for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index fb06af6..ea6dd70 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -45,6 +45,7 @@
extern int msm_fw_debug;
extern int msm_fw_debug_mode;
extern int msm_fw_low_power_mode;
+extern int msm_vp8_low_tier;
#define dprintk(__level, __fmt, arg...) \
do { \
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 8238d42..1bfbaa6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -37,6 +37,14 @@
#define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1);
#define MAX_DEBUGFS_NAME 50
#define DEFAULT_TIMEOUT 3
+#define DEFAULT_HEIGHT 1080
+#define DEFAULT_WIDTH 1920
+#define MIN_SUPPORTED_WIDTH 32
+#define MIN_SUPPORTED_HEIGHT 32
+#define MAX_SUPPORTED_WIDTH 3820
+#define MAX_SUPPORTED_HEIGHT 2160
+
+
#define V4L2_EVENT_VIDC_BASE 10
@@ -166,6 +174,13 @@
VIDC_SECURE,
};
+struct msm_vidc_core_capability {
+ struct hal_capability_supported width;
+ struct hal_capability_supported height;
+ struct hal_capability_supported frame_rate;
+ u32 capability_set;
+};
+
struct msm_vidc_core {
struct list_head list;
struct mutex sync_lock, lock;
@@ -189,7 +204,7 @@
void *session;
struct session_prop prop;
int state;
- const struct msm_vidc_format *fmts[MAX_PORT_NUM];
+ struct msm_vidc_format *fmts[MAX_PORT_NUM];
struct buf_queue bufq[MAX_PORT_NUM];
struct list_head pendingq;
struct list_head internalbufs;
@@ -212,6 +227,7 @@
struct msm_vidc_debug debug;
struct buf_count count;
enum msm_vidc_mode mode;
+ struct msm_vidc_core_capability capability;
};
extern struct msm_vidc_drv *vidc_driver;
@@ -238,4 +254,5 @@
void handle_cmd_response(enum command_response cmd, void *data);
int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
enum hal_ssr_trigger_type type);
+int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
#endif
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index f0ca050..bf6c7db 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -12,6 +12,8 @@
*/
#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <mach/iommu_domains.h>
#include <mach/qdsp6v2/apr.h>
#include <mach/subsystem_restart.h>
#include "hfi_packetization.h"
@@ -19,6 +21,7 @@
#include "q6_hfi.h"
#include "vidc_hfi_api.h"
+static struct hal_device_data hal_ctxt;
static int write_queue(void *info, u8 *packet)
{
@@ -190,17 +193,86 @@
static int q6_hfi_register_iommu_domains(struct q6_hfi_device *device)
{
- (void)device;
+ struct iommu_domain *domain;
+ int rc = 0, i = 0;
+ struct iommu_set *iommu_group_set;
+ struct iommu_info *iommu_map;
- dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "Invalid parameter: %p", device);
+ return -EINVAL;
+ }
- return 0;
+ iommu_group_set = &device->res->iommu_group_set;
+
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ iommu_map->group = iommu_group_find(iommu_map->name);
+ if (!iommu_map->group) {
+ dprintk(VIDC_ERR, "Failed to find group :%s\n",
+ iommu_map->name);
+ goto fail_group;
+ }
+ domain = iommu_group_get_iommudata(iommu_map->group);
+ if (IS_ERR_OR_NULL(domain)) {
+ dprintk(VIDC_ERR,
+ "Failed to get domain data for group %p",
+ iommu_map->group);
+ goto fail_group;
+ }
+ iommu_map->domain = msm_find_domain_no(domain);
+ if (iommu_map->domain < 0) {
+ dprintk(VIDC_ERR,
+ "Failed to get domain index for domain %p",
+ domain);
+ goto fail_group;
+ }
+ }
+ return rc;
+
+fail_group:
+ for (--i; i >= 0; i--) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ if (iommu_map->group)
+ iommu_group_put(iommu_map->group);
+ iommu_map->group = NULL;
+ iommu_map->domain = -1;
+ }
+ return -EINVAL;
}
-static int q6_hfi_init_resources(struct q6_hfi_device *device)
+static void q6_hfi_deregister_iommu_domains(struct q6_hfi_device *device)
+{
+ struct iommu_set *iommu_group_set;
+ struct iommu_info *iommu_map;
+ int i = 0;
+
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "Invalid parameter: %p", device);
+ return;
+ }
+
+ iommu_group_set = &device->res->iommu_group_set;
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ if (iommu_map->group)
+ iommu_group_put(iommu_map->group);
+ iommu_map->group = NULL;
+ iommu_map->domain = -1;
+ }
+}
+
+static int q6_hfi_init_resources(struct q6_hfi_device *device,
+ struct msm_vidc_platform_resources *res)
{
int rc = 0;
+ if (!device || !res) {
+ dprintk(VIDC_ERR, "Invalid device or resources");
+ return -EINVAL;
+ }
+
+ device->res = res;
rc = q6_hfi_register_iommu_domains(device);
if (rc)
dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
@@ -208,12 +280,17 @@
return rc;
}
+static void q6_hfi_deinit_resources(struct q6_hfi_device *device)
+{
+ q6_hfi_deregister_iommu_domains(device);
+}
+
static void *q6_hfi_add_device(u32 device_id,
hfi_cmd_response_callback callback)
{
struct q6_hfi_device *hdevice = NULL;
- if (device_id || !callback) {
+ if (!callback) {
dprintk(VIDC_ERR, "Invalid Paramters");
return NULL;
}
@@ -225,19 +302,23 @@
goto err_alloc;
}
- INIT_LIST_HEAD(&hal_ctxt.dev_head);
- INIT_LIST_HEAD(&hdevice->list);
hdevice->device_id = device_id;
hdevice->callback = callback;
+ dprintk(VIDC_DBG, "q6_hfi_add_device device_id %d\n", device_id);
+
INIT_WORK(&hdevice->vidc_worker, q6_hfi_core_work_handler);
hdevice->vidc_workq = create_singlethread_workqueue(
- "msm_vidc_workerq");
+ "msm_vidc_workerq_q6");
if (!hdevice->vidc_workq) {
dprintk(VIDC_ERR, ": create workq failed\n");
goto error_createq;
}
+ if (hal_ctxt.dev_count == 0)
+ INIT_LIST_HEAD(&hal_ctxt.dev_head);
+
+ INIT_LIST_HEAD(&hdevice->list);
list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
hal_ctxt.dev_count++;
@@ -249,6 +330,7 @@
}
static void *q6_hfi_get_device(u32 device_id,
+ struct msm_vidc_platform_resources *res,
hfi_cmd_response_callback callback)
{
struct q6_hfi_device *device;
@@ -266,7 +348,7 @@
return NULL;
}
- rc = q6_hfi_init_resources(device);
+ rc = q6_hfi_init_resources(device, res);
if (rc) {
dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
goto err_fail_init_res;
@@ -283,12 +365,15 @@
struct q6_hfi_device *close, *dev;
if (device) {
+ q6_hfi_deinit_resources(device);
dev = (struct q6_hfi_device *) device;
list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+ if (close->device_id == dev->device_id) {
hal_ctxt.dev_count--;
list_del(&close->list);
destroy_workqueue(close->vidc_workq);
kfree(close);
+ }
}
}
@@ -1115,13 +1200,74 @@
return -ENOTSUPP;
}
-static int q6_hfi_iommu_attach(void *dev)
+static int q6_hfi_iommu_attach(struct q6_hfi_device *device)
{
- (void)dev;
+ int rc = 0;
+ struct iommu_domain *domain;
+ int i;
+ struct iommu_set *iommu_group_set;
+ struct iommu_group *group;
+ struct iommu_info *iommu_map;
- dprintk(VIDC_ERR, "Not implemented: %s", __func__);
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "Invalid parameter: %p", device);
+ return -EINVAL;
+ }
- return 0;
+ iommu_group_set = &device->res->iommu_group_set;
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (IS_ERR_OR_NULL(domain)) {
+ dprintk(VIDC_ERR, "Failed to get domain: %s",
+ iommu_map->name);
+ rc = IS_ERR(domain) ? PTR_ERR(domain) : -EINVAL;
+ break;
+ }
+ dprintk(VIDC_DBG, "Attaching domain(id:%d) %p to group %p",
+ iommu_map->domain, domain, group);
+ rc = iommu_attach_group(domain, group);
+ if (rc) {
+ dprintk(VIDC_ERR, "IOMMU attach failed: %s",
+ iommu_map->name);
+ break;
+ }
+ }
+ if (i < iommu_group_set->count) {
+ i--;
+ for (; i >= 0; i--) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (group && domain)
+ iommu_detach_group(domain, group);
+ }
+ }
+ return rc;
+}
+
+static void q6_hfi_iommu_detach(struct q6_hfi_device *device)
+{
+ struct iommu_group *group;
+ struct iommu_domain *domain;
+ struct iommu_set *iommu_group_set;
+ struct iommu_info *iommu_map;
+ int i;
+
+ if (!device || !device->res) {
+ dprintk(VIDC_ERR, "Invalid parameter: %p", device);
+ return;
+ }
+
+ iommu_group_set = &device->res->iommu_group_set;
+ for (i = 0; i < iommu_group_set->count; i++) {
+ iommu_map = &iommu_group_set->iommu_maps[i];
+ group = iommu_map->group;
+ domain = msm_get_iommu_domain(iommu_map->domain);
+ if (group && domain)
+ iommu_detach_group(domain, group);
+ }
}
static int q6_hfi_load_fw(void *dev)
@@ -1132,6 +1278,15 @@
if (!device)
return -EINVAL;
+ if (!device->resources.fw.cookie)
+ device->resources.fw.cookie = subsystem_get("adsp");
+
+ if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
+ dprintk(VIDC_ERR, "Failed to download firmware\n");
+ rc = -ENOMEM;
+ goto fail_subsystem_get;
+ }
+
/*Set Q6 to loaded state*/
apr_set_q6_state(APR_SUBSYS_LOADED);
@@ -1156,9 +1311,11 @@
fail_iommu_attach:
apr_deregister(device->apr);
+ device->apr = NULL;
fail_apr_register:
subsystem_put(device->resources.fw.cookie);
device->resources.fw.cookie = NULL;
+fail_subsystem_get:
return rc;
}
@@ -1168,8 +1325,18 @@
if (!device)
return;
- if (device->apr)
- apr_deregister(device->apr);
+
+ if (device->resources.fw.cookie) {
+ q6_hfi_iommu_detach(device);
+ subsystem_put(device->resources.fw.cookie);
+ device->resources.fw.cookie = NULL;
+ }
+
+ if (device->apr) {
+ if (apr_deregister(device->apr))
+ dprintk(VIDC_ERR, "Failed to deregister APR");
+ device->apr = NULL;
+ }
}
static int q6_hfi_get_fw_info(void *dev, enum fw_info info)
@@ -1226,16 +1393,18 @@
int q6_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+ struct msm_vidc_platform_resources *res,
hfi_cmd_response_callback callback)
{
int rc = 0;
- if (!hdev || !callback) {
- dprintk(VIDC_ERR, "Invalid params: %p %p\n", hdev, callback);
+ if (!hdev || !res || !callback) {
+ dprintk(VIDC_ERR, "Invalid params: %p %p %p",
+ hdev, res, callback);
rc = -EINVAL;
goto err_hfi_init;
}
- hdev->hfi_device_data = q6_hfi_get_device(device_id, callback);
+ hdev->hfi_device_data = q6_hfi_get_device(device_id, res, callback);
q6_init_hfi_callbacks(hdev);
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.h b/drivers/media/platform/msm/vidc/q6_hfi.h
index 551eb04..3dc4607 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.h
+++ b/drivers/media/platform/msm/vidc/q6_hfi.h
@@ -13,9 +13,10 @@
#ifndef __Q6_HFI_H__
#define __Q6_HFI_H__
+#include <mach/qdsp6v2/apr.h>
#include "vidc_hfi.h"
#include "vidc_hfi_helper.h"
-#include <mach/qdsp6v2/apr.h>
+#include "msm_vidc_resources.h"
#define Q6_IFACEQ_QUEUE_SIZE (8 * 1024)
@@ -40,6 +41,7 @@
u32 device_id;
msm_vidc_callback callback;
struct q6_resources resources;
+ struct msm_vidc_platform_resources *res;
void *apr;
};
@@ -109,6 +111,7 @@
};
int q6_hfi_initialize(struct hfi_device *hdev, u32 device_id,
+ struct msm_vidc_platform_resources *res,
hfi_cmd_response_callback callback);
void q6_hfi_delete_device(void *device);
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 232ad90..b5dd15d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -37,6 +37,8 @@
#define SHARED_QSIZE 0x1000000
+static struct hal_device_data hal_ctxt;
+
static const u32 venus_qdss_entries[][2] = {
{0xFC307000, 0x1000},
{0xFC322000, 0x1000},
@@ -2604,7 +2606,7 @@
}
}
- rc = scm_call(SCM_SVC_CP, TZBSP_MEM_PROTECT_VIDEO_VAR, &memprot,
+ rc = scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_VIDEO_VAR, &memprot,
sizeof(memprot), &resp, sizeof(resp));
if (rc)
dprintk(VIDC_ERR,
@@ -2746,25 +2748,25 @@
if (rc)
goto err_init_regs;
- INIT_LIST_HEAD(&hal_ctxt.dev_head);
- INIT_LIST_HEAD(&hdevice->list);
- list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
- hal_ctxt.dev_count++;
hdevice->device_id = device_id;
-
hdevice->callback = callback;
hdevice->vidc_workq = create_singlethread_workqueue(
- "msm_vidc_workerq");
+ "msm_vidc_workerq_venus");
if (!hdevice->vidc_workq) {
dprintk(VIDC_ERR, ": create workq failed\n");
goto error_createq;
}
+ if (hal_ctxt.dev_count == 0)
+ INIT_LIST_HEAD(&hal_ctxt.dev_head);
+
+ INIT_LIST_HEAD(&hdevice->list);
+ list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
+ hal_ctxt.dev_count++;
+
return (void *) hdevice;
error_createq:
- hal_ctxt.dev_count--;
- list_del(&hal_ctxt.dev_head);
err_init_regs:
kfree(hdevice);
err_alloc:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c
index e8131dd..46293a6 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.c
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.c
@@ -16,8 +16,6 @@
#include "venus_hfi.h"
#include "q6_hfi.h"
-struct hal_device_data hal_ctxt;
-
void *vidc_hfi_initialize(enum msm_vidc_hfi_type hfi_type, u32 device_id,
struct msm_vidc_platform_resources *res,
hfi_cmd_response_callback callback)
@@ -37,7 +35,7 @@
break;
case VIDC_HFI_Q6:
- rc = q6_hfi_initialize(hdev, device_id, callback);
+ rc = q6_hfi_initialize(hdev, device_id, res, callback);
break;
default:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 8b3e7cb..075b391 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -830,8 +830,6 @@
void *cookie;
};
-extern struct hal_device_data hal_ctxt;
-
u32 hfi_process_msg_packet(msm_vidc_callback callback,
u32 device_id, struct vidc_hal_msg_pkt_hdr *msg_hdr);
#endif
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 5ad0bb5..e20348d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -165,6 +165,7 @@
HAL_PARAM_VENC_LOW_LATENCY,
HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER,
HAL_PARAM_VDEC_SYNC_FRAME_DECODE,
+ HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
};
enum hal_domain {
@@ -189,6 +190,7 @@
HAL_VIDEO_CODEC_VP6 = 0x00000400,
HAL_VIDEO_CODEC_VP7 = 0x00000800,
HAL_VIDEO_CODEC_VP8 = 0x00001000,
+ HAL_VIDEO_CODEC_HEVC = 0x00010000,
HAL_UNUSED_CODEC = 0x10000000,
};
@@ -533,15 +535,15 @@
};
*/
enum hal_h264_entropy {
- HAL_H264_ENTROPY_CAVLC,
- HAL_H264_ENTROPY_CABAC,
+ HAL_H264_ENTROPY_CAVLC = 1,
+ HAL_H264_ENTROPY_CABAC = 2,
HAL_UNUSED_ENTROPY = 0x10000000,
};
enum hal_h264_cabac_model {
- HAL_H264_CABAC_MODEL_0,
- HAL_H264_CABAC_MODEL_1,
- HAL_H264_CABAC_MODEL_2,
+ HAL_H264_CABAC_MODEL_0 = 1,
+ HAL_H264_CABAC_MODEL_1 = 2,
+ HAL_H264_CABAC_MODEL_2 = 4,
HAL_UNUSED_CABAC = 0x10000000,
};
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 01c5e0b..baf7bc4 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -76,9 +76,10 @@
#define HFI_VIDEO_CODEC_MPEG4 0x00000020
#define HFI_VIDEO_CODEC_DIVX_311 0x00000040
#define HFI_VIDEO_CODEC_DIVX 0x00000080
-#define HFI_VIDEO_CODEC_VC1 0x00000100
+#define HFI_VIDEO_CODEC_VC1 0x00000100
#define HFI_VIDEO_CODEC_SPARK 0x00000200
-#define HFI_VIDEO_CODEC_VP8 0x00001000
+#define HFI_VIDEO_CODEC_VP8 0x00001000
+#define HFI_VIDEO_CODEC_HEVC 0x00010000
#define HFI_H264_PROFILE_BASELINE 0x00000001
#define HFI_H264_PROFILE_MAIN 0x00000002
diff --git a/drivers/media/platform/msm/wfd/enc-subdev.h b/drivers/media/platform/msm/wfd/enc-subdev.h
index 8bfb884..a1469cd 100644
--- a/drivers/media/platform/msm/wfd/enc-subdev.h
+++ b/drivers/media/platform/msm/wfd/enc-subdev.h
@@ -25,6 +25,10 @@
VENC_MODE_VFR,
};
+enum venc_event {
+ VENC_EVENT_HARDWARE_ERROR,
+};
+
struct mem_region {
struct list_head list;
u8 *kvaddr;
@@ -64,6 +68,7 @@
struct vb2_buffer *buf);
void (*ip_buffer_done)(void *cookie, u32 status,
struct mem_region *mregion);
+ void (*on_event)(void *cookie, enum venc_event e);
};
static inline bool mem_region_equals(struct mem_region *a,
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 40362f0..9ebf763 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -48,6 +48,12 @@
bool secure;
};
+static const int subscribed_events[] = {
+ V4L2_EVENT_MSM_VIDC_CLOSE_DONE,
+ V4L2_EVENT_MSM_VIDC_FLUSH_DONE,
+ V4L2_EVENT_MSM_VIDC_SYS_ERROR,
+};
+
int venc_load_fw(struct v4l2_subdev *sd)
{
/*No need to explicitly load the fw */
@@ -134,13 +140,21 @@
bool bail_out = false;
msm_vidc_dqevent(inst->vidc_context, &event);
- if (event.type == V4L2_EVENT_MSM_VIDC_CLOSE_DONE) {
+
+ switch (event.type) {
+ case V4L2_EVENT_MSM_VIDC_CLOSE_DONE:
WFD_MSG_DBG("enc callback thread shutting " \
"down normally\n");
bail_out = true;
- } else {
- WFD_MSG_ERR("Got unknown event %d, ignoring\n",
- event.id);
+ break;
+ case V4L2_EVENT_MSM_VIDC_SYS_ERROR:
+ inst->vmops.on_event(inst->vmops.cbdata,
+ VENC_EVENT_HARDWARE_ERROR);
+ bail_out = true;
+ break;
+ default:
+ WFD_MSG_INFO("Got unknown event %d, ignoring\n",
+ event.type);
}
complete_all(&inst->cmd_complete);
@@ -251,11 +265,43 @@
return msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
}
+static int subscribe_events(struct venc_inst *inst)
+{
+ struct v4l2_event_subscription event = {0};
+ int c = 0, rc = 0;
+
+ for (c = 0; c < ARRAY_SIZE(subscribed_events); c++) {
+ event.type = subscribed_events[c];
+ rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
+ if (rc) {
+ WFD_MSG_ERR("Failed to subscribe to event 0x%x\n",
+ subscribed_events[c]);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static void unsubscribe_events(struct venc_inst *inst)
+{
+ struct v4l2_event_subscription event = {0};
+ int c = 0, rc = 0;
+ for (c = 0; c < ARRAY_SIZE(subscribed_events); c++) {
+ event.type = subscribed_events[c];
+ rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
+ if (rc) {
+ /* Just log and ignore failiures */
+ WFD_MSG_WARN("Failed to unsubscribe to event 0x%x\n",
+ subscribed_events[c]);
+ }
+ }
+}
+
static long venc_open(struct v4l2_subdev *sd, void *arg)
{
struct venc_inst *inst = NULL;
struct venc_msg_ops *vmops = arg;
- struct v4l2_event_subscription event = {0};
int rc = 0;
if (!vmops) {
@@ -289,17 +335,9 @@
goto vidc_open_fail;
}
- event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
- rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
+ rc = subscribe_events(inst);
if (rc) {
- WFD_MSG_ERR("Failed to subscribe to CLOSE_DONE event\n");
- goto vidc_subscribe_fail;
- }
-
- event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
- rc = msm_vidc_subscribe_event(inst->vidc_context, &event);
- if (rc) {
- WFD_MSG_ERR("Failed to subscribe to FLUSH_DONE event\n");
+ WFD_MSG_ERR("Failed to subscribe to events\n");
goto vidc_subscribe_fail;
}
@@ -317,11 +355,7 @@
vmops->cookie = inst;
return 0;
vidc_kthread_create_fail:
- event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
- msm_vidc_unsubscribe_event(inst->vidc_context, &event);
-
- event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
- msm_vidc_unsubscribe_event(inst->vidc_context, &event);
+ unsubscribe_events(inst);
vidc_subscribe_fail:
msm_vidc_close(inst->vidc_context);
vidc_open_fail:
@@ -333,7 +367,6 @@
static long venc_close(struct v4l2_subdev *sd, void *arg)
{
struct venc_inst *inst = NULL;
- struct v4l2_event_subscription event = {0};
struct v4l2_encoder_cmd enc_cmd = {0};
int rc = 0;
@@ -352,15 +385,7 @@
if (inst->callback_thread && inst->callback_thread_running)
kthread_stop(inst->callback_thread);
- event.type = V4L2_EVENT_MSM_VIDC_CLOSE_DONE;
- rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
- if (rc)
- WFD_MSG_WARN("Failed to unsubscribe close event\n");
-
- event.type = V4L2_EVENT_MSM_VIDC_FLUSH_DONE;
- rc = msm_vidc_unsubscribe_event(inst->vidc_context, &event);
- if (rc)
- WFD_MSG_WARN("Failed to unsubscribe flush event\n");
+ unsubscribe_events(inst);
rc = msm_vidc_close(inst->vidc_context);
if (rc)
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 9fb7c6d..72b02bb 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -18,15 +18,16 @@
#include <linux/init.h>
#include <linux/version.h>
#include <linux/platform_device.h>
-#include <linux/android_pmem.h>
+
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/time.h>
#include <mach/board.h>
#include <media/v4l2-dev.h>
-#include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
#include <media/v4l2-subdev.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-msm-mem.h>
@@ -42,6 +43,7 @@
#define DEFAULT_WFD_WIDTH 1280
#define DEFAULT_WFD_HEIGHT 720
#define VENC_INPUT_BUFFERS 4
+#define MAX_EVENTS 16
struct wfd_device {
struct mutex dev_lock;
@@ -92,12 +94,18 @@
struct list_head input_mem_list;
struct wfd_stats stats;
struct completion stop_mdp_thread;
+ struct v4l2_fh event_handler;
};
struct wfd_vid_buffer {
struct vb2_buffer vidbuf;
};
+static inline struct wfd_inst *file_to_inst(struct file *filp)
+{
+ return container_of(filp->private_data, struct wfd_inst, event_handler);
+}
+
static int wfd_vidbuf_queue_setup(struct vb2_queue *q,
const struct v4l2_format *fmt,
unsigned int *num_buffers,
@@ -105,7 +113,7 @@
unsigned int sizes[], void *alloc_ctxs[])
{
struct file *priv_data = (struct file *)(q->drv_priv);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
unsigned long flags;
int i;
@@ -124,10 +132,11 @@
return 0;
}
-void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
+static void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
{
}
-void wfd_vidbuf_wait_finish(struct vb2_queue *q)
+
+static void wfd_vidbuf_wait_finish(struct vb2_queue *q)
{
}
@@ -236,7 +245,8 @@
ION_IOC_INV_CACHES);
}
-int wfd_allocate_input_buffers(struct wfd_device *wfd_dev,
+
+static int wfd_allocate_input_buffers(struct wfd_device *wfd_dev,
struct wfd_inst *inst)
{
int i;
@@ -271,11 +281,15 @@
mmap_context.ion_client = wfd_dev->ion_client;
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENC_MMAP, &mmap_context);
- if (rc || !enc_mregion->paddr) {
+ if (rc) {
WFD_MSG_ERR("Failed to map input memory\n");
goto alloc_fail;
+ } else if (!enc_mregion->paddr) {
+ WFD_MSG_ERR("ENC_MMAP returned success" \
+ "but failed to map input memory\n");
+ rc = -EINVAL;
+ goto alloc_fail;
}
-
WFD_MSG_DBG("NOTE: enc paddr = [%p->%p], kvaddr = %p\n",
enc_mregion->paddr, (int8_t *)
enc_mregion->paddr + enc_mregion->size,
@@ -303,7 +317,7 @@
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
MDP_MMAP, (void *)&mmap_context);
- if (rc || !mdp_mregion->paddr) {
+ if (rc) {
WFD_MSG_ERR(
"Failed to map to mdp, rc = %d, paddr = 0x%p\n",
rc, mdp_mregion->paddr);
@@ -311,6 +325,14 @@
mdp_mregion->paddr = NULL;
mdp_mregion->ion_handle = NULL;
goto mdp_mmap_fail;
+ } else if (!mdp_mregion->paddr) {
+ WFD_MSG_ERR("MDP_MMAP returned success" \
+ "but failed to map to MDP\n");
+ rc = -EINVAL;
+ mdp_mregion->kvaddr = NULL;
+ mdp_mregion->paddr = NULL;
+ mdp_mregion->ion_handle = NULL;
+ goto mdp_mmap_fail;
}
mdp_buf.inst = inst->mdp_inst;
@@ -377,7 +399,8 @@
recon_alloc_fail:
return rc;
}
-void wfd_free_input_buffers(struct wfd_device *wfd_dev,
+
+static void wfd_free_input_buffers(struct wfd_device *wfd_dev,
struct wfd_inst *inst)
{
struct list_head *ptr, *next;
@@ -438,7 +461,7 @@
WFD_MSG_ERR("Failed to free recon buffers\n");
}
-struct mem_info *wfd_get_mem_info(struct wfd_inst *inst,
+static struct mem_info *wfd_get_mem_info(struct wfd_inst *inst,
unsigned long userptr)
{
struct mem_info_entry *temp;
@@ -456,7 +479,8 @@
spin_unlock_irqrestore(&inst->inst_lock, flags);
return ret;
}
-void wfd_put_mem_info(struct wfd_inst *inst,
+
+static void wfd_put_mem_info(struct wfd_inst *inst,
struct mem_info *minfo)
{
struct list_head *ptr, *next;
@@ -485,12 +509,13 @@
}
wfd_put_mem_info(inst, minfo);
}
-int wfd_vidbuf_buf_init(struct vb2_buffer *vb)
+
+static int wfd_vidbuf_buf_init(struct vb2_buffer *vb)
{
int rc = 0;
struct vb2_queue *q = vb->vb2_queue;
struct file *priv_data = (struct file *)(q->drv_priv);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(priv_data);
struct mem_info *minfo = vb2_plane_cookie(vb, 0);
@@ -520,24 +545,24 @@
return rc;
}
-int wfd_vidbuf_buf_prepare(struct vb2_buffer *vb)
+static int wfd_vidbuf_buf_prepare(struct vb2_buffer *vb)
{
return 0;
}
-int wfd_vidbuf_buf_finish(struct vb2_buffer *vb)
+static int wfd_vidbuf_buf_finish(struct vb2_buffer *vb)
{
return 0;
}
-void wfd_vidbuf_buf_cleanup(struct vb2_buffer *vb)
+static void wfd_vidbuf_buf_cleanup(struct vb2_buffer *vb)
{
int rc = 0;
struct vb2_queue *q = vb->vb2_queue;
struct file *priv_data = (struct file *)(q->drv_priv);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(priv_data);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
struct mem_info *minfo = vb2_plane_cookie(vb, 0);
struct mem_region mregion;
@@ -562,7 +587,7 @@
{
int rc = 0, no_sig_wait = 0;
struct file *filp = (struct file *)data;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
struct mdp_buf_info obuf_mdp = {inst->mdp_inst, 0, 0, 0};
@@ -621,12 +646,12 @@
return rc;
}
-int wfd_vidbuf_start_streaming(struct vb2_queue *q, unsigned int count)
+static int wfd_vidbuf_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct file *priv_data = (struct file *)(q->drv_priv);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(priv_data);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
int rc = 0;
WFD_MSG_ERR("Stream on called\n");
@@ -645,6 +670,7 @@
WFD_MSG_ERR("Failed to start vsg\n");
goto subdev_start_fail;
}
+
init_completion(&inst->stop_mdp_thread);
inst->mdp_task = kthread_run(mdp_output_thread, priv_data,
"mdp_output_thread");
@@ -661,12 +687,12 @@
return rc;
}
-int wfd_vidbuf_stop_streaming(struct vb2_queue *q)
+static int wfd_vidbuf_stop_streaming(struct vb2_queue *q)
{
struct file *priv_data = (struct file *)(q->drv_priv);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(priv_data);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
int rc = 0;
WFD_MSG_DBG("mdp stop\n");
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
@@ -695,14 +721,14 @@
return rc;
}
-void wfd_vidbuf_buf_queue(struct vb2_buffer *vb)
+static void wfd_vidbuf_buf_queue(struct vb2_buffer *vb)
{
int rc = 0;
struct vb2_queue *q = vb->vb2_queue;
struct file *priv_data = (struct file *)(q->drv_priv);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(priv_data);
- struct wfd_inst *inst = (struct wfd_inst *)priv_data->private_data;
+ struct wfd_inst *inst = file_to_inst(priv_data);
struct mem_region mregion;
struct mem_info *minfo = vb2_plane_cookie(vb, 0);
mregion.fd = minfo->fd;
@@ -775,7 +801,7 @@
static int wfdioc_g_fmt(struct file *filp, void *fh,
struct v4l2_format *fmt)
{
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
unsigned long flags;
if (!fmt) {
WFD_MSG_ERR("Invalid argument\n");
@@ -799,7 +825,7 @@
struct v4l2_format *fmt)
{
int rc = 0;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct wfd_device *wfd_dev = video_drvdata(filp);
struct mdp_prop prop;
unsigned long flags;
@@ -850,7 +876,7 @@
static int wfdioc_reqbufs(struct file *filp, void *fh,
struct v4l2_requestbuffers *b)
{
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct wfd_device *wfd_dev = video_drvdata(filp);
unsigned long flags;
int rc = 0;
@@ -906,7 +932,7 @@
struct v4l2_buffer *b)
{
int rc = 0;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
if (!inst || !b ||
(b->index < 0 || b->index >= inst->buf_count)) {
WFD_MSG_ERR("Invalid input parameters to QBUF IOCTL\n");
@@ -931,7 +957,7 @@
enum v4l2_buf_type i)
{
int rc = 0;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
unsigned long flags;
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
WFD_MSG_ERR("stream on for buffer type = %d is not "
@@ -957,7 +983,7 @@
static int wfdioc_streamoff(struct file *filp, void *fh,
enum v4l2_buf_type i)
{
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
unsigned long flags;
if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
@@ -981,7 +1007,7 @@
static int wfdioc_dqbuf(struct file *filp, void *fh,
struct v4l2_buffer *b)
{
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
int rc;
WFD_MSG_DBG("Waiting to dequeue buffer\n");
@@ -1045,7 +1071,7 @@
{
int rc = 0;
struct wfd_device *wfd_dev = video_drvdata(filp);
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
int64_t frame_interval = 0,
max_frame_interval = 0; /* both in nsecs*/
struct v4l2_qcom_frameskip frameskip, *usr_frameskip;
@@ -1100,7 +1126,7 @@
{
int rc = 0;
struct wfd_device *wfd_dev = video_drvdata(filp);
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct v4l2_qcom_frameskip frameskip;
int64_t frame_interval, max_frame_interval;
void *extendedmode = NULL;
@@ -1188,6 +1214,22 @@
return rc;
}
+static int wfdioc_subscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ struct wfd_inst *inst = container_of(fh, struct wfd_inst,
+ event_handler);
+ return v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS);
+}
+
+static int wfdioc_unsubscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ struct wfd_inst *inst = container_of(fh, struct wfd_inst,
+ event_handler);
+ return v4l2_event_unsubscribe(&inst->event_handler, sub);
+}
+
static const struct v4l2_ioctl_ops g_wfd_ioctl_ops = {
.vidioc_querycap = wfdioc_querycap,
.vidioc_s_fmt_vid_cap = wfdioc_s_fmt,
@@ -1201,13 +1243,16 @@
.vidioc_s_ctrl = wfdioc_s_ctrl,
.vidioc_g_parm = wfdioc_g_parm,
.vidioc_s_parm = wfdioc_s_parm,
+ .vidioc_subscribe_event = wfdioc_subscribe_event,
+ .vidioc_unsubscribe_event = wfdioc_unsubscribe_event,
+
};
static int wfd_set_default_properties(struct file *filp)
{
unsigned long flags;
struct v4l2_format fmt;
struct v4l2_control ctrl;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
if (!inst) {
WFD_MSG_ERR("Invalid argument\n");
return -EINVAL;
@@ -1237,7 +1282,7 @@
struct mem_region *mregion)
{
struct file *filp = cookie;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct vsg_buf_info buf;
struct mdp_buf_info mdp_buf = {0};
struct wfd_device *wfd_dev =
@@ -1261,10 +1306,33 @@
}
+static void venc_on_event(void *cookie, enum venc_event e)
+{
+ struct file *filp = cookie;
+ struct wfd_inst *inst = file_to_inst(filp);
+ struct v4l2_event event;
+ int type = 0;
+
+ switch (e) {
+ case VENC_EVENT_HARDWARE_ERROR:
+ type = V4L2_EVENT_MSM_VIDC_SYS_ERROR;
+ break;
+ default:
+ /* Whatever~~ */
+ break;
+ }
+
+ if (type) {
+ event.id = 0;
+ event.type = type;
+ v4l2_event_queue_fh(&inst->event_handler, &event);
+ }
+}
+
static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
{
struct file *filp = cookie;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
int rc = 0;
@@ -1284,7 +1352,7 @@
static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
{
struct file *filp = cookie;
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
struct venc_buf_info venc_buf;
@@ -1377,11 +1445,15 @@
rc = -ENOMEM;
goto err_mdp_open;
}
- filp->private_data = inst;
+ filp->private_data = &inst->event_handler;
spin_lock_init(&inst->inst_lock);
INIT_LIST_HEAD(&inst->input_mem_list);
INIT_LIST_HEAD(&inst->minfo_list);
+ /* Set up userspace event handlers */
+ v4l2_fh_init(&inst->event_handler, wfd_dev->pvdev);
+ v4l2_fh_add(&inst->event_handler);
+
wfd_stats_init(&inst->stats, MINOR(filp->f_dentry->d_inode->i_rdev));
mdp_mops.secure = wfd_dev->secure;
@@ -1399,8 +1471,10 @@
WFD_MSG_ERR("Failed to load video encoder firmware: %d\n", rc);
goto err_venc;
}
+
enc_mops.op_buffer_done = venc_op_buffer_done;
enc_mops.ip_buffer_done = venc_ip_buffer_done;
+ enc_mops.on_event = venc_on_event;
enc_mops.cbdata = filp;
enc_mops.secure = wfd_dev->secure;
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl, OPEN,
@@ -1432,9 +1506,12 @@
v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl,
MDP_CLOSE, (void *)inst->mdp_inst);
err_mdp_open:
+ v4l2_fh_del(&inst->event_handler);
+
mutex_lock(&wfd_dev->dev_lock);
wfd_dev->in_use = false;
mutex_unlock(&wfd_dev->dev_lock);
+
kfree(inst);
err_dev_busy:
return rc;
@@ -1447,7 +1524,7 @@
int rc = 0;
wfd_dev = video_drvdata(filp);
WFD_MSG_DBG("wfd_close: E\n");
- inst = filp->private_data;
+ inst = file_to_inst(filp);
if (inst) {
wfdioc_streamoff(filp, NULL, V4L2_BUF_TYPE_VIDEO_CAPTURE);
vb2_queue_release(&inst->vid_bufq);
@@ -1472,6 +1549,8 @@
kfree(inst);
}
+ v4l2_fh_del(&inst->event_handler);
+
mutex_lock(&wfd_dev->dev_lock);
wfd_dev->in_use = false;
mutex_unlock(&wfd_dev->dev_lock);
@@ -1479,12 +1558,28 @@
WFD_MSG_DBG("wfd_close: X\n");
return 0;
}
+
+unsigned int wfd_poll(struct file *filp, struct poll_table_struct *pt)
+{
+ struct wfd_inst *inst = file_to_inst(filp);
+ unsigned int flags = 0;
+
+ poll_wait(filp, &inst->event_handler.wait, pt);
+
+ if (v4l2_event_pending(&inst->event_handler))
+ flags |= POLLPRI;
+
+ return flags;
+}
+
static const struct v4l2_file_operations g_wfd_fops = {
.owner = THIS_MODULE,
.open = wfd_open,
.release = wfd_close,
- .ioctl = video_ioctl2
+ .ioctl = video_ioctl2,
+ .poll = wfd_poll,
};
+
void release_video_device(struct video_device *pvdev)
{
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index cfa5487..2573a16 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -523,7 +523,7 @@
TI wl127x chips.
config TSIF
- depends on ARCH_MSM
+ depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064
tristate "TSIF (Transport Stream InterFace) support"
default n
---help---
@@ -639,6 +639,15 @@
to the fuse block. Currently this is supported only
on FSM targets.
+config QPNP_MISC
+ tristate "QPNP Misc Peripheral"
+ depends on SPMI
+ help
+ Say 'y' here to include support for the Qualcomm QPNP MISC
+ peripheral. The MISC peripheral holds the USB ID interrupt
+ and the driver provides an API to check if this interrupt
+ is available on the current PMIC chip.
+
config USB_HSIC_SMSC_HUB
tristate "Support for HSIC based MSM on-chip SMSC3503 HUB"
depends on USB_EHCI_MSM_HSIC
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index f80f3f2..327d1ec 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -70,3 +70,4 @@
obj-$(CONFIG_QSEECOM) += qseecom.o
obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
obj-$(CONFIG_TI_DRV2667) += ti_drv2667.o
+obj-$(CONFIG_QPNP_MISC) += qpnp-misc.o
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
new file mode 100644
index 0000000..608be81
--- /dev/null
+++ b/drivers/misc/qpnp-misc.c
@@ -0,0 +1,167 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/qpnp-misc.h>
+
+#define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
+
+#define REVID_REVISION2 0x1
+
+static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
+static LIST_HEAD(qpnp_misc_dev_list);
+
+/**
+ * struct qpnp_misc_dev - holds controller device specific information
+ * @list: Doubly-linked list parameter linking to other
+ * qpnp_misc devices.
+ * @mutex: Mutex lock that is used to ensure mutual
+ * exclusion between probing and accessing misc
+ * driver information
+ * @dev: Device pointer to the misc device
+ * @resource: Resource pointer that holds base address
+ * @spmi: Spmi pointer which holds spmi information
+ */
+struct qpnp_misc_dev {
+ struct list_head list;
+ struct mutex mutex;
+ struct device *dev;
+ struct resource *resource;
+ struct spmi_device *spmi;
+};
+
+static struct of_device_id qpnp_misc_match_table[] = {
+ { .compatible = QPNP_MISC_DEV_NAME },
+ {}
+};
+
+static u8 qpnp_read_byte(struct spmi_device *spmi, u16 addr)
+{
+ int rc;
+ u8 val;
+
+ rc = spmi_ext_register_readl(spmi->ctrl, spmi->sid, addr, &val, 1);
+ if (rc) {
+ pr_err("SPMI read failed rc=%d\n", rc);
+ return 0;
+ }
+ return val;
+}
+
+#define REV2_IRQ_AVAILABLE_VERSION 2
+static bool __misc_irqs_available(struct qpnp_misc_dev *dev)
+{
+ u8 rev2;
+
+ rev2 = qpnp_read_byte(dev->spmi,
+ dev->resource->start + REVID_REVISION2);
+ pr_debug("rev2 0x%x\n", rev2);
+
+ if (rev2 >= REV2_IRQ_AVAILABLE_VERSION)
+ return 1;
+
+ return 0;
+}
+
+int qpnp_misc_irqs_available(struct device *consumer_dev)
+{
+ struct device_node *misc_node = NULL;
+ struct qpnp_misc_dev *mdev = NULL;
+ struct qpnp_misc_dev *mdev_found = NULL;
+
+ misc_node = of_parse_phandle(consumer_dev->of_node, "qcom,misc-ref", 0);
+ if (!misc_node) {
+ pr_debug("Could not find qcom,misc-ref property in %s\n",
+ consumer_dev->of_node->full_name);
+ return 0;
+ }
+
+ mutex_lock(&qpnp_misc_dev_list_mutex);
+ list_for_each_entry(mdev, &qpnp_misc_dev_list, list) {
+ if (mdev->dev->of_node == misc_node) {
+ mdev_found = mdev;
+ break;
+ }
+ }
+ mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+ if (!mdev_found) {
+ /* No MISC device was found. This API should only
+ * be called by drivers which have specified the
+ * misc phandle in their device tree node */
+ pr_err("no probed misc device found\n");
+ return -EPROBE_DEFER;
+ }
+
+ return __misc_irqs_available(mdev_found);
+}
+
+static int __devinit qpnp_misc_probe(struct spmi_device *spmi)
+{
+ struct resource *resource;
+ struct qpnp_misc_dev *mdev = ERR_PTR(-EINVAL);
+
+ resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!resource) {
+ pr_err("Unable to get spmi resource for MISC\n");
+ return -EINVAL;
+ }
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev) {
+ pr_err("allocation failed\n");
+ return -ENOMEM;
+ }
+
+ mdev->spmi = spmi;
+ mdev->dev = &(spmi->dev);
+ mdev->resource = resource;
+
+ mutex_lock(&qpnp_misc_dev_list_mutex);
+ list_add_tail(&mdev->list, &qpnp_misc_dev_list);
+ mutex_unlock(&qpnp_misc_dev_list_mutex);
+
+ pr_debug("probed successfully\n");
+ return 0;
+}
+
+static struct spmi_driver qpnp_misc_driver = {
+ .probe = qpnp_misc_probe,
+ .driver = {
+ .name = QPNP_MISC_DEV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = qpnp_misc_match_table,
+ },
+};
+
+static int __init qpnp_misc_init(void)
+{
+ return spmi_driver_register(&qpnp_misc_driver);
+}
+
+static void __exit qpnp_misc_exit(void)
+{
+ return spmi_driver_unregister(&qpnp_misc_driver);
+}
+
+module_init(qpnp_misc_init);
+module_exit(qpnp_misc_exit);
+
+MODULE_DESCRIPTION(QPNP_MISC_DEV_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" QPNP_MISC_DEV_NAME);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9e22ffb..7d76b43 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -57,7 +57,6 @@
#define QSEOS_CHECK_VERSION_CMD 0x00001803
#define QSEE_CE_CLK_100MHZ 100000000
-#define QSEE_CE_CLK_50MHZ 50000000
#define QSEECOM_MAX_SG_ENTRY 512
@@ -78,10 +77,6 @@
static DEFINE_MUTEX(qsee_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
-static int qsee_bw_count;
-static int qsee_sfpb_bw_count;
-static uint32_t qsee_perf_client;
-
struct qseecom_registered_listener_list {
struct list_head list;
struct qseecom_register_listener_req svc;
@@ -106,6 +101,13 @@
struct qseecom_handle *handle;
};
+struct qseecom_clk {
+ struct clk *ce_core_clk;
+ struct clk *ce_clk;
+ struct clk *ce_core_src_clk;
+ struct clk *ce_bus_clk;
+};
+
struct qseecom_control {
struct ion_client *ion_clnt; /* Ion client */
struct list_head registered_listener_list_head;
@@ -124,6 +126,12 @@
uint32_t qsee_version;
struct device *pdev;
bool commonlib_loaded;
+
+ int qsee_bw_count;
+ int qsee_sfpb_bw_count;
+
+ uint32_t qsee_perf_client;
+ struct qseecom_clk qsee;
};
struct qseecom_client_handle {
@@ -155,11 +163,6 @@
atomic_t ioctl_count;
};
-struct clk *ce_core_clk;
-struct clk *ce_clk;
-struct clk *ce_core_src_clk;
-struct clk *ce_bus_clk;
-
struct qseecom_sg_entry {
uint32_t phys_addr;
uint32_t len;
@@ -355,12 +358,14 @@
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req,
sizeof(req), &resp, sizeof(resp));
if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ pr_err("scm_call() failed with err: %d (lstnr id=%d)\n",
+ ret, data->listener.id);
return ret;
}
if (resp.result != QSEOS_RESULT_SUCCESS) {
- pr_err("SB deregistartion: result=%d\n", resp.result);
+ pr_err("Failed resp.result=%d,(lstnr id=%d)\n",
+ resp.result, data->listener.id);
return -EPERM;
}
} else {
@@ -538,12 +543,13 @@
sizeof(send_data_rsp), resp,
sizeof(*resp));
if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ pr_err("scm_call() failed with err: %d (app_id = %d)\n",
+ ret, data->client.app_id);
return ret;
}
if (resp->result == QSEOS_RESULT_FAILURE) {
- pr_err("Response result %d not supported\n",
- resp->result);
+ pr_err("Response result %d FAIL (app_id = %d)\n",
+ resp->result, data->client.app_id);
return -EINVAL;
}
}
@@ -980,7 +986,8 @@
sizeof(send_data_req),
&resp, sizeof(resp));
if (ret) {
- pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ pr_err("scm_call() failed with err: %d (app_id = %d)\n",
+ ret, data->client.app_id);
return ret;
}
@@ -1161,13 +1168,15 @@
if (wait_event_freezable(this_lstnr->rcv_req_wq,
__qseecom_listener_has_rcvd_req(data,
this_lstnr))) {
- pr_warning("Interrupted: exiting wait_rcv_req loop\n");
+ pr_warning("Interrupted: exiting Listener Service = %d\n",
+ (uint32_t)data->listener.id);
/* woken up for different reason */
return -ERESTARTSYS;
}
if (data->abort) {
- pr_err("Aborting driver!\n");
+ pr_err("Aborting Listener Service = %d\n",
+ (uint32_t)data->listener.id);
return -ENODEV;
}
this_lstnr->rcv_req_flag = 0;
@@ -1387,6 +1396,14 @@
}
/* Populate the remaining parameters */
load_req.qsee_cmd_id = QSEOS_LOAD_SERV_IMAGE_COMMAND;
+ /* Vote for the SFPB clock */
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret) {
+ pr_err("Unable to vote for SFPB clock: ret = %d", ret);
+ kzfree(img_data);
+ return -EIO;
+ }
+
/* SCM_CALL to load the image */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
sizeof(struct qseecom_load_lib_image_ireq),
@@ -1417,6 +1434,7 @@
}
}
kzfree(img_data);
+ qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
}
@@ -1517,7 +1535,7 @@
}
if (ret) {
- pr_err("Failed to loadd commonlib image\n");
+ pr_err("Failed to load commonlib image\n");
kfree(data);
kfree(*handle);
*handle = NULL;
@@ -1746,64 +1764,123 @@
return 0;
}
+static int __qseecom_enable_clk(void)
+{
+ int rc = 0;
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
+ /* Enable CE core clk */
+ rc = clk_prepare_enable(qclk->ce_core_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE core clk\n");
+ goto err;
+ }
+ /* Enable CE clk */
+ rc = clk_prepare_enable(qclk->ce_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE iface clk\n");
+ goto ce_clk_err;
+ }
+ /* Enable AXI clk */
+ rc = clk_prepare_enable(qclk->ce_bus_clk);
+ if (rc) {
+ pr_err("Unable to enable/prepare CE bus clk\n");
+ goto ce_bus_clk_err;
+ }
+ return 0;
+
+ce_bus_clk_err:
+ clk_disable_unprepare(qclk->ce_clk);
+ce_clk_err:
+ clk_disable_unprepare(qclk->ce_core_clk);
+err:
+ return -EIO;
+}
+
+static void __qseecom_disable_clk(void)
+{
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
+ if (qclk->ce_clk != NULL)
+ clk_disable_unprepare(qclk->ce_clk);
+ if (qclk->ce_core_clk != NULL)
+ clk_disable_unprepare(qclk->ce_core_clk);
+ if (qclk->ce_bus_clk != NULL)
+ clk_disable_unprepare(qclk->ce_bus_clk);
+}
+
static int qsee_vote_for_clock(struct qseecom_dev_handle *data,
int32_t clk_type)
{
int ret = 0;
+ struct qseecom_clk *qclk;
- if (!qsee_perf_client)
+ qclk = &qseecom.qsee;
+ if (!qseecom.qsee_perf_client)
return ret;
switch (clk_type) {
case CLK_DFAB:
mutex_lock(&qsee_bw_mutex);
- if (!qsee_bw_count) {
- if (qsee_sfpb_bw_count > 0)
+ if (!qseecom.qsee_bw_count) {
+ if (qseecom.qsee_sfpb_bw_count > 0)
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 3);
+ qseecom.qsee_perf_client, 3);
else {
- if (ce_core_src_clk != NULL)
- clk_set_rate(ce_core_src_clk,
- QSEE_CE_CLK_100MHZ);
- ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 1);
+ if (qclk->ce_core_src_clk != NULL)
+ ret = __qseecom_enable_clk();
+ if (!ret) {
+ ret =
+ msm_bus_scale_client_update_request(
+ qseecom.qsee_perf_client, 1);
+ if ((ret) &&
+ (qclk->ce_core_src_clk != NULL))
+ __qseecom_disable_clk();
+ }
}
if (ret)
pr_err("DFAB Bandwidth req failed (%d)\n",
ret);
else {
- qsee_bw_count++;
+ qseecom.qsee_bw_count++;
data->client.perf_enabled = true;
}
} else {
- qsee_bw_count++;
+ qseecom.qsee_bw_count++;
data->client.perf_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
break;
case CLK_SFPB:
mutex_lock(&qsee_bw_mutex);
- if (!qsee_sfpb_bw_count) {
- if (qsee_bw_count > 0)
+ if (!qseecom.qsee_sfpb_bw_count) {
+ if (qseecom.qsee_bw_count > 0)
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 3);
+ qseecom.qsee_perf_client, 3);
else {
- if (ce_core_src_clk != NULL)
- clk_set_rate(ce_core_src_clk,
- QSEE_CE_CLK_100MHZ);
- ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 2);
+ if (qclk->ce_core_src_clk != NULL)
+ ret = __qseecom_enable_clk();
+ if (!ret) {
+ ret =
+ msm_bus_scale_client_update_request(
+ qseecom.qsee_perf_client, 2);
+ if ((ret) &&
+ (qclk->ce_core_src_clk != NULL))
+ __qseecom_disable_clk();
+ }
}
if (ret)
pr_err("SFPB Bandwidth req failed (%d)\n",
ret);
else {
- qsee_sfpb_bw_count++;
+ qseecom.qsee_sfpb_bw_count++;
data->client.fast_load_enabled = true;
}
} else {
- qsee_sfpb_bw_count++;
+ qseecom.qsee_sfpb_bw_count++;
data->client.fast_load_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
@@ -1819,70 +1896,70 @@
int32_t clk_type)
{
int32_t ret = 0;
+ struct qseecom_clk *qclk;
- if (!qsee_perf_client)
+ qclk = &qseecom.qsee;
+ if (!qseecom.qsee_perf_client)
return;
switch (clk_type) {
case CLK_DFAB:
mutex_lock(&qsee_bw_mutex);
- if (qsee_bw_count == 0) {
+ if (qseecom.qsee_bw_count == 0) {
pr_err("Client error.Extra call to disable DFAB clk\n");
mutex_unlock(&qsee_bw_mutex);
return;
}
- if (qsee_bw_count == 1) {
- if (qsee_sfpb_bw_count > 0)
+ if (qseecom.qsee_bw_count == 1) {
+ if (qseecom.qsee_sfpb_bw_count > 0)
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 2);
+ qseecom.qsee_perf_client, 2);
else {
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 0);
- if (ce_core_src_clk != NULL)
- clk_set_rate(ce_core_src_clk,
- QSEE_CE_CLK_50MHZ);
+ qseecom.qsee_perf_client, 0);
+ if ((!ret) && (qclk->ce_core_src_clk != NULL))
+ __qseecom_disable_clk();
}
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
else {
- qsee_bw_count--;
+ qseecom.qsee_bw_count--;
data->client.perf_enabled = false;
}
} else {
- qsee_bw_count--;
+ qseecom.qsee_bw_count--;
data->client.perf_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
break;
case CLK_SFPB:
mutex_lock(&qsee_bw_mutex);
- if (qsee_sfpb_bw_count == 0) {
+ if (qseecom.qsee_sfpb_bw_count == 0) {
pr_err("Client error.Extra call to disable SFPB clk\n");
mutex_unlock(&qsee_bw_mutex);
return;
}
- if (qsee_sfpb_bw_count == 1) {
- if (qsee_bw_count > 0)
+ if (qseecom.qsee_sfpb_bw_count == 1) {
+ if (qseecom.qsee_bw_count > 0)
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 1);
+ qseecom.qsee_perf_client, 1);
else {
ret = msm_bus_scale_client_update_request(
- qsee_perf_client, 0);
- if (ce_core_src_clk != NULL)
- clk_set_rate(ce_core_src_clk,
- QSEE_CE_CLK_50MHZ);
+ qseecom.qsee_perf_client, 0);
+ if ((!ret) && (qclk->ce_core_src_clk != NULL))
+ __qseecom_disable_clk();
}
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
ret);
else {
- qsee_sfpb_bw_count--;
+ qseecom.qsee_sfpb_bw_count--;
data->client.fast_load_enabled = false;
}
} else {
- qsee_sfpb_bw_count--;
+ qseecom.qsee_sfpb_bw_count--;
data->client.fast_load_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
@@ -1941,6 +2018,13 @@
ret = -EFAULT;
goto qseecom_load_external_elf_set_cpu_err;
}
+ /* Vote for the SFPB clock */
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret) {
+ pr_err("Unable to vote for SFPB clock: ret = %d", ret);
+ ret = -EIO;
+ goto qseecom_load_external_elf_set_cpu_err;
+ }
/* SCM_CALL to load the external elf */
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &load_req,
@@ -1980,7 +2064,7 @@
/* Deallocate the handle */
if (!IS_ERR_OR_NULL(ihandle))
ion_free(qseecom.ion_clnt, ihandle);
-
+ qsee_disable_clock_vote(data, CLK_SFPB);
return ret;
}
@@ -2350,97 +2434,61 @@
.release = qseecom_release
};
-static int __qseecom_enable_clk(void)
-{
- int rc = 0;
-
- /* Enable CE core clk */
- rc = clk_prepare_enable(ce_core_clk);
- if (rc) {
- pr_err("Unable to enable/prepare CE core clk\n");
- return -EIO;
- } else {
- /* Enable CE clk */
- rc = clk_prepare_enable(ce_clk);
- if (rc) {
- pr_err("Unable to enable/prepare CE iface clk\n");
- clk_disable_unprepare(ce_core_clk);
- return -EIO;
- } else {
- /* Enable AXI clk */
- rc = clk_prepare_enable(ce_bus_clk);
- if (rc) {
- pr_err("Unable to enable/prepare CE iface clk\n");
- clk_disable_unprepare(ce_core_clk);
- clk_disable_unprepare(ce_clk);
- return -EIO;
- }
- }
- }
- return rc;
-}
-
-static void __qseecom_disable_clk(void)
-{
- if (ce_clk != NULL)
- clk_disable_unprepare(ce_clk);
- if (ce_core_clk != NULL)
- clk_disable_unprepare(ce_core_clk);
- if (ce_bus_clk != NULL)
- clk_disable_unprepare(ce_bus_clk);
-}
-
static int __qseecom_init_clk(void)
{
int rc = 0;
struct device *pdev;
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
pdev = qseecom.pdev;
/* Get CE3 src core clk. */
- ce_core_src_clk = clk_get(pdev, "core_clk_src");
- if (!IS_ERR(ce_core_src_clk)) {
- /* Set the core src clk @50Mhz */
- rc = clk_set_rate(ce_core_src_clk, QSEE_CE_CLK_50MHZ);
+
+ qclk->ce_core_src_clk = clk_get(pdev, "core_clk_src");
+ if (!IS_ERR(qclk->ce_core_src_clk)) {
+ /* Set the core src clk @100Mhz */
+ rc = clk_set_rate(qclk->ce_core_src_clk, QSEE_CE_CLK_100MHZ);
if (rc) {
- clk_put(ce_core_src_clk);
+ clk_put(qclk->ce_core_src_clk);
pr_err("Unable to set the core src clk @100Mhz.\n");
return -EIO;
}
} else {
pr_warn("Unable to get CE core src clk, set to NULL\n");
- ce_core_src_clk = NULL;
+ qclk->ce_core_src_clk = NULL;
}
/* Get CE core clk */
- ce_core_clk = clk_get(pdev, "core_clk");
- if (IS_ERR(ce_core_clk)) {
- rc = PTR_ERR(ce_core_clk);
+ qclk->ce_core_clk = clk_get(pdev, "core_clk");
+ if (IS_ERR(qclk->ce_core_clk)) {
+ rc = PTR_ERR(qclk->ce_core_clk);
pr_err("Unable to get CE core clk\n");
- if (ce_core_src_clk != NULL)
- clk_put(ce_core_src_clk);
+ if (qclk->ce_core_src_clk != NULL)
+ clk_put(qclk->ce_core_src_clk);
return -EIO;
}
/* Get CE Interface clk */
- ce_clk = clk_get(pdev, "iface_clk");
- if (IS_ERR(ce_clk)) {
- rc = PTR_ERR(ce_clk);
+ qclk->ce_clk = clk_get(pdev, "iface_clk");
+ if (IS_ERR(qclk->ce_clk)) {
+ rc = PTR_ERR(qclk->ce_clk);
pr_err("Unable to get CE interface clk\n");
- if (ce_core_src_clk != NULL)
- clk_put(ce_core_src_clk);
- clk_put(ce_core_clk);
+ if (qclk->ce_core_src_clk != NULL)
+ clk_put(qclk->ce_core_src_clk);
+ clk_put(qclk->ce_core_clk);
return -EIO;
}
/* Get CE AXI clk */
- ce_bus_clk = clk_get(pdev, "bus_clk");
- if (IS_ERR(ce_bus_clk)) {
- rc = PTR_ERR(ce_bus_clk);
+ qclk->ce_bus_clk = clk_get(pdev, "bus_clk");
+ if (IS_ERR(qclk->ce_bus_clk)) {
+ rc = PTR_ERR(qclk->ce_bus_clk);
pr_err("Unable to get CE BUS interface clk\n");
- if (ce_core_src_clk != NULL)
- clk_put(ce_core_src_clk);
- clk_put(ce_core_clk);
- clk_put(ce_clk);
+ if (qclk->ce_core_src_clk != NULL)
+ clk_put(qclk->ce_core_src_clk);
+ clk_put(qclk->ce_core_clk);
+ clk_put(qclk->ce_clk);
return -EIO;
}
return rc;
@@ -2448,21 +2496,25 @@
static void __qseecom_deinit_clk(void)
{
- if (ce_clk != NULL) {
- clk_put(ce_clk);
- ce_clk = NULL;
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
+
+ if (qclk->ce_clk != NULL) {
+ clk_put(qclk->ce_clk);
+ qclk->ce_clk = NULL;
}
- if (ce_core_clk != NULL) {
- clk_put(ce_core_clk);
- ce_clk = NULL;
+ if (qclk->ce_core_clk != NULL) {
+ clk_put(qclk->ce_core_clk);
+ qclk->ce_clk = NULL;
}
- if (ce_bus_clk != NULL) {
- clk_put(ce_bus_clk);
- ce_clk = NULL;
+ if (qclk->ce_bus_clk != NULL) {
+ clk_put(qclk->ce_bus_clk);
+ qclk->ce_clk = NULL;
}
- if (ce_core_src_clk != NULL) {
- clk_put(ce_core_src_clk);
- ce_core_src_clk = NULL;
+ if (qclk->ce_core_src_clk != NULL) {
+ clk_put(qclk->ce_core_src_clk);
+ qclk->ce_core_src_clk = NULL;
}
}
@@ -2475,14 +2527,14 @@
struct msm_bus_scale_pdata *qseecom_platform_support = NULL;
uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
- qsee_bw_count = 0;
- qsee_perf_client = 0;
- qsee_sfpb_bw_count = 0;
+ qseecom.qsee_bw_count = 0;
+ qseecom.qsee_perf_client = 0;
+ qseecom.qsee_sfpb_bw_count = 0;
- ce_core_clk = NULL;
- ce_clk = NULL;
- ce_core_src_clk = NULL;
- ce_bus_clk = NULL;
+ qseecom.qsee.ce_core_clk = NULL;
+ qseecom.qsee.ce_clk = NULL;
+ qseecom.qsee.ce_core_src_clk = NULL;
+ qseecom.qsee.ce_bus_clk = NULL;
rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
if (rc < 0) {
@@ -2561,11 +2613,7 @@
ret = __qseecom_init_clk();
if (ret)
goto err;
- ret = __qseecom_enable_clk();
- if (ret) {
- __qseecom_deinit_clk();
- goto err;
- }
+
qseecom_platform_support = (struct msm_bus_scale_pdata *)
msm_bus_cl_get_pdata(pdev);
if (qseecom.qsee_version >= (QSEE_VERSION_02)) {
@@ -2599,10 +2647,10 @@
pdev->dev.platform_data;
}
- qsee_perf_client = msm_bus_scale_register_client(
+ qseecom.qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
- if (!qsee_perf_client)
+ if (!qseecom.qsee_perf_client)
pr_err("Unable to register bus client\n");
return 0;
err:
@@ -2621,7 +2669,7 @@
int ret = 0;
if (pdev->dev.platform_data != NULL)
- msm_bus_scale_unregister_client(qsee_perf_client);
+ msm_bus_scale_unregister_client(qseecom.qsee_perf_client);
spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
kclient = list_entry((&qseecom.registered_kclient_list_head)->next,
@@ -2672,13 +2720,13 @@
if (qseecom.qseos_version > QSEEE_VERSION_00)
qseecom_unload_commonlib_image();
- if (qsee_perf_client)
- msm_bus_scale_client_update_request(qsee_perf_client, 0);
+ if (qseecom.qsee_perf_client)
+ msm_bus_scale_client_update_request(qseecom.qsee_perf_client,
+ 0);
/* register client for bus scaling */
- if (pdev->dev.of_node) {
- __qseecom_disable_clk();
+ if (pdev->dev.of_node)
__qseecom_deinit_clk();
- }
+
return ret;
};
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index f3973ef..4a063fd 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1160,9 +1160,16 @@
data_cnt = SPS_MAX_DESC_SIZE;
} else {
data_cnt = len;
- if (i == data->sg_len - 1)
+ if ((i == data->sg_len - 1) &&
+ (sps_pipe_handle ==
+ host->sps.cons.pipe_handle)) {
+ /*
+ * set EOT only for consumer pipe, for
+ * producer pipe h/w will set it.
+ */
flags = SPS_IOVEC_FLAG_INT |
SPS_IOVEC_FLAG_EOT;
+ }
}
rc = sps_transfer_one(sps_pipe_handle, addr,
data_cnt, host, flags);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 7bae401..2769709 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -35,6 +35,7 @@
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/mmc/cd-gpio.h>
+#include <linux/dma-mapping.h>
#include <mach/gpio.h>
#include <mach/msm_bus.h>
@@ -102,6 +103,10 @@
0xFFFFBBBB, 0xFFFF77FF, 0xFF7777FF, 0xEEDDBB77
};
+static int disable_slots;
+/* root can write, others read */
+module_param(disable_slots, int, S_IRUGO|S_IWUSR);
+
/* This structure keeps information per regulator */
struct sdhci_msm_reg_data {
/* voltage regulator handle */
@@ -198,13 +203,14 @@
u32 caps2;
unsigned long mmc_bus_width;
- u32 max_clk;
struct sdhci_msm_slot_reg_data *vreg_data;
bool nonremovable;
struct sdhci_msm_pin_data *pin_data;
u32 cpu_dma_latency_us;
int status_gpio; /* card detection GPIO that is configured as IRQ */
struct sdhci_msm_bus_voting_data *voting_data;
+ u32 *sup_clk_table;
+ unsigned char sup_clk_cnt;
};
struct sdhci_msm_bus_vote {
@@ -228,8 +234,11 @@
struct sdhci_msm_pltfm_data *pdata;
struct mmc_host *mmc;
struct sdhci_pltfm_data sdhci_msm_pdata;
- wait_queue_head_t pwr_irq_wait;
+ u32 curr_pwr_state;
+ u32 curr_io_level;
+ struct completion pwr_irq_completion;
struct sdhci_msm_bus_vote msm_bus_vote;
+ u32 clk_rate; /* Keeps track of current clock rate that is set */
};
enum vdd_io_level {
@@ -549,9 +558,18 @@
int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
int rc;
struct mmc_host *mmc = host->mmc;
+ struct mmc_ios ios = host->mmc->ios;
+
+ /*
+ * Tuning is required for SDR104 and HS200 cards and if clock frequency
+ * is greater than 100MHz in these modes.
+ */
+ if (host->clock <= (100 * 1000 * 1000) ||
+ !(ios.timing == MMC_TIMING_MMC_HS200 ||
+ ios.timing == MMC_TIMING_UHS_SDR104))
+ return 0;
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
- /* Tuning is only required for SDR104 modes */
spin_lock_irqsave(&host->lock, flags);
if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
@@ -1073,6 +1091,8 @@
u32 bus_width = 0;
u32 cpu_dma_latency;
int len, i;
+ int clk_table_len;
+ u32 *clk_table = NULL;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1096,6 +1116,18 @@
&cpu_dma_latency))
pdata->cpu_dma_latency_us = cpu_dma_latency;
+ if (sdhci_msm_dt_get_array(dev, "qcom,clk-rates",
+ &clk_table, &clk_table_len, 0)) {
+ dev_err(dev, "failed parsing supported clock rates\n");
+ goto out;
+ }
+ if (!clk_table || !clk_table_len) {
+ dev_err(dev, "Invalid clock table\n");
+ goto out;
+ }
+ pdata->sup_clk_table = clk_table;
+ pdata->sup_clk_cnt = clk_table_len;
+
pdata->vreg_data = devm_kzalloc(dev, sizeof(struct
sdhci_msm_slot_reg_data),
GFP_KERNEL);
@@ -1121,8 +1153,6 @@
goto out;
}
- of_property_read_u32(np, "qcom,max-clk-rate", &pdata->max_clk);
-
len = of_property_count_strings(np, "qcom,bus-speed-mode");
for (i = 0; i < len; i++) {
@@ -1637,6 +1667,8 @@
u8 irq_status = 0;
u8 irq_ack = 0;
int ret = 0;
+ int pwr_state = 0, io_level = 0;
+ unsigned long flags;
irq_status = readb_relaxed(msm_host->core_mem + CORE_PWRCTL_STATUS);
pr_debug("%s: Received IRQ(%d), status=0x%x\n",
@@ -1655,21 +1687,33 @@
/* Handle BUS ON/OFF*/
if (irq_status & CORE_PWRCTL_BUS_ON) {
ret = sdhci_msm_setup_vreg(msm_host->pdata, true, false);
- if (!ret)
+ if (!ret) {
ret = sdhci_msm_setup_pins(msm_host->pdata, true);
+ ret |= sdhci_msm_set_vdd_io_vol(msm_host->pdata,
+ VDD_IO_HIGH, 0);
+ }
if (ret)
irq_ack |= CORE_PWRCTL_BUS_FAIL;
else
irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+
+ pwr_state = REQ_BUS_ON;
+ io_level = REQ_IO_HIGH;
}
if (irq_status & CORE_PWRCTL_BUS_OFF) {
ret = sdhci_msm_setup_vreg(msm_host->pdata, false, false);
- if (!ret)
+ if (!ret) {
ret = sdhci_msm_setup_pins(msm_host->pdata, false);
+ ret |= sdhci_msm_set_vdd_io_vol(msm_host->pdata,
+ VDD_IO_LOW, 0);
+ }
if (ret)
irq_ack |= CORE_PWRCTL_BUS_FAIL;
else
irq_ack |= CORE_PWRCTL_BUS_SUCCESS;
+
+ pwr_state = REQ_BUS_OFF;
+ io_level = REQ_IO_LOW;
}
/* Handle IO LOW/HIGH */
if (irq_status & CORE_PWRCTL_IO_LOW) {
@@ -1679,6 +1723,8 @@
irq_ack |= CORE_PWRCTL_IO_FAIL;
else
irq_ack |= CORE_PWRCTL_IO_SUCCESS;
+
+ io_level = REQ_IO_LOW;
}
if (irq_status & CORE_PWRCTL_IO_HIGH) {
/* Switch voltage High */
@@ -1687,6 +1733,8 @@
irq_ack |= CORE_PWRCTL_IO_FAIL;
else
irq_ack |= CORE_PWRCTL_IO_SUCCESS;
+
+ io_level = REQ_IO_HIGH;
}
/* ACK status to the core */
@@ -1699,11 +1747,11 @@
*/
mb();
- if (irq_status & CORE_PWRCTL_IO_HIGH)
+ if (io_level & REQ_IO_HIGH)
writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
~CORE_IO_PAD_PWR_SWITCH),
host->ioaddr + CORE_VENDOR_SPEC);
- if (irq_status & CORE_PWRCTL_IO_LOW)
+ else if (io_level & REQ_IO_LOW)
writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) |
CORE_IO_PAD_PWR_SWITCH),
host->ioaddr + CORE_VENDOR_SPEC);
@@ -1711,7 +1759,14 @@
pr_debug("%s: Handled IRQ(%d), ret=%d, ack=0x%x\n",
mmc_hostname(msm_host->mmc), irq, ret, irq_ack);
- wake_up_interruptible(&msm_host->pwr_irq_wait);
+ spin_lock_irqsave(&host->lock, flags);
+ if (pwr_state)
+ msm_host->curr_pwr_state = pwr_state;
+ if (io_level)
+ msm_host->curr_io_level = io_level;
+ complete(&msm_host->pwr_irq_completion);
+ spin_unlock_irqrestore(&host->lock, flags);
+
return IRQ_HANDLED;
}
@@ -1757,25 +1812,36 @@
return count;
}
-static void sdhci_msm_check_power_status(struct sdhci_host *host)
+static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
- int ret = 0;
+ unsigned long flags;
+ bool done = false;
- pr_debug("%s: %s: power status before waiting 0x%x\n",
- mmc_hostname(host->mmc), __func__,
- readb_relaxed(msm_host->core_mem + CORE_PWRCTL_CTL));
+ spin_lock_irqsave(&host->lock, flags);
+ pr_debug("%s: %s: request %d curr_pwr_state %x curr_io_level %x\n",
+ mmc_hostname(host->mmc), __func__, req_type,
+ msm_host->curr_pwr_state, msm_host->curr_io_level);
+ if ((req_type & msm_host->curr_pwr_state) ||
+ (req_type & msm_host->curr_io_level))
+ done = true;
+ spin_unlock_irqrestore(&host->lock, flags);
- ret = wait_event_interruptible(msm_host->pwr_irq_wait,
- (readb_relaxed(msm_host->core_mem +
- CORE_PWRCTL_CTL)) != 0x0);
- if (ret)
- pr_warning("%s: %s: returned due to error %d\n",
- mmc_hostname(host->mmc), __func__, ret);
- pr_debug("%s: %s: ret %d power status after handling power IRQ 0x%x\n",
- mmc_hostname(host->mmc), __func__, ret,
- readb_relaxed(msm_host->core_mem + CORE_PWRCTL_CTL));
+ /*
+ * This is needed here to hanlde a case where IRQ gets
+ * triggered even before this function is called so that
+ * x->done counter of completion gets reset. Otherwise,
+ * next call to wait_for_completion returns immediately
+ * without actually waiting for the IRQ to be handled.
+ */
+ if (done)
+ init_completion(&msm_host->pwr_irq_completion);
+ else
+ wait_for_completion(&msm_host->pwr_irq_completion);
+
+ pr_debug("%s: %s: request %d done\n", mmc_hostname(host->mmc),
+ __func__, req_type);
}
static void sdhci_msm_toggle_cdr(struct sdhci_host *host, bool enable)
@@ -1795,16 +1861,58 @@
return SDHCI_MSM_MAX_SEGMENTS;
}
-void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
{
- int rc;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
- unsigned long flags;
- if (clock && !atomic_read(&msm_host->clks_on)) {
- pr_debug("%s: request to enable clock at rate %u\n",
- mmc_hostname(host->mmc), clock);
+ return msm_host->pdata->sup_clk_table[0];
+}
+
+static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ int max_clk_index = msm_host->pdata->sup_clk_cnt;
+
+ return msm_host->pdata->sup_clk_table[max_clk_index - 1];
+}
+
+static unsigned int sdhci_msm_get_sup_clk_rate(struct sdhci_host *host,
+ u32 req_clk)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ unsigned int sel_clk = -1;
+ unsigned char cnt;
+
+ if (req_clk < sdhci_msm_get_min_clock(host)) {
+ sel_clk = sdhci_msm_get_min_clock(host);
+ return sel_clk;
+ }
+
+ for (cnt = 0; cnt < msm_host->pdata->sup_clk_cnt; cnt++) {
+ if (msm_host->pdata->sup_clk_table[cnt] > req_clk) {
+ break;
+ } else if (msm_host->pdata->sup_clk_table[cnt] == req_clk) {
+ sel_clk = msm_host->pdata->sup_clk_table[cnt];
+ break;
+ } else {
+ sel_clk = msm_host->pdata->sup_clk_table[cnt];
+ }
+ }
+ return sel_clk;
+}
+
+static int sdhci_msm_prepare_clocks(struct sdhci_host *host, bool enable)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ int rc = 0;
+
+ if (enable && !atomic_read(&msm_host->clks_on)) {
+ pr_debug("%s: request to enable clocks\n",
+ mmc_hostname(host->mmc));
if (!IS_ERR_OR_NULL(msm_host->bus_clk)) {
rc = clk_prepare_enable(msm_host->bus_clk);
if (rc) {
@@ -1828,9 +1936,8 @@
goto disable_pclk;
}
mb();
- atomic_set(&msm_host->clks_on, 1);
- } else if (!clock && atomic_read(&msm_host->clks_on)) {
+ } else if (!enable && atomic_read(&msm_host->clks_on)) {
pr_debug("%s: request to disable clocks\n",
mmc_hostname(host->mmc));
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
@@ -1840,11 +1947,8 @@
clk_disable_unprepare(msm_host->pclk);
if (!IS_ERR_OR_NULL(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
- atomic_set(&msm_host->clks_on, 0);
}
- spin_lock_irqsave(&host->lock, flags);
- host->clock = clock;
- spin_unlock_irqrestore(&host->lock, flags);
+ atomic_set(&msm_host->clks_on, enable);
goto out;
disable_pclk:
if (!IS_ERR_OR_NULL(msm_host->pclk))
@@ -1853,16 +1957,100 @@
if (!IS_ERR_OR_NULL(msm_host->bus_clk))
clk_disable_unprepare(msm_host->bus_clk);
out:
- return;
+ return rc;
+}
+
+static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ int rc;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+ struct mmc_ios curr_ios = host->mmc->ios;
+ u32 sup_clock, ddr_clock;
+
+ if (!clock) {
+ sdhci_msm_prepare_clocks(host, false);
+ host->clock = clock;
+ return;
+ }
+
+ rc = sdhci_msm_prepare_clocks(host, true);
+ if (rc)
+ return;
+
+ sup_clock = sdhci_msm_get_sup_clk_rate(host, clock);
+ if (curr_ios.timing == MMC_TIMING_UHS_DDR50) {
+ /*
+ * The SDHC requires internal clock frequency to be double the
+ * actual clock that will be set for DDR mode. The controller
+ * uses the faster clock(100MHz) for some of its parts and send
+ * the actual required clock (50MHz) to the card.
+ */
+ ddr_clock = clock * 2;
+ sup_clock = sdhci_msm_get_sup_clk_rate(host,
+ ddr_clock);
+ }
+ if (sup_clock != msm_host->clk_rate) {
+ pr_debug("%s: %s: setting clk rate to %u\n",
+ mmc_hostname(host->mmc), __func__, sup_clock);
+ rc = clk_set_rate(msm_host->clk, sup_clock);
+ if (rc) {
+ pr_err("%s: %s: Failed to set rate %u for host-clk : %d\n",
+ mmc_hostname(host->mmc), __func__,
+ sup_clock, rc);
+ return;
+ }
+ msm_host->clk_rate = sup_clock;
+ host->clock = clock;
+ }
+}
+
+static int sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
+ unsigned int uhs)
+{
+ u16 ctrl_2;
+
+ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+ /* Select Bus Speed Mode for host */
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ if (uhs == MMC_TIMING_MMC_HS200)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+ else if (uhs == MMC_TIMING_UHS_SDR12)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+ else if (uhs == MMC_TIMING_UHS_SDR25)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+ else if (uhs == MMC_TIMING_UHS_SDR50)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+ else if (uhs == MMC_TIMING_UHS_SDR104)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+ else if (uhs == MMC_TIMING_UHS_DDR50)
+ ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+ /*
+ * When clock frquency is less than 100MHz, the feedback clock must be
+ * provided and DLL must not be used so that tuning can be skipped. To
+ * provide feedback clock, the mode selection can be any value less
+ * than 3'b011 in bits [2:0] of HOST CONTROL2 register.
+ */
+ if (host->clock <= (100 * 1000 * 1000) &&
+ (uhs == MMC_TIMING_MMC_HS200 ||
+ uhs == MMC_TIMING_UHS_SDR104))
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+ return 0;
}
static struct sdhci_ops sdhci_msm_ops = {
+ .set_uhs_signaling = sdhci_msm_set_uhs_signaling,
.check_power_status = sdhci_msm_check_power_status,
.execute_tuning = sdhci_msm_execute_tuning,
.toggle_cdr = sdhci_msm_toggle_cdr,
.get_max_segments = sdhci_msm_max_segs,
.set_clock = sdhci_msm_set_clock,
.platform_bus_voting = sdhci_msm_bus_voting,
+ .get_min_clock = sdhci_msm_get_min_clock,
+ .get_max_clock = sdhci_msm_get_max_clock,
};
static int __devinit sdhci_msm_probe(struct platform_device *pdev)
@@ -1882,7 +2070,6 @@
ret = -ENOMEM;
goto out;
}
- init_waitqueue_head(&msm_host->pwr_irq_wait);
msm_host->sdhci_msm_pdata.ops = &sdhci_msm_ops;
host = sdhci_pltfm_init(pdev, &msm_host->sdhci_msm_pdata);
@@ -1898,6 +2085,19 @@
/* Extract platform data */
if (pdev->dev.of_node) {
+ ret = of_alias_get_id(pdev->dev.of_node, "sdhc");
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get slot index %d\n",
+ ret);
+ goto pltfm_free;
+ }
+ if (disable_slots & (1 << (ret - 1))) {
+ dev_info(&pdev->dev, "%s: Slot %d disabled\n", __func__,
+ ret);
+ ret = -ENODEV;
+ goto pltfm_free;
+ }
+
msm_host->pdata = sdhci_msm_populate_pdata(&pdev->dev);
if (!msm_host->pdata) {
dev_err(&pdev->dev, "DT parsing error\n");
@@ -1941,7 +2141,15 @@
if (ret)
goto pclk_disable;
+ /* Set to the minimum supported clock frequency */
+ ret = clk_set_rate(msm_host->clk, sdhci_msm_get_min_clock(host));
+ if (ret) {
+ dev_err(&pdev->dev, "MClk rate set failed (%d)\n", ret);
+ goto clk_disable;
+ }
+ msm_host->clk_rate = sdhci_msm_get_min_clock(host);
atomic_set(&msm_host->clks_on, 1);
+
/* Setup regulators */
ret = sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, true);
if (ret) {
@@ -1973,6 +2181,8 @@
*/
host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
host->quirks |= SDHCI_QUIRK_SINGLE_POWER_WRITE;
+ host->quirks |= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
+ host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK;
host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING;
host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
@@ -2045,6 +2255,7 @@
msm_host->mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
msm_host->mmc->caps2 |= MMC_CAP2_INIT_BKOPS;
msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
+ msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
if (msm_host->pdata->nonremovable)
msm_host->mmc->caps |= MMC_CAP_NONREMOVABLE;
@@ -2059,6 +2270,8 @@
INIT_DELAYED_WORK(&msm_host->msm_bus_vote.vote_work,
sdhci_msm_bus_work);
+ init_completion(&msm_host->pwr_irq_completion);
+
if (gpio_is_valid(msm_host->pdata->status_gpio)) {
ret = mmc_cd_gpio_request(msm_host->mmc,
msm_host->pdata->status_gpio);
@@ -2069,21 +2282,19 @@
}
}
+ if (dma_supported(mmc_dev(host->mmc), DMA_BIT_MASK(32))) {
+ host->dma_mask = DMA_BIT_MASK(32);
+ mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
+ } else {
+ dev_err(&pdev->dev, "%s: Failed to set dma mask\n", __func__);
+ }
+
ret = sdhci_add_host(host);
if (ret) {
dev_err(&pdev->dev, "Add host failed (%d)\n", ret);
goto free_cd_gpio;
}
- /* Set core clk rate, optionally override from dts */
- if (msm_host->pdata->max_clk)
- host->max_clk = msm_host->pdata->max_clk;
- ret = clk_set_rate(msm_host->clk, host->max_clk);
- if (ret) {
- dev_err(&pdev->dev, "MClk rate set failed (%d)\n", ret);
- goto remove_host;
- }
-
msm_host->msm_bus_vote.max_bus_bw.show = show_sdhci_max_bus_bw;
msm_host->msm_bus_vote.max_bus_bw.store = store_sdhci_max_bus_bw;
sysfs_attr_init(&msm_host->msm_bus_vote.max_bus_bw.attr);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 0a89ea2..c247ae9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -197,7 +197,7 @@
if (host->ops->check_power_status && host->pwr &&
(mask & SDHCI_RESET_ALL))
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_OFF);
/* hw clears the bit when it's done */
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
@@ -1209,6 +1209,9 @@
if (real_div)
host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
+ if (host->quirks2 & SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK)
+ div = 0;
+
clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
<< SDHCI_DIVIDER_HI_SHIFT;
@@ -1268,7 +1271,7 @@
if (pwr == 0) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_OFF);
return 0;
}
@@ -1279,7 +1282,7 @@
if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) {
sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_OFF);
}
/*
@@ -1289,14 +1292,14 @@
if (host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER) {
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_ON);
}
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_ON);
/*
* Some controllers need an extra 10ms delay of 10ms before they
@@ -1741,7 +1744,7 @@
ctrl &= ~SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_IO_HIGH);
/* Wait for 5ms */
usleep_range(5000, 5500);
@@ -1773,7 +1776,7 @@
ctrl |= SDHCI_CTRL_VDD_180;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_IO_LOW);
/* Wait for 5ms */
usleep_range(5000, 5500);
@@ -1807,14 +1810,14 @@
pwr &= ~SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_OFF);
/* Wait for 1ms as per the spec */
usleep_range(1000, 1500);
pwr |= SDHCI_POWER_ON;
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
if (host->ops->check_power_status)
- host->ops->check_power_status(host);
+ host->ops->check_power_status(host, REQ_BUS_ON);
pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
"voltage failed, retrying with S18R set to 0\n");
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 49d7957..c6bef8a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -277,7 +277,11 @@
void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
- void (*check_power_status)(struct sdhci_host *host);
+ void (*check_power_status)(struct sdhci_host *host, u32 req_type);
+#define REQ_BUS_OFF (1 << 0)
+#define REQ_BUS_ON (1 << 1)
+#define REQ_IO_LOW (1 << 2)
+#define REQ_IO_HIGH (1 << 3)
int (*execute_tuning)(struct sdhci_host *host, u32 opcode);
void (*toggle_cdr)(struct sdhci_host *host, bool enable);
unsigned int (*get_max_segments)(void);
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index f7e8c9f..c37a4a4 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2264,19 +2264,22 @@
*/
bam.manage = SPS_BAM_MGR_DEVICE_REMOTE | SPS_BAM_MGR_MULTI_EE;
+ rc = sps_phy2h(bam.phys_addr, &nand_info->sps.bam_handle);
+ if (!rc)
+ goto init_sps_ep;
rc = sps_register_bam_device(&bam, &nand_info->sps.bam_handle);
if (rc) {
- pr_err("sps_register_bam_device() failed with %d\n", rc);
+ pr_err("%s: sps_register_bam_device() failed with %d\n",
+ __func__, rc);
goto out;
}
- pr_info("BAM device registered: bam_handle 0x%x\n",
- nand_info->sps.bam_handle);
-
+ pr_info("%s: BAM device registered: bam_handle 0x%x\n",
+ __func__, nand_info->sps.bam_handle);
+init_sps_ep:
rc = msm_nand_init_endpoint(nand_info, &nand_info->sps.data_prod,
SPS_DATA_PROD_PIPE_INDEX);
if (rc)
- goto unregister_bam;
-
+ goto out;
rc = msm_nand_init_endpoint(nand_info, &nand_info->sps.data_cons,
SPS_DATA_CONS_PIPE_INDEX);
if (rc)
@@ -2291,22 +2294,20 @@
msm_nand_deinit_endpoint(nand_info, &nand_info->sps.data_cons);
deinit_data_prod:
msm_nand_deinit_endpoint(nand_info, &nand_info->sps.data_prod);
-unregister_bam:
- sps_deregister_bam_device(nand_info->sps.bam_handle);
out:
return rc;
}
/*
- * This function de-registers BAM device, disconnects and frees its end points
- * for all the pipes.
+ * This function disconnects and frees its end points for all the pipes.
+ * Since the BAM is shared resource, it is not deregistered as its handle
+ * might be in use with LCDC.
*/
static void msm_nand_bam_free(struct msm_nand_info *nand_info)
{
msm_nand_deinit_endpoint(nand_info, &nand_info->sps.data_prod);
msm_nand_deinit_endpoint(nand_info, &nand_info->sps.data_cons);
msm_nand_deinit_endpoint(nand_info, &nand_info->sps.cmd_pipe);
- sps_deregister_bam_device(nand_info->sps.bam_handle);
}
/* This function enables DMA support for the NANDc in BAM mode. */
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index 41dd6e7..ed67df4 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -22,7 +22,7 @@
#include <mach/ecm_ipa.h>
#define DRIVER_NAME "ecm_ipa"
-#define DRIVER_VERSION "12-Mar-2013"
+#define DRIVER_VERSION "20-Mar-2013"
#define ECM_IPA_IPV4_HDR_NAME "ecm_eth_ipv4"
#define ECM_IPA_IPV6_HDR_NAME "ecm_eth_ipv6"
#define IPA_TO_USB_CLIENT IPA_CLIENT_USB_CONS
@@ -30,13 +30,6 @@
#define ECM_IPA_ERROR(fmt, args...) \
pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\
fmt, __func__, __LINE__, current->comm, ## args)
-#ifdef ECM_IPA_DEBUG_ON
-#define ECM_IPA_DEBUG(fmt, args...) \
- pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\
- fmt, __func__, __LINE__, current->comm, ## args)
-#else /* ECM_IPA_DEBUG_ON */
-#define ECM_IPA_DEBUG(fmt, args...)
-#endif /* ECM_IPA_DEBUG_ON */
#define NULL_CHECK(ptr) \
do { \
@@ -47,8 +40,8 @@
} \
while (0)
-#define ECM_IPA_LOG_ENTRY() ECM_IPA_DEBUG("begin\n")
-#define ECM_IPA_LOG_EXIT() ECM_IPA_DEBUG("end\n")
+#define ECM_IPA_LOG_ENTRY() pr_debug("begin\n")
+#define ECM_IPA_LOG_EXIT() pr_debug("end\n")
/**
* struct ecm_ipa_dev - main driver context parameters
@@ -192,7 +185,7 @@
struct net_device *net;
struct ecm_ipa_dev *dev;
ECM_IPA_LOG_ENTRY();
- ECM_IPA_DEBUG("%s version %s\n", DRIVER_NAME, DRIVER_VERSION);
+ pr_debug("%s version %s\n", DRIVER_NAME, DRIVER_VERSION);
NULL_CHECK(ecm_ipa_rx_dp_notify);
NULL_CHECK(ecm_ipa_tx_dp_notify);
NULL_CHECK(priv);
@@ -202,7 +195,7 @@
ECM_IPA_ERROR("fail to allocate etherdev\n");
goto fail_alloc_etherdev;
}
- ECM_IPA_DEBUG("etherdev was successfully allocated\n");
+ pr_debug("etherdev was successfully allocated\n");
dev = netdev_priv(net);
memset(dev, 0, sizeof(*dev));
dev->tx_enable = true;
@@ -213,11 +206,11 @@
*priv = (void *)dev;
snprintf(net->name, sizeof(net->name), "%s%%d", "ecm");
net->netdev_ops = &ecm_ipa_netdev_ops;
- ECM_IPA_DEBUG("internal data structures were intialized\n");
+ pr_debug("internal data structures were intialized\n");
ret = ecm_ipa_debugfs_init(dev);
if (ret)
goto fail_debugfs;
- ECM_IPA_DEBUG("debugfs entries were created\n");
+ pr_debug("debugfs entries were created\n");
*ecm_ipa_rx_dp_notify = ecm_ipa_packet_receive_notify;
*ecm_ipa_tx_dp_notify = ecm_ipa_tx_complete_notify;
ECM_IPA_LOG_EXIT();
@@ -382,7 +375,7 @@
ECM_IPA_LOG_ENTRY();
result = ipa_deregister_intf("ecm0");
if (result)
- ECM_IPA_DEBUG("Fail on Tx prop deregister\n");
+ pr_debug("Fail on Tx prop deregister\n");
ECM_IPA_LOG_EXIT();
return;
}
@@ -415,14 +408,14 @@
NULL_CHECK(dev);
net = dev->net;
NULL_CHECK(net);
- ECM_IPA_DEBUG("host_ethaddr=%pM device_ethaddr=%pM\n",
+ pr_debug("host_ethaddr=%pM device_ethaddr=%pM\n",
host_ethaddr, device_ethaddr);
result = ecm_ipa_create_rm_resource(dev);
if (result) {
ECM_IPA_ERROR("fail on RM create\n");
return -EINVAL;
}
- ECM_IPA_DEBUG("RM resource was created\n");
+ pr_debug("RM resource was created\n");
netif_carrier_off(dev->net);
result = ecm_ipa_set_device_ethernet_addr(net->dev_addr,
device_ethaddr);
@@ -435,19 +428,19 @@
ECM_IPA_ERROR("fail on ipa rules set\n");
goto fail_set_device_ethernet;
}
- ECM_IPA_DEBUG("Ethernet header insertion was set\n");
+ pr_debug("Ethernet header insertion was set\n");
result = ecm_ipa_register_properties();
if (result) {
ECM_IPA_ERROR("fail on properties set\n");
goto fail_register_tx;
}
- ECM_IPA_DEBUG("ECM 2 Tx and 2 Rx properties were registered\n");
+ pr_debug("ECM 2 Tx and 2 Rx properties were registered\n");
result = register_netdev(net);
if (result) {
ECM_IPA_ERROR("register_netdev failed: %d\n", result);
goto fail_register_netdev;
}
- ECM_IPA_DEBUG("register_netdev succeeded\n");
+ pr_debug("register_netdev succeeded\n");
ECM_IPA_LOG_EXIT();
return 0;
fail_register_netdev:
@@ -467,7 +460,7 @@
struct ecm_ipa_dev *dev = priv;
ECM_IPA_LOG_ENTRY();
NULL_CHECK(priv);
- ECM_IPA_DEBUG("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d\n",
+ pr_debug("usb_to_ipa_hdl = %d, ipa_to_usb_hdl = %d\n",
usb_to_ipa_hdl, ipa_to_usb_hdl);
if (!usb_to_ipa_hdl || usb_to_ipa_hdl >= IPA_CLIENT_MAX) {
ECM_IPA_ERROR("usb_to_ipa_hdl(%d) is not a valid ipa handle\n",
@@ -511,10 +504,10 @@
ECM_IPA_LOG_ENTRY();
if (event == IPA_RM_RESOURCE_GRANTED &&
netif_queue_stopped(dev->net)) {
- ECM_IPA_DEBUG("Resource Granted - waking queue\n");
+ pr_debug("Resource Granted - waking queue\n");
netif_wake_queue(dev->net);
} else {
- ECM_IPA_DEBUG("Resource released\n");
+ pr_debug("Resource released\n");
}
ECM_IPA_LOG_EXIT();
}
@@ -532,7 +525,7 @@
ECM_IPA_ERROR("Fail on ipa_rm_create_resource\n");
goto fail_rm_create;
}
- ECM_IPA_DEBUG("rm client was created");
+ pr_debug("rm client was created");
result = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_STD_ECM_PROD,
INACTIVITY_MSEC_DELAY);
@@ -540,14 +533,14 @@
ECM_IPA_ERROR("Fail on ipa_rm_inactivity_timer_init\n");
goto fail_it;
}
- ECM_IPA_DEBUG("rm_it client was created");
+ pr_debug("rm_it client was created");
result = ipa_rm_add_dependency(IPA_RM_RESOURCE_STD_ECM_PROD,
IPA_RM_RESOURCE_USB_CONS);
if (result)
ECM_IPA_ERROR("unable to add dependency (%d)\n", result);
- ECM_IPA_DEBUG("rm dependency was set\n");
+ pr_debug("rm dependency was set\n");
ECM_IPA_LOG_EXIT();
return 0;
@@ -596,7 +589,7 @@
static int ecm_ipa_stop(struct net_device *net)
{
ECM_IPA_LOG_ENTRY();
- ECM_IPA_DEBUG("stopping net device\n");
+ pr_debug("stopping net device\n");
netif_stop_queue(net);
ECM_IPA_LOG_EXIT();
return 0;
@@ -624,7 +617,7 @@
unregister_netdev(dev->net);
free_netdev(dev->net);
}
- ECM_IPA_DEBUG("cleanup done\n");
+ pr_debug("cleanup done\n");
ecm_ipa_ctx = NULL;
ECM_IPA_LOG_EXIT();
return ;
@@ -678,20 +671,20 @@
if (unlikely(tx_filter(skb))) {
dev_kfree_skb_any(skb);
- ECM_IPA_DEBUG("packet got filtered out on Tx path\n");
+ pr_debug("packet got filtered out on Tx path\n");
status = NETDEV_TX_OK;
goto out;
}
ret = resource_request(dev);
if (ret) {
- ECM_IPA_DEBUG("Waiting to resource\n");
+ pr_debug("Waiting to resource\n");
netif_stop_queue(net);
goto resource_busy;
}
spin_lock_irqsave(&dev->ack_spinlock, flags);
if (dev->last_out_skb) {
- ECM_IPA_DEBUG("No Tx-ack received for previous packet\n");
+ pr_debug("No Tx-ack received for previous packet\n");
spin_unlock_irqrestore(&dev->ack_spinlock, flags);
netif_stop_queue(net);
status = -NETDEV_TX_BUSY;
@@ -743,7 +736,7 @@
skb->dev = dev->net;
skb->protocol = eth_type_trans(skb, dev->net);
if (rx_filter(skb)) {
- ECM_IPA_DEBUG("packet got filtered out on Rx path\n");
+ pr_debug("packet got filtered out on Rx path\n");
dev_kfree_skb_any(skb);
return;
}
@@ -789,7 +782,7 @@
dev->last_out_skb = NULL;
spin_unlock_irqrestore(&dev->ack_spinlock, flags);
if (netif_queue_stopped(dev->net)) {
- ECM_IPA_DEBUG("waking up queue\n");
+ pr_debug("waking up queue\n");
netif_wake_queue(dev->net);
}
dev_kfree_skb_any(skb);
@@ -866,9 +859,9 @@
missing = copy_from_user(&input, buf, 1);
if (missing)
return -EFAULT;
- ECM_IPA_DEBUG("input received %c\n", input);
+ pr_debug("input received %c\n", input);
*enable = input - '0';
- ECM_IPA_DEBUG("value was set to %d\n", *enable);
+ pr_debug("value was set to %d\n", *enable);
return count;
}
@@ -1001,7 +994,7 @@
ECM_IPA_ERROR("failed to configure IPA to USB end-point\n");
goto out;
}
- ECM_IPA_DEBUG("end-point registers successfully configured\n");
+ pr_debug("end-point registers successfully configured\n");
out:
ECM_IPA_LOG_EXIT();
return result;
@@ -1040,7 +1033,7 @@
ECM_IPA_ERROR("failed to configure USB to IPA\n");
goto out;
}
- ECM_IPA_DEBUG("end-point registers successfully configured\n");
+ pr_debug("end-point registers successfully configured\n");
out:
ECM_IPA_LOG_EXIT();
return result;
@@ -1057,7 +1050,7 @@
if (!is_valid_ether_addr(device_ethaddr))
return -EINVAL;
memcpy(dev_ethaddr, device_ethaddr, ETH_ALEN);
- ECM_IPA_DEBUG("device ethernet address: %pM\n", dev_ethaddr);
+ pr_debug("device ethernet address: %pM\n", dev_ethaddr);
return 0;
}
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index 0aa9677..7e6cd4f 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -28,8 +28,6 @@
static void __iomem *msm_wcnss_base;
-static struct msm_xo_voter *wlan_clock;
-static const char *id = "WLAN";
static LIST_HEAD(power_on_lock_list);
static DEFINE_MUTEX(list_lock);
static DEFINE_SEMAPHORE(wcnss_power_on_lock);
@@ -93,7 +91,7 @@
{"qcom,iris-vddpa", VREG_NULL_CONFIG, 2900000, 0,
3000000, 515000, NULL},
{"qcom,iris-vdddig", VREG_NULL_CONFIG, 1225000, 0,
- 1225000, 10000, NULL},
+ 1300000, 10000, NULL},
};
/* WCNSS regulators for Pronto hardware */
@@ -124,6 +122,7 @@
void __iomem *pmu_conf_reg;
void __iomem *spare_reg;
struct clk *clk;
+ struct clk *clk_rf = NULL;
if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
wcnss_phys_addr = MSM_PRONTO_PHYS;
@@ -136,6 +135,15 @@
pr_err("Couldn't get xo clock\n");
return PTR_ERR(clk);
}
+
+ if (!use_48mhz_xo) {
+ clk_rf = clk_get(dev, "rf_clk");
+ if (IS_ERR(clk_rf)) {
+ pr_err("Couldn't get rf_clk\n");
+ clk_put(clk);
+ return PTR_ERR(clk_rf);
+ }
+ }
} else {
wcnss_phys_addr = MSM_RIVA_PHYS;
pmu_offset = RIVA_PMU_OFFSET;
@@ -162,6 +170,7 @@
pr_err("clk enable failed\n");
goto fail;
}
+
/* NV bit is set to indicate that platform driver is capable
* of doing NV download. SSR should not set NV bit; during
* SSR NV bin is downloaded by WLAN driver.
@@ -205,40 +214,28 @@
clk_disable_unprepare(clk);
if (!use_48mhz_xo) {
- wlan_clock = msm_xo_get(MSM_XO_TCXO_A2, id);
- if (IS_ERR(wlan_clock)) {
- rc = PTR_ERR(wlan_clock);
- pr_err("Failed to get MSM_XO_TCXO_A2 voter (%d)\n",
- rc);
+ rc = clk_prepare_enable(clk_rf);
+ if (rc) {
+ pr_err("clk_rf enable failed\n");
goto fail;
}
-
- rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_ON);
- if (rc < 0) {
- pr_err("Configuring MSM_XO_MODE_ON failed (%d)\n",
- rc);
- goto msm_xo_vote_fail;
- }
}
- } else {
- if (wlan_clock != NULL && !use_48mhz_xo) {
- rc = msm_xo_mode_vote(wlan_clock, MSM_XO_MODE_OFF);
- if (rc < 0)
- pr_err("Configuring MSM_XO_MODE_OFF failed (%d)\n",
- rc);
- }
- }
-
+ } else if (clk_rf != NULL && !use_48mhz_xo)
+ clk_disable_unprepare(clk_rf);
/* Add some delay for XO to settle */
msleep(20);
clk_put(clk);
+
+ if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
+ if (!use_48mhz_xo)
+ clk_put(clk_rf);
+ }
+
return rc;
-
-msm_xo_vote_fail:
- msm_xo_put(wlan_clock);
-
fail:
+ if (clk_rf != NULL)
+ clk_put(clk_rf);
clk_put(clk);
return rc;
}
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index ee76304..0158235 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -48,6 +48,10 @@
module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
+static int do_not_cancel_vote = WCNSS_CONFIG_UNSPECIFIED;
+module_param(do_not_cancel_vote, int, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(do_not_cancel_vote, "Do not cancel votes for wcnss");
+
static DEFINE_SPINLOCK(reg_spinlock);
#define MSM_RIVA_PHYS 0x03204000
@@ -87,6 +91,9 @@
#define CCU_PRONTO_LAST_ADDR1_OFFSET 0x10
#define CCU_PRONTO_LAST_ADDR2_OFFSET 0x14
+#define MSM_PRONTO_CCPU_CTL_BASE 0xfb21d000
+#define BOOT_REMAP_OFFSET 0x04
+
#define WCNSS_CTRL_CHANNEL "WCNSS_CTRL"
#define WCNSS_MAX_FRAME_SIZE 500
#define WCNSS_VERSION_LEN 30
@@ -193,6 +200,7 @@
void __iomem *riva_ccu_base;
void __iomem *pronto_a2xb_base;
void __iomem *pronto_ccpu_base;
+ void __iomem *pronto_ctl_base;
} *penv = NULL;
static ssize_t wcnss_serial_number_show(struct device *dev,
@@ -326,6 +334,10 @@
reg = readl_relaxed(reg_addr);
pr_info_ratelimited("%s: CCU_CCPU_LAST_ADDR2 %08x\n", __func__, reg);
+ reg_addr = penv->pronto_ctl_base + BOOT_REMAP_OFFSET;
+ reg = readl_relaxed(reg_addr);
+ pr_info_ratelimited("%s: BOOT_REMAP_ADDR %08x\n", __func__, reg);
+
tst_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_OFFSET;
tst_ctrl_addr = penv->pronto_a2xb_base + A2XB_TSTBUS_CTRL_OFFSET;
@@ -396,12 +408,13 @@
{
if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
wcnss_pronto_log_debug_regs();
- pr_err("%s: reset interrupt not supported\n", __func__);
- return;
+ wmb();
+ __raw_writel(1 << 16, MSM_APCS_GCC_BASE + 0x8);
+ } else {
+ wcnss_riva_log_debug_regs();
+ wmb();
+ __raw_writel(1 << 24, MSM_APCS_GCC_BASE + 0x8);
}
- wcnss_riva_log_debug_regs();
- wmb();
- __raw_writel(1 << 24, MSM_APCS_GCC_BASE + 0x8);
}
EXPORT_SYMBOL(wcnss_reset_intr);
@@ -477,6 +490,11 @@
static void wcnss_post_bootup(struct work_struct *work)
{
+ if (do_not_cancel_vote == 1) {
+ pr_info("%s: Keeping APPS vote for Iris & WCNSS\n", __func__);
+ return;
+ }
+
pr_info("%s: Cancel APPS vote for Iris & WCNSS\n", __func__);
/* Since WCNSS is up, cancel any APPS vote for Iris & WCNSS VREGs */
@@ -1173,11 +1191,20 @@
pr_err("%s: ioremap wcnss physical failed\n", __func__);
goto fail_ioremap2;
}
+ penv->pronto_ctl_base = ioremap(MSM_PRONTO_CCPU_CTL_BASE,
+ SZ_32);
+ if (!penv->pronto_ctl_base) {
+ ret = -ENOMEM;
+ pr_err("%s: ioremap wcnss physical failed\n", __func__);
+ goto fail_ioremap3;
+ }
}
penv->cold_boot_done = 1;
return 0;
+fail_ioremap3:
+ iounmap(penv->pronto_ccpu_base);
fail_ioremap2:
iounmap(penv->pronto_a2xb_base);
fail_ioremap:
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 42a0016..db7f7f0 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -119,7 +119,7 @@
module_param(ip4_rt_tbl_lcl, bool, 0644);
MODULE_PARM_DESC(ip4_rt_tbl_lcl,
"where ip4 rt tables reside 1-local; 0-system");
-static bool ip6_rt_tbl_lcl = 1;
+static bool ip6_rt_tbl_lcl;
module_param(ip6_rt_tbl_lcl, bool, 0644);
MODULE_PARM_DESC(ip6_rt_tbl_lcl,
"where ip6 rt tables reside 1-local; 0-system");
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index 0227ee4..eeb98e9 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -43,6 +43,7 @@
struct sps_mem_buffer desc_mem_buf;
struct sps_register_event register_event;
struct list_head free_desc_list;
+ bool valid;
};
struct ipa_bridge_context {
@@ -465,6 +466,7 @@
}
*clnt_hdl = ipa_ep_idx;
+ sys->valid = true;
return 0;
@@ -620,6 +622,8 @@
}
}
+ sys->valid = true;
+
return 0;
event_reg_failed:
@@ -809,12 +813,15 @@
for (; lo <= hi; lo++) {
sys = &bridge[type].pipe[lo];
- sps_disconnect(sys->pipe);
- dma_free_coherent(NULL, sys->desc_mem_buf.size,
- sys->desc_mem_buf.base,
- sys->desc_mem_buf.phys_base);
- sps_free_endpoint(sys->pipe);
- ipa_bridge_free_resources(sys);
+ if (sys->valid) {
+ sps_disconnect(sys->pipe);
+ dma_free_coherent(NULL, sys->desc_mem_buf.size,
+ sys->desc_mem_buf.base,
+ sys->desc_mem_buf.phys_base);
+ sps_free_endpoint(sys->pipe);
+ ipa_bridge_free_resources(sys);
+ sys->valid = false;
+ }
}
memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index b57585c..a4b7e22 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -33,56 +33,17 @@
static int ipa_disable_data_path(u32 clnt_hdl)
{
- DECLARE_COMPLETION_ONSTACK(tag_rsp);
- struct ipa_desc desc = {0};
- struct ipa_ip_packet_tag cmd;
struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
- struct ipa_tree_node *node;
- int result = 0;
if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
return 0;
}
- node = kmem_cache_zalloc(ipa_ctx->tree_node_cache, GFP_KERNEL);
- if (!node) {
- IPAERR("failed to alloc tree node object\n");
- result = -ENOMEM;
- goto fail_alloc;
- }
-
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
- cmd.tag = (u32) &tag_rsp;
-
- desc.pyld = &cmd;
- desc.len = sizeof(struct ipa_ip_packet_tag);
- desc.type = IPA_IMM_CMD_DESC;
- desc.opcode = IPA_IP_PACKET_TAG;
-
- IPADBG("Wait on TAG %p clnt=%d\n", &tag_rsp, clnt_hdl);
-
- node->hdl = cmd.tag;
- mutex_lock(&ipa_ctx->lock);
- if (ipa_insert(&ipa_ctx->tag_tree, node)) {
- IPAERR("failed to add to tree\n");
- result = -EINVAL;
- mutex_unlock(&ipa_ctx->lock);
- goto fail_insert;
- }
- mutex_unlock(&ipa_ctx->lock);
-
- if (ipa_send_cmd(1, &desc)) {
- ipa_write_reg(ipa_ctx->mmio,
- IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
- IPAERR("fail to send TAG command\n");
- result = -EPERM;
- goto fail_send;
- }
- wait_for_completion(&tag_rsp);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
@@ -91,13 +52,6 @@
}
return 0;
-
-fail_send:
- rb_erase(&node->node, &ipa_ctx->tag_tree);
-fail_insert:
- kmem_cache_free(ipa_ctx->tree_node_cache, node);
-fail_alloc:
- return result;
}
static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -310,6 +264,8 @@
IPA_HOLB_TMR_VAL);
}
+ IPADBG("client %d (ep: %d) connected\n", in->client, ipa_ep_idx);
+
return 0;
sps_connect_fail:
@@ -345,6 +301,7 @@
return result;
}
EXPORT_SYMBOL(ipa_connect);
+
/**
* ipa_disconnect() - low-level IPA client disconnect
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
@@ -420,6 +377,8 @@
ipa_disable_clks();
}
+ IPADBG("client (ep: %d) disconnected\n", clnt_hdl);
+
return 0;
}
EXPORT_SYMBOL(ipa_disconnect);
diff --git a/drivers/platform/msm/ipa/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_debugfs.c
index 1605ed2..51a950d 100644
--- a/drivers/platform/msm/ipa/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_debugfs.c
@@ -18,6 +18,8 @@
#define IPA_MAX_MSG_LEN 4096
+#define IPA_DBG_CNTR_ON 127265
+#define IPA_DBG_CNTR_OFF 127264
const char *ipa_client_name[] = {
__stringify(IPA_CLIENT_HSIC1_PROD),
@@ -76,6 +78,19 @@
__stringify_1(IPA_A5_MUX_HDR_EXCP_FLAG_IP),
};
+const char *ipa_event_name[] = {
+ __stringify(WLAN_CLIENT_CONNECT),
+ __stringify(WLAN_CLIENT_DISCONNECT),
+ __stringify(WLAN_CLIENT_POWER_SAVE_MODE),
+ __stringify(WLAN_CLIENT_NORMAL_MODE),
+ __stringify(SW_ROUTING_ENABLE),
+ __stringify(SW_ROUTING_DISABLE),
+ __stringify(WLAN_AP_CONNECT),
+ __stringify(WLAN_AP_DISCONNECT),
+ __stringify(WLAN_STA_CONNECT),
+ __stringify(WLAN_STA_DISCONNECT),
+};
+
static struct dentry *dent;
static struct dentry *dfile_gen_reg;
static struct dentry *dfile_ep_reg;
@@ -85,6 +100,8 @@
static struct dentry *dfile_ip4_flt;
static struct dentry *dfile_ip6_flt;
static struct dentry *dfile_stats;
+static struct dentry *dfile_dbg_cnt;
+static struct dentry *dfile_msg;
static char dbg_buff[IPA_MAX_MSG_LEN];
static s8 ep_reg_idx;
@@ -199,7 +216,10 @@
"IPA_ENDP_INIT_HDR_%u=0x%x\n"
"IPA_ENDP_INIT_MODE_%u=0x%x\n"
"IPA_ENDP_INIT_AGGR_%u=0x%x\n"
- "IPA_ENDP_INIT_ROUTE_%u=0x%x\n",
+ "IPA_ENDP_INIT_ROUTE_%u=0x%x\n"
+ "IPA_ENDP_INIT_CTRL_%u=0x%x\n"
+ "IPA_ENDP_INIT_HOL_EN_%u=0x%x\n"
+ "IPA_ENDP_INIT_HOL_TIMER_%u=0x%x\n",
i, ipa_read_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_NAT_n_OFST_v2(i)),
i, ipa_read_reg(ipa_ctx->mmio,
@@ -209,7 +229,14 @@
i, ipa_read_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_AGGR_n_OFST_v2(i)),
i, ipa_read_reg(ipa_ctx->mmio,
- IPA_ENDP_INIT_ROUTE_n_OFST_v2(i)));
+ IPA_ENDP_INIT_ROUTE_n_OFST_v2(i)),
+ i, ipa_read_reg(ipa_ctx->mmio,
+ IPA_ENDP_INIT_CTRL_n_OFST(i)),
+ i, ipa_read_reg(ipa_ctx->mmio,
+ IPA_ENDP_INIT_HOL_BLOCK_EN_n_OFST(i)),
+ i, ipa_read_reg(ipa_ctx->mmio,
+ IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_OFST(i))
+ );
}
*ppos = pos;
@@ -516,6 +543,10 @@
int nbytes;
int i;
int cnt = 0;
+ uint connect = 0;
+
+ for (i = 0; i < IPA_NUM_PIPES; i++)
+ connect |= (ipa_ctx->ep[i].valid << i);
nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
"sw_tx=%u\n"
@@ -523,13 +554,17 @@
"rx=%u\n"
"rx_repl_repost=%u\n"
"x_intr_repost=%u\n"
- "rx_q_len=%u\n",
+ "rx_q_len=%u\n"
+ "act_clnt=%u\n"
+ "con_clnt_bmap=0x%x\n",
ipa_ctx->stats.tx_sw_pkts,
ipa_ctx->stats.tx_hw_pkts,
ipa_ctx->stats.rx_pkts,
ipa_ctx->stats.rx_repl_repost,
ipa_ctx->stats.x_intr_repost,
- ipa_ctx->stats.rx_q_len);
+ ipa_ctx->stats.rx_q_len,
+ atomic_read(&ipa_ctx->ipa_active_clients),
+ connect);
cnt += nbytes;
for (i = 0; i < MAX_NUM_EXCP; i++) {
@@ -560,6 +595,64 @@
return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
}
+static ssize_t ipa_write_dbg_cnt(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long missing;
+ u32 option = 0;
+
+ if (sizeof(dbg_buff) < count + 1)
+ return -EFAULT;
+
+ missing = copy_from_user(dbg_buff, buf, count);
+ if (missing)
+ return -EFAULT;
+
+ dbg_buff[count] = '\0';
+ if (kstrtou32(dbg_buff, 0, &option))
+ return -EFAULT;
+
+ if (option == 1)
+ ipa_write_reg(ipa_ctx->mmio, IPA_DEBUG_CNT_CTRL_n_OFST(0),
+ IPA_DBG_CNTR_ON);
+ else
+ ipa_write_reg(ipa_ctx->mmio, IPA_DEBUG_CNT_CTRL_n_OFST(0),
+ IPA_DBG_CNTR_OFF);
+
+ return count;
+}
+
+static ssize_t ipa_read_dbg_cnt(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ int nbytes;
+
+ nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
+ "IPA_DEBUG_CNT_REG_0=0x%x\n",
+ ipa_read_reg(ipa_ctx->mmio,
+ IPA_DEBUG_CNT_REG_n_OFST(0)));
+
+ return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t ipa_read_msg(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ int nbytes;
+ int cnt = 0;
+ int i;
+
+ for (i = 0; i < IPA_EVENT_MAX; i++) {
+ nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt,
+ "msg[%u:%27s] W:%u R:%u\n", i,
+ ipa_event_name[i],
+ ipa_ctx->stats.msg_w[i],
+ ipa_ctx->stats.msg_r[i]);
+ cnt += nbytes;
+ }
+
+ return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
+}
const struct file_operations ipa_gen_reg_ops = {
.read = ipa_read_gen_reg,
@@ -588,6 +681,15 @@
.read = ipa_read_stats,
};
+const struct file_operations ipa_msg_ops = {
+ .read = ipa_read_msg,
+};
+
+const struct file_operations ipa_dbg_cnt_ops = {
+ .read = ipa_read_dbg_cnt,
+ .write = ipa_write_dbg_cnt,
+};
+
void ipa_debugfs_init(void)
{
const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -656,6 +758,20 @@
goto fail;
}
+ dfile_dbg_cnt = debugfs_create_file("dbg_cnt", read_write_mode, dent, 0,
+ &ipa_dbg_cnt_ops);
+ if (!dfile_dbg_cnt || IS_ERR(dfile_dbg_cnt)) {
+ IPAERR("fail to create file for debug_fs dbg_cnt\n");
+ goto fail;
+ }
+
+ dfile_msg = debugfs_create_file("msg", read_only_mode, dent, 0,
+ &ipa_msg_ops);
+ if (!dfile_msg || IS_ERR(dfile_msg)) {
+ IPAERR("fail to create file for debug_fs msg\n");
+ goto fail;
+ }
+
return;
fail:
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 971cf5e..bd1da2c 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -528,8 +528,6 @@
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
struct ipa_ep_context *ep;
int cnt = 0;
- struct completion *compl;
- struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
@@ -584,35 +582,6 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
- if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
- if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
- /* retrieve the compl object from tag value */
- mux_hdr++;
- compl = (struct completion *)
- ntohl(*((u32 *)mux_hdr));
- IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
- *((u32 *)mux_hdr + 1), compl);
-
- mutex_lock(&ipa_ctx->lock);
- node = ipa_search(&ipa_ctx->tag_tree,
- (u32)compl);
- if (node) {
- complete_all(compl);
- rb_erase(&node->node,
- &ipa_ctx->tag_tree);
- kmem_cache_free(
- ipa_ctx->tree_node_cache, node);
- } else {
- WARN_ON(1);
- }
- mutex_unlock(&ipa_ctx->lock);
- }
- dev_kfree_skb(rx_skb);
- ipa_replenish_rx_cache();
- ++cnt;
- continue;
- }
-
/*
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
@@ -900,6 +869,8 @@
*clnt_hdl = ipa_ep_idx;
+ IPADBG("client %d (ep: %d) connected\n", sys_in->client, ipa_ep_idx);
+
return 0;
fail_register_event:
@@ -936,6 +907,9 @@
ipa_ctx->ep[clnt_hdl].connect.desc.phys_base);
sps_free_endpoint(ipa_ctx->ep[clnt_hdl].ep_hdl);
memset(&ipa_ctx->ep[clnt_hdl], 0, sizeof(struct ipa_ep_context));
+
+ IPADBG("client (ep: %d) disconnected\n", clnt_hdl);
+
return 0;
}
EXPORT_SYMBOL(ipa_teardown_sys_pipe);
diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c
index 0439a69..7d0bc24 100644
--- a/drivers/platform/msm/ipa/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_hdr.c
@@ -221,6 +221,8 @@
WARN_ON(1);
}
+ entry->ref_cnt++;
+
return 0;
ofst_alloc_fail:
@@ -246,7 +248,7 @@
return -EINVAL;
}
- if (!entry || (entry->cookie != IPA_COOKIE) || (entry->ref_cnt != 0)) {
+ if (!entry || (entry->cookie != IPA_COOKIE)) {
IPAERR("bad parm\n");
return -EINVAL;
}
@@ -254,6 +256,11 @@
IPADBG("del hdr of sz=%d hdr_cnt=%d ofst=%d\n", entry->hdr_len,
htbl->hdr_cnt, entry->offset_entry->offset);
+ if (--entry->ref_cnt) {
+ IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt);
+ return 0;
+ }
+
/* move the offset entry to appropriate free list */
list_move(&entry->offset_entry->link,
&htbl->head_free_offset_list[entry->offset_entry->bin]);
@@ -502,8 +509,7 @@
* ipa_get_hdr() - Lookup the specified header resource
* @lookup: [inout] header to lookup and its handle
*
- * lookup the specified header resource and return handle if it exists, if
- * lookup succeeds the header entry ref cnt is increased
+ * lookup the specified header resource and return handle if it exists
*
* Returns: 0 on success, negative on failure
*
@@ -522,7 +528,6 @@
mutex_lock(&ipa_ctx->lock);
entry = __ipa_find_hdr(lookup->name);
if (entry) {
- entry->ref_cnt++;
lookup->hdl = (uint32_t) entry;
result = 0;
}
@@ -533,6 +538,34 @@
EXPORT_SYMBOL(ipa_get_hdr);
/**
+ * __ipa_release_hdr() - drop reference to header and cause
+ * deletion if reference count permits
+ * @hdr_hdl: [in] handle of header to be released
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int __ipa_release_hdr(u32 hdr_hdl)
+{
+ int result = 0;
+
+ if (__ipa_del_hdr(hdr_hdl)) {
+ IPADBG("fail to del hdr %x\n", hdr_hdl);
+ result = -EFAULT;
+ goto bail;
+ }
+
+ /* commit for put */
+ if (__ipa_commit_hdr()) {
+ IPAERR("fail to commit hdr\n");
+ result = -EFAULT;
+ goto bail;
+ }
+
+bail:
+ return result;
+}
+
+/**
* ipa_put_hdr() - Release the specified header handle
* @hdr_hdl: [in] the header handle to release
*
@@ -554,27 +587,12 @@
goto bail;
}
- if (entry == NULL || entry->cookie != IPA_COOKIE ||
- entry->ref_cnt == 0) {
+ if (entry == NULL || entry->cookie != IPA_COOKIE) {
IPAERR("bad params\n");
result = -EINVAL;
goto bail;
}
- entry->ref_cnt--;
- if (entry->ref_cnt == 0) {
- if (__ipa_del_hdr(hdr_hdl)) {
- IPAERR("fail to del hdr\n");
- result = -EFAULT;
- goto bail;
- }
- /* commit for put */
- if (__ipa_commit_hdr()) {
- IPAERR("fail to commit hdr\n");
- result = -EFAULT;
- goto bail;
- }
- }
result = 0;
bail:
mutex_unlock(&ipa_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index 45f7b09..ca5740d 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -529,6 +529,8 @@
u32 rx_repl_repost;
u32 x_intr_repost;
u32 rx_q_len;
+ u32 msg_w[IPA_EVENT_MAX];
+ u32 msg_r[IPA_EVENT_MAX];
};
/**
@@ -795,6 +797,7 @@
void ipa_disable_clks(void);
int __ipa_del_rt_rule(u32 rule_hdl);
int __ipa_del_hdr(u32 hdr_hdl);
+int __ipa_release_hdr(u32 hdr_hdl);
static inline u32 ipa_read_reg(void *base, u32 offset)
{
diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c
index 9876650..0f41d2c 100644
--- a/drivers/platform/msm/ipa/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_intf.c
@@ -268,6 +268,11 @@
return -EINVAL;
}
+ if (meta->msg_type >= IPA_EVENT_MAX) {
+ IPAERR("unsupported message type %d\n", meta->msg_type);
+ return -EINVAL;
+ }
+
msg = kzalloc(sizeof(struct ipa_push_msg), GFP_KERNEL);
if (msg == NULL) {
IPAERR("fail to alloc ipa_msg container\n");
@@ -281,6 +286,7 @@
mutex_lock(&ipa_ctx->msg_lock);
list_add_tail(&msg->link, &ipa_ctx->msg_list);
mutex_unlock(&ipa_ctx->msg_lock);
+ IPA_STATS_INC_CNT(ipa_ctx->stats.msg_w[meta->msg_type]);
wake_up(&ipa_ctx->msg_waitq);
@@ -424,6 +430,8 @@
msg->callback(msg->buff, msg->meta.msg_len,
msg->meta.msg_type);
}
+ IPA_STATS_INC_CNT(
+ ipa_ctx->stats.msg_r[msg->meta.msg_type]);
}
ret = -EAGAIN;
diff --git a/drivers/platform/msm/ipa/ipa_ram_mmap.h b/drivers/platform/msm/ipa/ipa_ram_mmap.h
index 7e12b6a..78093b8 100644
--- a/drivers/platform/msm/ipa/ipa_ram_mmap.h
+++ b/drivers/platform/msm/ipa/ipa_ram_mmap.h
@@ -15,21 +15,22 @@
/*
* This header defines the memory map of the IPA RAM (not all 8K is available
- * for SW use) the first 2K are set aside for NAT
+ * for SW use)
*/
#define IPA_RAM_NAT_OFST 0
-#define IPA_RAM_NAT_SIZE 2048
-#define IPA_RAM_HDR_OFST 2048
-#define IPA_RAM_HDR_SIZE 440
+#define IPA_RAM_NAT_SIZE 0
+#define IPA_RAM_HDR_OFST (IPA_RAM_NAT_OFST + IPA_RAM_NAT_SIZE)
+#define IPA_RAM_HDR_SIZE 1280
#define IPA_RAM_V4_FLT_OFST (IPA_RAM_HDR_OFST + IPA_RAM_HDR_SIZE)
-#define IPA_RAM_V4_FLT_SIZE 1024
+#define IPA_RAM_V4_FLT_SIZE 1408
#define IPA_RAM_V4_RT_OFST (IPA_RAM_V4_FLT_OFST + IPA_RAM_V4_FLT_SIZE)
-#define IPA_RAM_V4_RT_SIZE 1024
+#define IPA_RAM_V4_RT_SIZE 2176
#define IPA_RAM_V6_FLT_OFST (IPA_RAM_V4_RT_OFST + IPA_RAM_V4_RT_SIZE)
-#define IPA_RAM_V6_FLT_SIZE 1024
+#define IPA_RAM_V6_FLT_SIZE 1280
#define IPA_RAM_V6_RT_OFST (IPA_RAM_V6_FLT_OFST + IPA_RAM_V6_FLT_SIZE)
-#define IPA_RAM_V6_RT_SIZE 1024
+#define IPA_RAM_V6_RT_SIZE 512
#define IPA_RAM_END_OFST (IPA_RAM_V6_RT_OFST + IPA_RAM_V6_RT_SIZE)
+#define IPA_RAM_V6_RT_SIZE_DDR 16384
#endif /* _IPA_RAM_MMAP_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_reg.h b/drivers/platform/msm/ipa/ipa_reg.h
index 03d1972..ffa81dc 100644
--- a/drivers/platform/msm/ipa/ipa_reg.h
+++ b/drivers/platform/msm/ipa/ipa_reg.h
@@ -183,6 +183,27 @@
#define IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_TIMER_BMSK 0x1ff
#define IPA_ENDP_INIT_HOL_BLOCK_TIMER_n_TIMER_SHFT 0x0
+#define IPA_DEBUG_CNT_REG_n_OFST(n) (0x00000340 + 0x4 * (n))
+#define IPA_DEBUG_CNT_REG_n_RMSK 0xffffffff
+#define IPA_DEBUG_CNT_REG_n_MAXn 15
+#define IPA_DEBUG_CNT_REG_n_DBG_CNT_REG_BMSK 0xffffffff
+#define IPA_DEBUG_CNT_REG_n_DBG_CNT_REG_SHFT 0x0
+
+#define IPA_DEBUG_CNT_CTRL_n_OFST(n) (0x00000380 + 0x4 * (n))
+#define IPA_DEBUG_CNT_CTRL_n_RMSK 0x1ff1f171
+#define IPA_DEBUG_CNT_CTRL_n_MAXn 15
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_BMSK 0x1ff00000
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_RULE_INDEX_SHFT 0x14
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_SOURCE_PIPE_BMSK 0x1f000
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_SOURCE_PIPE_SHFT 0xc
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_PRODUCT_BMSK 0x100
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_PRODUCT_SHFT 0x8
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_TYPE_BMSK 0x70
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_TYPE_SHFT 0x4
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_EN_BMSK 0x1
+#define IPA_DEBUG_CNT_CTRL_n_DBG_CNT_EN_SHFT 0x0
+
+
#endif
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 7d509c6..1d88280 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -361,7 +361,8 @@
avail = IPA_RAM_V4_RT_SIZE;
size = sizeof(struct ipa_ip_v4_routing_init);
} else {
- avail = IPA_RAM_V6_RT_SIZE;
+ avail = ipa_ctx->ip6_rt_tbl_lcl ? IPA_RAM_V6_RT_SIZE :
+ IPA_RAM_V6_RT_SIZE_DDR;
size = sizeof(struct ipa_ip_v6_routing_init);
}
cmd = kmalloc(size, GFP_KERNEL);
@@ -698,7 +699,7 @@
}
if (entry->hdr)
- entry->hdr->ref_cnt--;
+ __ipa_release_hdr((u32)entry->hdr);
list_del(&entry->link);
entry->tbl->rule_cnt--;
IPADBG("del rt rule tbl_idx=%d rule_cnt=%d\n", entry->tbl->idx,
@@ -850,7 +851,7 @@
list_del(&rule->link);
tbl->rule_cnt--;
if (rule->hdr)
- rule->hdr->ref_cnt--;
+ __ipa_release_hdr((u32)rule->hdr);
rule->cookie = 0;
kmem_cache_free(ipa_ctx->rt_rule_cache, rule);
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 37dfc1b..b34f9dc 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -555,14 +555,14 @@
return;
}
- dfile_info = debugfs_create_file("info", 0666, dent, 0,
+ dfile_info = debugfs_create_file("info", 0664, dent, 0,
&sps_info_ops);
if (!dfile_info || IS_ERR(dfile_info)) {
pr_err("sps:fail to create the file for debug_fs info.\n");
goto info_err;
}
- dfile_logging_option = debugfs_create_file("logging_option", 0666,
+ dfile_logging_option = debugfs_create_file("logging_option", 0664,
dent, 0, &sps_logging_option_ops);
if (!dfile_logging_option || IS_ERR(dfile_logging_option)) {
pr_err("sps:fail to create the file for debug_fs "
@@ -571,7 +571,7 @@
}
dfile_debug_level_option = debugfs_create_u8("debug_level_option",
- 0666, dent, &debug_level_option);
+ 0664, dent, &debug_level_option);
if (!dfile_debug_level_option || IS_ERR(dfile_debug_level_option)) {
pr_err("sps:fail to create the file for debug_fs "
"debug_level_option.\n");
@@ -579,14 +579,14 @@
}
dfile_print_limit_option = debugfs_create_u8("print_limit_option",
- 0666, dent, &print_limit_option);
+ 0664, dent, &print_limit_option);
if (!dfile_print_limit_option || IS_ERR(dfile_print_limit_option)) {
pr_err("sps:fail to create the file for debug_fs "
"print_limit_option.\n");
goto print_limit_option_err;
}
- dfile_reg_dump_option = debugfs_create_u8("reg_dump_option", 0666,
+ dfile_reg_dump_option = debugfs_create_u8("reg_dump_option", 0664,
dent, ®_dump_option);
if (!dfile_reg_dump_option || IS_ERR(dfile_reg_dump_option)) {
pr_err("sps:fail to create the file for debug_fs "
@@ -594,28 +594,28 @@
goto reg_dump_option_err;
}
- dfile_testbus_sel = debugfs_create_u32("testbus_sel", 0666,
+ dfile_testbus_sel = debugfs_create_u32("testbus_sel", 0664,
dent, &testbus_sel);
if (!dfile_testbus_sel || IS_ERR(dfile_testbus_sel)) {
pr_err("sps:fail to create debug_fs file for testbus_sel.\n");
goto testbus_sel_err;
}
- dfile_bam_pipe_sel = debugfs_create_u32("bam_pipe_sel", 0666,
+ dfile_bam_pipe_sel = debugfs_create_u32("bam_pipe_sel", 0664,
dent, &bam_pipe_sel);
if (!dfile_bam_pipe_sel || IS_ERR(dfile_bam_pipe_sel)) {
pr_err("sps:fail to create debug_fs file for bam_pipe_sel.\n");
goto bam_pipe_sel_err;
}
- dfile_desc_option = debugfs_create_u32("desc_option", 0666,
+ dfile_desc_option = debugfs_create_u32("desc_option", 0664,
dent, &desc_option);
if (!dfile_desc_option || IS_ERR(dfile_desc_option)) {
pr_err("sps:fail to create debug_fs file for desc_option.\n");
goto desc_option_err;
}
- dfile_bam_addr = debugfs_create_file("bam_addr", 0666,
+ dfile_bam_addr = debugfs_create_file("bam_addr", 0664,
dent, 0, &sps_bam_addr_ops);
if (!dfile_bam_addr || IS_ERR(dfile_bam_addr)) {
pr_err("sps:fail to create the file for debug_fs "
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index f9ae3c2..a5fac9e 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -52,6 +52,28 @@
struct sps_connect *sps_connections;
};
+/**
+* struct usb_bam_ctx_type - represents the usb bam driver entity
+* @usb_bam_sps: holds the sps pipes the usb bam driver holds
+* against the sps driver.
+* @usb_bam_pdev: the platfrom device that represents the usb bam.
+* @usb_bam_wq: Worqueue used for managing states of reset against
+* a peer bam.
+* @qscratch_ram1_reg: The memory region mapped to the qscratch
+* registers.
+* @max_connections: The maximum number of pipes that are configured
+* in the platform data.
+* @mem_clk: Clock that controls the usb bam driver memory in
+* case the usb bam uses its private memory for the pipes.
+* @mem_iface_clk: Clock that controls the usb bam private memory in
+* case the usb bam uses its private memory for the pipes.
+* @qdss_core_name: Stores the name of the core ("ssusb", "hsusb" or "hsic")
+* that it used as a peer of the qdss in bam2bam mode.
+* @h_bam: This array stores for each BAM ("ssusb", "hsusb" or "hsic") the
+* handle/device of the sps driver.
+* @pipes_enabled_per_bam: This array stores for each BAM
+* ("ssusb", "hsusb" or "hsic") the number of pipes currently enabled.
+*/
struct usb_bam_ctx_type {
struct usb_bam_sps_type usb_bam_sps;
struct platform_device *usb_bam_pdev;
@@ -61,8 +83,8 @@
struct clk *mem_clk;
struct clk *mem_iface_clk;
char qdss_core_name[USB_BAM_MAX_STR_LEN];
- char bam_enabled_list[USB_BAM_MAX_STR_LEN];
u32 h_bam[MAX_BAMS];
+ u8 pipes_enabled_per_bam[MAX_BAMS];
};
static char *bam_enable_strings[3] = {
@@ -442,7 +464,6 @@
int usb_bam_connect(u8 idx, u32 *bam_pipe_idx)
{
int ret;
- enum usb_bam bam;
struct usb_bam_pipe_connect *pipe_connect = &usb_bam_connections[idx];
struct msm_usb_bam_platform_data *pdata;
@@ -467,13 +488,11 @@
pr_err("idx is wrong %d", idx);
return -EINVAL;
}
- bam = pipe_connect->bam_type;
- if (bam < 0)
- return -EINVAL;
- /* Check if BAM requires RESET before connect */
- if (pdata->reset_on_connect[bam] == true)
- sps_device_reset(ctx.h_bam[bam]);
+ /* Check if BAM requires RESET before connect and reset of first pipe */
+ if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
+ (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
+ sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
ret = connect_pipe(idx, bam_pipe_idx);
if (ret) {
@@ -482,6 +501,7 @@
}
pipe_connect->enabled = 1;
+ ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
return 0;
}
@@ -548,6 +568,8 @@
u8 idx;
struct usb_bam_pipe_connect *pipe_connect;
int ret;
+ struct msm_usb_bam_platform_data *pdata =
+ ctx.usb_bam_pdev->dev.platform_data;
if (!ipa_params) {
pr_err("%s: Invalid ipa params\n",
@@ -573,8 +595,13 @@
return 0;
}
+ /* Check if BAM requires RESET before connect and reset of first pipe */
+ if ((pdata->reset_on_connect[pipe_connect->bam_type] == true) &&
+ (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0))
+ sps_device_reset(ctx.h_bam[pipe_connect->bam_type]);
+
ret = connect_pipe_ipa(idx, ipa_params);
- ipa_rm_request_resource(IPA_CLIENT_USB_PROD);
+ ipa_rm_request_resource(IPA_RM_RESOURCE_USB_PROD);
if (ret) {
pr_err("%s: dst pipe connection failure\n", __func__);
@@ -582,6 +609,7 @@
}
pipe_connect->enabled = 1;
+ ctx.pipes_enabled_per_bam[pipe_connect->bam_type] += 1;
return 0;
}
@@ -799,6 +827,11 @@
}
pipe_connect->enabled = 0;
+ if (ctx.pipes_enabled_per_bam[pipe_connect->bam_type] == 0)
+ pr_err("%s: wrong pipes enabled counter for bam_type=%d\n",
+ __func__, pipe_connect->bam_type);
+ else
+ ctx.pipes_enabled_per_bam[pipe_connect->bam_type] -= 1;
return 0;
}
@@ -853,7 +886,7 @@
}
}
- ipa_rm_release_resource(IPA_CLIENT_USB_PROD);
+ ipa_rm_release_resource(IPA_RM_RESOURCE_USB_PROD);
return 0;
}
EXPORT_SYMBOL(usb_bam_disconnect_ipa);
@@ -993,6 +1026,7 @@
__func__);
goto err;
}
+ bam = usb_bam_connections[i].bam_type;
rc = of_property_read_u32(node, "qcom,peer-bam",
&usb_bam_connections[i].peer_bam);
@@ -1220,6 +1254,9 @@
usb_bam_work);
}
+ for (i = 0; i < MAX_BAMS; i++)
+ ctx.pipes_enabled_per_bam[i] = 0;
+
spin_lock_init(&usb_bam_lock);
INIT_WORK(&peer_handshake_info.reset_event.event_w, usb_bam_sm_work);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index becc314..a2701ce 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -59,6 +59,8 @@
#define PON_CNTRL_6 0x018
#define WD_BIT BIT(7)
+#define BATT_ALARM_ACCURACY 50 /* 50mV */
+
enum pmic_bms_interrupts {
PM8921_BMS_SBI_WRITE_OK,
PM8921_BMS_CC_THR,
@@ -159,7 +161,6 @@
int soc_at_cv;
int prev_chg_soc;
struct power_supply *batt_psy;
- bool low_voltage_wake_lock_held;
struct wake_lock low_voltage_wake_lock;
int soc_calc_period;
int normal_voltage_calc_ms;
@@ -170,6 +171,9 @@
int ocv_dis_high_soc;
int ocv_dis_low_soc;
int prev_vbat_batt_terminal_uv;
+ int vbatt_cutoff_count;
+ int low_voltage_detect;
+ int vbatt_cutoff_retries;
};
/*
@@ -391,6 +395,20 @@
return val;
}
+static void pm8921_bms_low_voltage_config(struct pm8921_bms_chip *chip,
+ int time_ms)
+{
+ int ms = 0;
+
+ /* if work was pending and was cancelled, calculate SOC immediately */
+ if (!cancel_delayed_work_sync(&chip->calculate_soc_delayed_work))
+ ms = time_ms;
+
+ chip->soc_calc_period = time_ms;
+ schedule_delayed_work(&chip->calculate_soc_delayed_work,
+ msecs_to_jiffies(ms));
+}
+
static int pm8921_bms_enable_batt_alarm(struct pm8921_bms_chip *chip)
{
int rc = 0;
@@ -479,8 +497,12 @@
* hold the low voltage wakelock until the soc
* work finds it appropriate to release it.
*/
- wake_lock(&the_chip->low_voltage_wake_lock);
- the_chip->low_voltage_wake_lock_held = 1;
+ if (!wake_lock_active(&the_chip->low_voltage_wake_lock)) {
+ pr_debug("Holding low voltage wakelock\n");
+ wake_lock(&the_chip->low_voltage_wake_lock);
+ pm8921_bms_low_voltage_config(the_chip,
+ the_chip->low_voltage_calc_ms);
+ }
rc = pm8xxx_batt_alarm_disable(
PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
@@ -1788,26 +1810,42 @@
* if battery is very low (v_cutoff voltage + 20mv) hold
* a wakelock untill soc = 0%
*/
- if (vbat_uv <= (chip->v_cutoff + 20) * 1000
- && !chip->low_voltage_wake_lock_held) {
+ if (vbat_uv <= (chip->alarm_low_mv + 20) * 1000 &&
+ !wake_lock_active(&the_chip->low_voltage_wake_lock)) {
pr_debug("voltage = %d low holding wakelock\n", vbat_uv);
wake_lock(&chip->low_voltage_wake_lock);
- chip->low_voltage_wake_lock_held = 1;
chip->soc_calc_period = chip->low_voltage_calc_ms;
}
- if (vbat_uv > (chip->v_cutoff + 20) * 1000
- && chip->low_voltage_wake_lock_held) {
+ if (vbat_uv > (chip->alarm_low_mv + 20 + BATT_ALARM_ACCURACY) * 1000
+ && wake_lock_active(&the_chip->low_voltage_wake_lock)) {
pr_debug("voltage = %d releasing wakelock\n", vbat_uv);
- chip->low_voltage_wake_lock_held = 0;
- wake_unlock(&chip->low_voltage_wake_lock);
+ chip->vbatt_cutoff_count = 0;
chip->soc_calc_period = chip->normal_voltage_calc_ms;
rc = pm8921_bms_enable_batt_alarm(chip);
if (rc)
pr_err("Unable to enable batt alarm\n");
+ wake_unlock(&chip->low_voltage_wake_lock);
}
}
+static bool is_voltage_below_cutoff_window(struct pm8921_bms_chip *chip,
+ int ibat_ua, int vbat_uv)
+{
+ if (vbat_uv < (chip->v_cutoff * 1000) && ibat_ua > 0) {
+ chip->vbatt_cutoff_count++;
+ if (chip->vbatt_cutoff_count >= chip->vbatt_cutoff_retries) {
+ pr_debug("cutoff_count >= %d\n",
+ chip->vbatt_cutoff_retries);
+ return true;
+ }
+ } else {
+ chip->vbatt_cutoff_count = 0;
+ }
+
+ return false;
+}
+
static int last_soc_est = -EINVAL;
static int adjust_soc(struct pm8921_bms_chip *chip, int soc,
int batt_temp, int chargecycles,
@@ -1834,6 +1872,15 @@
very_low_voltage_check(chip, ibat_ua, vbat_uv);
+ if (chip->low_voltage_detect &&
+ wake_lock_active(&chip->low_voltage_wake_lock)) {
+ if (is_voltage_below_cutoff_window(chip, ibat_ua, vbat_uv)) {
+ soc = 0;
+ pr_info("Voltage below cutoff, setting soc to 0\n");
+ goto out;
+ }
+ }
+
delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
ocv_est_uv = vbat_uv + (ibat_ua * rbatt)/1000;
@@ -3327,6 +3374,8 @@
chip->alarm_low_mv = pdata->alarm_low_mv;
chip->alarm_high_mv = pdata->alarm_high_mv;
+ chip->low_voltage_detect = pdata->low_voltage_detect;
+ chip->vbatt_cutoff_retries = pdata->vbatt_cutoff_retries;
mutex_init(&chip->calib_mutex);
INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 68f4bdd..5136fdf 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3142,6 +3142,9 @@
static void pm_batt_external_power_changed(struct power_supply *psy)
{
+ if (!the_chip)
+ return;
+
/* Only look for an external supply if it hasn't been registered */
if (!the_chip->ext_psy)
class_for_each_device(power_supply_class, NULL, psy,
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index bc6f289..08cf71e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -116,6 +116,8 @@
u8 revision1;
u8 revision2;
int battery_present;
+ bool new_battery;
+ bool last_soc_invalid;
/* platform data */
int r_sense_uohm;
unsigned int v_cutoff_uv;
@@ -135,6 +137,7 @@
int default_rbatt_mohm;
struct delayed_work calculate_soc_delayed_work;
+ struct work_struct recalc_work;
struct mutex bms_output_lock;
struct mutex last_ocv_uv_mutex;
@@ -144,7 +147,7 @@
bool use_ocv_thresholds;
bool ignore_shutdown_soc;
- int shutdown_soc_invalid;
+ bool shutdown_soc_invalid;
int shutdown_soc;
int shutdown_iavg_ma;
@@ -552,6 +555,100 @@
pr_err("cc reenable failed: %d\n", rc);
}
+static bool is_battery_charging(struct qpnp_bms_chip *chip)
+{
+ union power_supply_propval ret = {0,};
+
+ if (chip->batt_psy == NULL)
+ chip->batt_psy = power_supply_get_by_name("battery");
+ if (chip->batt_psy) {
+ /* if battery has been registered, use the status property */
+ chip->batt_psy->get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_STATUS, &ret);
+ return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
+ }
+
+ /* Default to false if the battery power supply is not registered. */
+ pr_debug("battery power supply is not registered\n");
+ return false;
+}
+
+static bool is_batfet_open(struct qpnp_bms_chip *chip)
+{
+ union power_supply_propval ret = {0,};
+
+ if (chip->batt_psy == NULL)
+ chip->batt_psy = power_supply_get_by_name("battery");
+ if (chip->batt_psy) {
+ /* if battery has been registered, use the status property */
+ chip->batt_psy->get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_STATUS, &ret);
+ return ret.intval == POWER_SUPPLY_STATUS_FULL;
+ }
+
+ /* Default to true if the battery power supply is not registered. */
+ pr_debug("battery power supply is not registered\n");
+ return true;
+}
+
+static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
+ int *ibat_ua, int *vbat_uv)
+{
+ struct qpnp_iadc_result i_result;
+ struct qpnp_vadc_result v_result;
+ enum qpnp_iadc_channels iadc_channel;
+ int rc;
+
+ iadc_channel = chip->use_external_rsense ?
+ EXTERNAL_RSENSE : INTERNAL_RSENSE;
+ rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
+ VBAT_SNS, &v_result);
+ if (rc) {
+ pr_err("vadc read failed with rc: %d\n", rc);
+ return rc;
+ }
+ /*
+ * reverse the current read by the iadc, since the bms uses
+ * flipped battery current polarity.
+ */
+ *ibat_ua = -1 * (int)i_result.result_ua;
+ *vbat_uv = (int)v_result.physical;
+
+ return 0;
+}
+
+static int estimate_ocv(struct qpnp_bms_chip *chip)
+{
+ int ibat_ua, vbat_uv, ocv_est_uv;
+ int rc;
+ int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm;
+
+ rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
+ if (rc) {
+ pr_err("simultaneous failed rc = %d\n", rc);
+ return rc;
+ }
+
+ ocv_est_uv = vbat_uv + (ibat_ua * rbatt_mohm) / 1000;
+ pr_debug("estimated pon ocv = %d\n", ocv_est_uv);
+ return ocv_est_uv;
+}
+
+static void reset_for_new_battery(struct qpnp_bms_chip *chip, int batt_temp)
+{
+ chip->last_ocv_uv = estimate_ocv(chip);
+ chip->last_soc = -EINVAL;
+ chip->soc_at_cv = -EINVAL;
+ chip->shutdown_soc_invalid = true;
+ chip->shutdown_soc = 0;
+ chip->shutdown_iavg_ma = 0;
+ chip->prev_pc_unusable = -EINVAL;
+ reset_cc(chip);
+ chip->last_cc_uah = INT_MIN;
+ chip->last_ocv_temp = batt_temp;
+ chip->last_soc_invalid = true;
+}
+
#define OCV_RAW_UNINITIALIZED 0xFFFF
static int read_soc_params_raw(struct qpnp_bms_chip *chip,
struct raw_soc_params *raw,
@@ -590,6 +687,12 @@
if (chip->prev_last_good_ocv_raw == OCV_RAW_UNINITIALIZED) {
convert_and_store_ocv(chip, raw, batt_temp);
pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
+ } else if (chip->new_battery) {
+ /* if a new battery was inserted, estimate the ocv */
+ reset_for_new_battery(chip, batt_temp);
+ raw->cc = 0;
+ raw->last_good_ocv_uv = chip->last_ocv_uv;
+ chip->new_battery = false;
} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
convert_and_store_ocv(chip, raw, batt_temp);
/* forget the old cc value upon ocv */
@@ -1083,75 +1186,13 @@
pr_debug("rejecting shutdown soc = %d, soc = %d limit = %d\n",
chip->shutdown_soc, soc,
chip->shutdown_soc_valid_limit);
- chip->shutdown_soc_invalid = 1;
+ chip->shutdown_soc_invalid = true;
return 0;
}
return 1;
}
-static bool is_battery_charging(struct qpnp_bms_chip *chip)
-{
- union power_supply_propval ret = {0,};
-
- if (chip->batt_psy == NULL)
- chip->batt_psy = power_supply_get_by_name("battery");
- if (chip->batt_psy) {
- /* if battery has been registered, use the status property */
- chip->batt_psy->get_property(chip->batt_psy,
- POWER_SUPPLY_PROP_STATUS, &ret);
- return ret.intval == POWER_SUPPLY_STATUS_CHARGING;
- }
-
- /* Default to false if the battery power supply is not registered. */
- pr_debug("battery power supply is not registered\n");
- return false;
-}
-
-static bool is_batfet_open(struct qpnp_bms_chip *chip)
-{
- union power_supply_propval ret = {0,};
-
- if (chip->batt_psy == NULL)
- chip->batt_psy = power_supply_get_by_name("battery");
- if (chip->batt_psy) {
- /* if battery has been registered, use the status property */
- chip->batt_psy->get_property(chip->batt_psy,
- POWER_SUPPLY_PROP_STATUS, &ret);
- return ret.intval == POWER_SUPPLY_STATUS_FULL;
- }
-
- /* Default to true if the battery power supply is not registered. */
- pr_debug("battery power supply is not registered\n");
- return true;
-}
-
-static int get_simultaneous_batt_v_and_i(struct qpnp_bms_chip *chip,
- int *ibat_ua, int *vbat_uv)
-{
- struct qpnp_iadc_result i_result;
- struct qpnp_vadc_result v_result;
- enum qpnp_iadc_channels iadc_channel;
- int rc;
-
- iadc_channel = chip->use_external_rsense ?
- EXTERNAL_RSENSE : INTERNAL_RSENSE;
- rc = qpnp_iadc_vadc_sync_read(iadc_channel, &i_result,
- VBAT_SNS, &v_result);
- if (rc) {
- pr_err("vadc read failed with rc: %d\n", rc);
- return rc;
- }
- /*
- * reverse the current read by the iadc, since the bms uses
- * flipped battery current polarity.
- */
- *ibat_ua = -1 * (int)i_result.result_ua;
- *vbat_uv = (int)v_result.physical;
-
- return 0;
-}
-
static int bound_soc(int soc)
{
soc = max(0, soc);
@@ -1188,6 +1229,7 @@
pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
chip->last_ocv_uv = ocv_est_uv;
chip->last_soc = -EINVAL;
+ chip->last_soc_invalid = true;
reset_cc(chip);
chip->last_cc_uah = INT_MIN;
stop_ocv_updates(chip);
@@ -1475,6 +1517,11 @@
int shutdown_soc, new_calculated_soc, remaining_usable_charge_uah;
struct soc_params params;
+ if (!chip->battery_present) {
+ pr_debug("battery gone, reporting 100\n");
+ new_calculated_soc = 100;
+ goto done_calculating;
+ }
calculate_soc_params(chip, raw, ¶ms, batt_temp);
/* calculate remaining usable charge */
remaining_usable_charge_uah = params.ocv_charge_uah
@@ -1574,6 +1621,10 @@
}
chip->calculated_soc = new_calculated_soc;
+ if (chip->last_soc_invalid) {
+ chip->last_soc_invalid = false;
+ chip->last_soc = -EINVAL;
+ }
pr_debug("CC based calculated SOC = %d\n", chip->calculated_soc);
chip->first_time_calc_soc = 0;
get_current_time(&chip->last_recalc_time);
@@ -1639,6 +1690,15 @@
return soc;
}
+static void recalculate_work(struct work_struct *work)
+{
+ struct qpnp_bms_chip *chip = container_of(work,
+ struct qpnp_bms_chip,
+ recalc_work);
+
+ recalculate_soc(chip);
+}
+
static void calculate_soc_work(struct work_struct *work)
{
struct qpnp_bms_chip *chip = container_of(work,
@@ -1820,7 +1880,7 @@
pr_debug("Reported SOC = %d\n", chip->last_soc);
chip->t_soc_queried = now;
- return chip->last_soc;
+ return soc;
}
static int report_state_of_charge(struct qpnp_bms_chip *chip)
@@ -1872,8 +1932,14 @@
static void set_prop_bms_present(struct qpnp_bms_chip *chip, int present)
{
- if (chip->battery_present != present)
+ if (chip->battery_present != present) {
chip->battery_present = present;
+ if (present)
+ chip->new_battery = true;
+ /* a new battery was inserted or removed, so force a soc
+ * recalculation to update the SoC */
+ schedule_work(&chip->recalc_work);
+ }
}
static void qpnp_bms_external_power_changed(struct power_supply *psy)
@@ -1969,7 +2035,7 @@
u8 temp;
if (chip->ignore_shutdown_soc) {
- chip->shutdown_soc_invalid = 1;
+ chip->shutdown_soc_invalid = true;
chip->shutdown_soc = 0;
chip->shutdown_iavg_ma = 0;
} else {
@@ -2003,7 +2069,7 @@
if (chip->shutdown_soc == 0) {
pr_debug("No shutdown soc available\n");
- chip->shutdown_soc_invalid = 1;
+ chip->shutdown_soc_invalid = true;
chip->shutdown_iavg_ma = 0;
} else if (chip->shutdown_soc == SOC_ZERO) {
chip->shutdown_soc = 0;
@@ -2391,6 +2457,7 @@
"qpnp_low_voltage_lock");
INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
calculate_soc_work);
+ INIT_WORK(&chip->recalc_work, recalculate_work);
read_shutdown_soc_and_iavg(chip);
@@ -2403,6 +2470,9 @@
chip->batt_psy->get_property(chip->batt_psy,
POWER_SUPPLY_PROP_PRESENT, &retval);
chip->battery_present = retval.intval;
+ pr_debug("present = %d\n", chip->battery_present);
+ } else {
+ chip->battery_present = 1;
}
calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 180ca0d..35d8df9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -190,8 +190,8 @@
* @safe_current: battery safety current setting
* @maxinput_usb_ma: Maximum Input current USB
* @maxinput_dc_ma: Maximum Input current DC
- * @warm_bat_degc Warm battery temperature in degree Celsius
- * @cool_bat_degc Cool battery temperature in degree Celsius
+ * @warm_bat_decidegc Warm battery temperature in degree Celsius
+ * @cool_bat_decidegc Cool battery temperature in degree Celsius
* @revision: PMIC revision
* @thermal_levels amount of thermal mitigation levels
* @thermal_mitigation thermal mitigation level values
@@ -242,8 +242,8 @@
unsigned int term_current;
unsigned int maxinput_usb_ma;
unsigned int maxinput_dc_ma;
- unsigned int warm_bat_degc;
- unsigned int cool_bat_degc;
+ unsigned int warm_bat_decidegc;
+ unsigned int cool_bat_decidegc;
unsigned int safe_current;
unsigned int revision;
unsigned int thermal_levels;
@@ -546,6 +546,12 @@
if (chip->batt_present ^ batt_present) {
chip->batt_present = batt_present;
power_supply_changed(&chip->batt_psy);
+
+ if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
+ && batt_present) {
+ if (qpnp_adc_tm_channel_measure(&chip->adc_param))
+ pr_err("request ADC error\n");
+ }
}
if (chip->bms_psy)
@@ -1019,7 +1025,8 @@
/* Only honour requests while USB is present */
if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
- if (ret.intval <= 2) {
+ if (ret.intval <= 2 && !chip->use_default_batt_values &&
+ get_prop_batt_present(chip)) {
qpnp_chg_usb_suspend_enable(chip, 1);
qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
} else {
@@ -1304,56 +1311,74 @@
}
}
-#define TEMP_HYSTERISIS_DEGC 2
+#define HYSTERISIS_DECIDEGC 20
static void
qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
{
struct qpnp_chg_chip *chip = ctx;
bool bat_warm = 0, bat_cool = 0;
+ int temp;
if (state >= ADC_TM_STATE_NUM) {
pr_err("invalid notification %d\n", state);
return;
}
- pr_debug("state = %s\n", state == ADC_TM_HIGH_STATE ? "high" : "low");
+ temp = get_prop_batt_temp(chip);
- if (state == ADC_TM_HIGH_STATE) {
- if (!chip->bat_is_warm) {
+ pr_debug("temp = %d state = %s\n", temp,
+ state == ADC_TM_WARM_STATE ? "warm" : "cool");
+
+ if (state == ADC_TM_WARM_STATE) {
+ if (temp > chip->warm_bat_decidegc) {
bat_warm = true;
bat_cool = false;
chip->adc_param.low_temp =
- chip->warm_bat_degc - TEMP_HYSTERISIS_DEGC;
- } else if (chip->bat_is_cool) {
+ chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC;
+ chip->adc_param.state_request =
+ ADC_TM_COOL_THR_ENABLE;
+ } else if (temp >
+ chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC){
bat_warm = false;
bat_cool = false;
- chip->adc_param.high_temp = chip->warm_bat_degc;
+
+ chip->adc_param.low_temp = chip->cool_bat_decidegc;
+ chip->adc_param.high_temp = chip->warm_bat_decidegc;
+ chip->adc_param.state_request =
+ ADC_TM_HIGH_LOW_THR_ENABLE;
}
} else {
- if (!chip->bat_is_cool) {
+ if (temp < chip->cool_bat_decidegc) {
+ bat_warm = false;
bat_cool = true;
- bat_warm = false;
chip->adc_param.high_temp =
- chip->cool_bat_degc + TEMP_HYSTERISIS_DEGC;
- } else if (chip->bat_is_warm) {
- bat_cool = false;
+ chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC;
+ chip->adc_param.state_request =
+ ADC_TM_WARM_THR_ENABLE;
+ } else if (temp >
+ chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC){
bat_warm = false;
- chip->adc_param.low_temp = chip->cool_bat_degc;
+ bat_cool = false;
+
+ chip->adc_param.low_temp = chip->cool_bat_decidegc;
+ chip->adc_param.high_temp = chip->warm_bat_decidegc;
+ chip->adc_param.state_request =
+ ADC_TM_HIGH_LOW_THR_ENABLE;
}
}
if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
+ chip->bat_is_cool = bat_cool;
+ chip->bat_is_warm = bat_warm;
+
/* set appropriate voltages and currents */
qpnp_chg_set_appropriate_vddmax(chip);
qpnp_chg_set_appropriate_battery_current(chip);
qpnp_chg_set_appropriate_vbatdet(chip);
-
- chip->bat_is_cool = bat_cool;
- chip->bat_is_warm = bat_warm;
}
- /* re-arm ADC interrupt */
- qpnp_adc_tm_btm_configure(&chip->adc_param);
+ if (qpnp_adc_tm_channel_measure(&chip->adc_param))
+ pr_err("request ADC error\n");
}
static int
@@ -1743,8 +1768,8 @@
/* Get the warm-bat-degc property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-warm-bat-degc",
- &chip->warm_bat_degc);
+ "qcom,chg-warm-bat-decidegc",
+ &chip->warm_bat_decidegc);
if (rc && rc != -EINVAL) {
pr_err("Error reading warm-bat-degc property %d\n", rc);
goto fail_chg_enable;
@@ -1752,14 +1777,14 @@
/* Get the cool-bat-degc property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-cool-bat-degc",
- &chip->cool_bat_degc);
+ "qcom,chg-cool-bat-decidegc",
+ &chip->cool_bat_decidegc);
if (rc && rc != -EINVAL) {
pr_err("Error reading cool-bat-degc property %d\n", rc);
goto fail_chg_enable;
}
- if (chip->cool_bat_degc && chip->warm_bat_degc) {
+ if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
rc = qpnp_adc_tm_is_ready();
if (rc) {
pr_err("tm not ready %d\n", rc);
@@ -1997,19 +2022,22 @@
}
}
- if (chip->cool_bat_degc && chip->warm_bat_degc) {
- chip->adc_param.low_temp = chip->cool_bat_degc;
- chip->adc_param.high_temp = chip->warm_bat_degc;
+ if (chip->cool_bat_decidegc && chip->warm_bat_decidegc) {
+ chip->adc_param.low_temp = chip->cool_bat_decidegc;
+ chip->adc_param.high_temp = chip->warm_bat_decidegc;
chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
chip->adc_param.btm_ctx = chip;
chip->adc_param.threshold_notification =
qpnp_chg_adc_notification;
+ chip->adc_param.channel = LR_MUX1_BATT_THERM;
- rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
- if (rc) {
- pr_err("request ADC error %d\n", rc);
- goto fail_chg_enable;
+ if (get_prop_batt_present(chip)) {
+ rc = qpnp_adc_tm_channel_measure(&chip->adc_param);
+ if (rc) {
+ pr_err("request ADC error %d\n", rc);
+ goto fail_chg_enable;
+ }
}
}
@@ -2038,6 +2066,10 @@
qpnp_charger_remove(struct spmi_device *spmi)
{
struct qpnp_chg_chip *chip = dev_get_drvdata(&spmi->dev);
+ if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
+ && chip->batt_present) {
+ qpnp_adc_tm_disable_chan_meas(&chip->adc_param);
+ }
dev_set_drvdata(&spmi->dev, NULL);
kfree(chip);
diff --git a/drivers/staging/ste_rmi4/Kconfig b/drivers/staging/ste_rmi4/Kconfig
index e867950..6570368 100644
--- a/drivers/staging/ste_rmi4/Kconfig
+++ b/drivers/staging/ste_rmi4/Kconfig
@@ -1,9 +1,12 @@
-config TOUCHSCREEN_SYNAPTICS_I2C_RMI4
- tristate "Synaptics i2c rmi4 touchscreen"
+config TOUCHSCREEN_SYNAPTICS_I2C_RMI4_STAGING
+ tristate "Synaptics i2c rmi4 touchscreen staging"
depends on I2C && INPUT
help
Say Y here if you have a Synaptics RMI4 and
- want to enable support for the built-in touchscreen.
+ want to enable support for the built-in touchscreen
+ through staging driver. Not to be confused with
+ TOUCHSCREEN_SYNAPTICS_I2C_RMI4 in
+ drivers/input/touchscreen directory.
To compile this driver as a module, choose M here: the
module will be called synaptics_rmi4_ts.
diff --git a/drivers/staging/ste_rmi4/Makefile b/drivers/staging/ste_rmi4/Makefile
index e4c0335..ee9a53e 100644
--- a/drivers/staging/ste_rmi4/Makefile
+++ b/drivers/staging/ste_rmi4/Makefile
@@ -1,5 +1,6 @@
#
# Makefile for the RMI4 touchscreen driver.
#
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4_STAGING) \
+ += synaptics_i2c_rmi4_staging.o
obj-$(CONFIG_MACH_MOP500) += board-mop500-u8500uib-rmi4.o
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
similarity index 99%
rename from drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
rename to drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
index 11728a0..43115c3 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.c
@@ -31,7 +31,7 @@
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
-#include "synaptics_i2c_rmi4.h"
+#include "synaptics_i2c_rmi4_staging.h"
/* TODO: for multiple device support will need a per-device mutex */
#define DRIVER_NAME "synaptics_rmi4_i2c"
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.h
similarity index 100%
rename from drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
rename to drivers/staging/ste_rmi4/synaptics_i2c_rmi4_staging.h
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 17ae34f..c02db14 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,8 @@
#include <linux/platform_device.h>
/* QPNP VADC TM register definition */
+#define QPNP_REVISION3 0x3
+#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT 2
#define QPNP_STATUS1 0x8
#define QPNP_STATUS1_OP_MODE 4
#define QPNP_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
@@ -79,22 +81,41 @@
#define QPNP_M0_LOW_THR_MSB 0x5d
#define QPNP_M0_HIGH_THR_LSB 0x5e
#define QPNP_M0_HIGH_THR_MSB 0x5f
+#define QPNP_M1_ADC_CH_SEL_CTL 0x68
#define QPNP_M1_LOW_THR_LSB 0x69
#define QPNP_M1_LOW_THR_MSB 0x6a
#define QPNP_M1_HIGH_THR_LSB 0x6b
#define QPNP_M1_HIGH_THR_MSB 0x6c
+#define QPNP_M2_ADC_CH_SEL_CTL 0x70
#define QPNP_M2_LOW_THR_LSB 0x71
#define QPNP_M2_LOW_THR_MSB 0x72
#define QPNP_M2_HIGH_THR_LSB 0x7b
#define QPNP_M2_HIGH_THR_MSB 0x7c
+#define QPNP_M3_ADC_CH_SEL_CTL 0x78
#define QPNP_M3_LOW_THR_LSB 0x79
#define QPNP_M3_LOW_THR_MSB 0x7a
#define QPNP_M3_HIGH_THR_LSB 0x7b
#define QPNP_M3_HIGH_THR_MSB 0x7c
+#define QPNP_M4_ADC_CH_SEL_CTL 0x80
#define QPNP_M4_LOW_THR_LSB 0x81
#define QPNP_M4_LOW_THR_MSB 0x82
#define QPNP_M4_HIGH_THR_LSB 0x83
#define QPNP_M4_HIGH_THR_MSB 0x84
+#define QPNP_M5_ADC_CH_SEL_CTL 0x88
+#define QPNP_M5_LOW_THR_LSB 0x89
+#define QPNP_M5_LOW_THR_MSB 0x8a
+#define QPNP_M5_HIGH_THR_LSB 0x8b
+#define QPNP_M5_HIGH_THR_MSB 0x8c
+#define QPNP_M6_ADC_CH_SEL_CTL 0x90
+#define QPNP_M6_LOW_THR_LSB 0x91
+#define QPNP_M6_LOW_THR_MSB 0x92
+#define QPNP_M6_HIGH_THR_LSB 0x93
+#define QPNP_M6_HIGH_THR_MSB 0x94
+#define QPNP_M7_ADC_CH_SEL_CTL 0x98
+#define QPNP_M7_LOW_THR_LSB 0x99
+#define QPNP_M7_LOW_THR_MSB 0x9a
+#define QPNP_M7_HIGH_THR_LSB 0x9b
+#define QPNP_M7_HIGH_THR_MSB 0x9c
#define QPNP_ADC_TM_MULTI_MEAS_EN 0x41
#define QPNP_ADC_TM_MULTI_MEAS_EN_M0 BIT(0)
@@ -102,24 +123,36 @@
#define QPNP_ADC_TM_MULTI_MEAS_EN_M2 BIT(2)
#define QPNP_ADC_TM_MULTI_MEAS_EN_M3 BIT(3)
#define QPNP_ADC_TM_MULTI_MEAS_EN_M4 BIT(4)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M5 BIT(5)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M6 BIT(6)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M7 BIT(7)
#define QPNP_ADC_TM_LOW_THR_INT_EN 0x42
#define QPNP_ADC_TM_LOW_THR_INT_EN_M0 BIT(0)
#define QPNP_ADC_TM_LOW_THR_INT_EN_M1 BIT(1)
#define QPNP_ADC_TM_LOW_THR_INT_EN_M2 BIT(2)
#define QPNP_ADC_TM_LOW_THR_INT_EN_M3 BIT(3)
#define QPNP_ADC_TM_LOW_THR_INT_EN_M4 BIT(4)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M5 BIT(5)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M6 BIT(6)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M7 BIT(7)
#define QPNP_ADC_TM_HIGH_THR_INT_EN 0x43
#define QPNP_ADC_TM_HIGH_THR_INT_EN_M0 BIT(0)
#define QPNP_ADC_TM_HIGH_THR_INT_EN_M1 BIT(1)
#define QPNP_ADC_TM_HIGH_THR_INT_EN_M2 BIT(2)
#define QPNP_ADC_TM_HIGH_THR_INT_EN_M3 BIT(3)
#define QPNP_ADC_TM_HIGH_THR_INT_EN_M4 BIT(4)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M5 BIT(5)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M6 BIT(6)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M7 BIT(7)
-#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL 0x57
+#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL 0x59
#define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL 0x6d
#define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL 0x75
#define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL 0x7d
#define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL 0x85
+#define QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL 0x8d
+#define QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL 0x95
+#define QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL 0x9d
#define QPNP_ADC_TM_STATUS1 0x8
#define QPNP_ADC_TM_STATUS_LOW 0xa
#define QPNP_ADC_TM_STATUS_HIGH 0xb
@@ -131,6 +164,9 @@
#define QPNP_ADC_TM_THR_LSB_MASK(val) (val & 0xff)
#define QPNP_ADC_TM_THR_MSB_MASK(val) ((val & 0xff00) >> 8)
+#define QPNP_MIN_TIME 2000
+#define QPNP_MAX_TIME 2100
+
struct qpnp_adc_tm_sensor {
struct thermal_zone_device *tz_dev;
enum thermal_device_mode mode;
@@ -140,16 +176,19 @@
uint32_t low_thr;
uint32_t high_thr;
uint32_t btm_channel_num;
+ uint32_t vadc_channel_num;
struct work_struct work;
+ struct qpnp_adc_tm_btm_param *btm_param;
+ bool thermal_node;
+ bool low_thr_notify;
+ bool high_thr_notify;
+ uint32_t scale_type;
};
struct qpnp_adc_tm_drv {
struct qpnp_adc_drv *adc;
- struct qpnp_adc_tm_usbid_param *usb_id_param;
- struct work_struct usbid_work;
- struct qpnp_adc_tm_btm_param *battery_param;
- struct work_struct batt_work;
bool adc_tm_initialized;
+ int max_channels_available;
struct qpnp_adc_tm_sensor sensor[0];
};
@@ -163,29 +202,57 @@
u8 multi_meas_en;
u8 low_thr_int_chan_en;
u8 high_thr_int_chan_en;
+ u8 meas_interval_ctl;
};
static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
[QPNP_ADC_TM_M0_ADC_CH_SEL_CTL] = {QPNP_M0_LOW_THR_LSB,
QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
- QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0},
+ QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
+ QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
[QPNP_ADC_TM_M1_ADC_CH_SEL_CTL] = {QPNP_M1_LOW_THR_LSB,
QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
- QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1},
+ QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
+ QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
[QPNP_ADC_TM_M2_ADC_CH_SEL_CTL] = {QPNP_M2_LOW_THR_LSB,
QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
- QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2},
+ QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
+ QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
[QPNP_ADC_TM_M3_ADC_CH_SEL_CTL] = {QPNP_M3_LOW_THR_LSB,
QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
- QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3},
+ QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
+ QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
[QPNP_ADC_TM_M4_ADC_CH_SEL_CTL] = {QPNP_M4_LOW_THR_LSB,
QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
- QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4},
+ QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
+ QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_M5_ADC_CH_SEL_CTL] = {QPNP_M5_LOW_THR_LSB,
+ QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
+ QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
+ QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_M6_ADC_CH_SEL_CTL] = {QPNP_M6_LOW_THR_LSB,
+ QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
+ QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
+ QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
+ [QPNP_ADC_TM_M7_ADC_CH_SEL_CTL] = {QPNP_M7_LOW_THR_LSB,
+ QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
+ QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
+ QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
+ QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
+};
+
+static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
+ [SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
+ [SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
+ [SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
+ [SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
};
static int32_t qpnp_adc_tm_read_reg(int16_t reg, u8 *data)
@@ -217,40 +284,63 @@
return rc;
}
-static int32_t qpnp_adc_tm_enable(bool state)
+static int32_t qpnp_adc_tm_enable(void)
{
int rc = 0;
- u8 data = 0, enable_check = 0;
+ u8 data = 0;
- if (state) {
- data = QPNP_ADC_TM_EN;
- rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1,
- data);
- if (rc < 0)
- pr_err("adc-tm enable failed\n");
- } else {
- rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
- &enable_check);
+ data = QPNP_ADC_TM_EN;
+ rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+ if (rc < 0)
+ pr_err("adc-tm enable failed\n");
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_disable(void)
+{
+ u8 data = 0;
+ int rc = 0;
+
+ rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+ if (rc < 0)
+ pr_err("adc-tm disable failed\n");
+
+ return rc;
+}
+
+static int32_t qpnp_adc_tm_enable_if_channel_meas(void)
+{
+ u8 adc_tm_meas_en = 0;
+ int rc = 0;
+
+ /* Check if a measurement request is still required */
+ rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
+ &adc_tm_meas_en);
+ if (rc) {
+ pr_err("adc-tm-tm read status high failed with %d\n", rc);
+ return rc;
+ }
+
+ /* Enable only if there are pending measurement requests */
+ if (adc_tm_meas_en) {
+ qpnp_adc_tm_enable();
+
+ /* Request conversion */
+ rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
if (rc < 0) {
- pr_err("multi measurement read failed\n");
+ pr_err("adc-tm request conversion failed\n");
return rc;
}
-
- if (!enable_check) {
- data = 0;
- rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
- if (rc < 0)
- pr_err("adc-tm disable failed\n");
- }
}
return rc;
}
-static int32_t qpnp_adc_tm_enable_req_sts_check(void)
+static int32_t qpnp_adc_tm_req_sts_check(void)
{
u8 status1;
- int rc;
+ int rc, count = 0;
/* The VADC_TM bank needs to be disabled for new conversion request */
rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
@@ -260,19 +350,45 @@
}
/* Disable the bank if a conversion is occuring */
- if (status1 & QPNP_STATUS1_REQ_STS) {
- rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, 0);
+ while ((status1 & QPNP_STATUS1_REQ_STS) && (count < 5)) {
+ rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
if (rc < 0)
pr_err("adc-tm disable failed\n");
+ /* Wait time is based on the optimum sampling rate
+ * and adding enough time buffer to account for ADC conversions
+ * occuring on different peripheral banks */
+ usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
+ count++;
}
return rc;
}
+static int32_t qpnp_adc_tm_check_revision(uint32_t btm_chan_num)
+{
+ u8 rev;
+ int rc = 0;
+
+ rc = qpnp_adc_tm_read_reg(QPNP_REVISION3, &rev);
+ if (rc) {
+ pr_err("adc-tm revision read failed\n");
+ return rc;
+ }
+
+ if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
+ (btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
+ pr_debug("Version does not support more than 5 channels\n");
+ return -EINVAL;
+ }
+
+ return rc;
+}
static int32_t qpnp_adc_tm_mode_select(u8 mode_ctl)
{
int rc;
+ mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
+
/* VADC_BTM current sets mode to recurring measurements */
rc = qpnp_adc_tm_write_reg(QPNP_MODE_CTL, mode_ctl);
if (rc < 0)
@@ -281,13 +397,13 @@
return rc;
}
-static int32_t qpnp_adc_tm_timer_interval_select(
+static int32_t qpnp_adc_tm_timer_interval_select(uint32_t btm_chan,
struct qpnp_vadc_chan_properties *chan_prop)
{
int rc;
u8 meas_interval_timer2 = 0;
- /* Configure USB_ID to timer1, batt_therm to timer2 */
+ /* Configure kernel clients to timer1 */
switch (chan_prop->timer_select) {
case ADC_MEAS_TIMER_SELECT1:
rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL,
@@ -298,6 +414,7 @@
}
break;
case ADC_MEAS_TIMER_SELECT2:
+ /* Thermal channels uses timer2, default to 1 second */
rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
&meas_interval_timer2);
if (rc < 0) {
@@ -315,7 +432,6 @@
}
break;
case ADC_MEAS_TIMER_SELECT3:
- /* Thermal channels uses timer3, default to 1 second */
rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
&meas_interval_timer2);
if (rc < 0) {
@@ -336,34 +452,40 @@
return -EINVAL;
}
+ /* Select the timer to use for the corresponding channel */
+ adc_tm_data[btm_chan].meas_interval_ctl = chan_prop->timer_select;
+
return rc;
}
-static int32_t qpnp_adc_tm_meas_int_update(uint16_t reg_addr_src,
- u8 reg_addr_dst, bool state)
+static int32_t qpnp_adc_tm_reg_update(uint16_t addr,
+ u8 mask, bool state)
{
- u8 bit_mask_check = 0;
+ u8 reg_value = 0;
int rc = 0;
- rc = qpnp_adc_tm_read_reg(reg_addr_src, &bit_mask_check);
+ rc = qpnp_adc_tm_read_reg(addr, ®_value);
if (rc < 0) {
- pr_err("read failed for addr:%x\n", reg_addr_src);
+ pr_err("read failed for addr:0x%x\n", addr);
return rc;
}
+ reg_value = reg_value & ~mask;
if (state)
- bit_mask_check |= reg_addr_dst;
- else
- bit_mask_check &= ~reg_addr_dst;
+ reg_value |= mask;
- rc = qpnp_adc_tm_write_reg(reg_addr_src, bit_mask_check);
- if (rc < 0)
- pr_err("write failed for addr:%x\n", reg_addr_src);
+ pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
+ state, addr, reg_value, ~mask);
+ rc = qpnp_adc_tm_write_reg(addr, reg_value);
+ if (rc < 0) {
+ pr_err("write failed for addr:%x\n", addr);
+ return rc;
+ }
return rc;
}
-static int32_t qpnp_adc_tm_usbid_btm_thr_en(uint32_t btm_chan,
+static int32_t qpnp_adc_tm_thr_update(uint32_t btm_chan,
struct qpnp_vadc_chan_properties *chan_prop)
{
int rc = 0;
@@ -398,6 +520,9 @@
if (rc < 0)
pr_err("high threshold msb setting failed\n");
+ pr_debug("client requested low:%d and high:%d\n",
+ chan_prop->low_thr, chan_prop->high_thr);
+
return rc;
}
@@ -405,13 +530,29 @@
struct qpnp_vadc_chan_properties *chan_prop,
uint32_t amux_channel)
{
- int rc = 0;
+ struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+ int rc = 0, i = 0, chan_idx = 0;
+ bool chan_found = false;
+ u8 sensor_mask = 0;
- switch (btm_chan) {
- case QPNP_ADC_TM_M0_ADC_CH_SEL_CTL:
- case QPNP_ADC_TM_M1_ADC_CH_SEL_CTL:
+ while (i < adc_tm->max_channels_available) {
+ if (adc_tm->sensor[i].btm_channel_num == btm_chan) {
+ chan_idx = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
+
+ if ((i == adc_tm->max_channels_available) && (!chan_found)) {
+ pr_err("Channel not found\n");
+ return -EINVAL;
+ }
+
+ sensor_mask = 1 << chan_idx;
+ if (!adc_tm->sensor[chan_idx].thermal_node) {
/* Update low and high notification thresholds */
- rc = qpnp_adc_tm_usbid_btm_thr_en(btm_chan,
+ rc = qpnp_adc_tm_thr_update(btm_chan,
chan_prop);
if (rc < 0) {
pr_err("setting chan:%d threshold failed\n", btm_chan);
@@ -422,11 +563,11 @@
ADC_TM_LOW_THR_ENABLE) ||
(chan_prop->state_request ==
ADC_TM_HIGH_LOW_THR_ENABLE)) {
+ pr_debug("low sensor mask:%x with state:%d\n",
+ sensor_mask, chan_prop->state_request);
/* Enable low threshold's interrupt */
- rc = qpnp_adc_tm_meas_int_update(
- QPNP_ADC_TM_LOW_THR_INT_EN,
- adc_tm_data[btm_chan].low_thr_int_chan_en,
- true);
+ rc = qpnp_adc_tm_reg_update(
+ QPNP_ADC_TM_LOW_THR_INT_EN, sensor_mask, true);
if (rc < 0) {
pr_err("low thr enable err:%d\n", btm_chan);
return rc;
@@ -438,37 +579,22 @@
(chan_prop->state_request ==
ADC_TM_HIGH_LOW_THR_ENABLE)) {
/* Enable high threshold's interrupt */
- rc = qpnp_adc_tm_meas_int_update(
- QPNP_ADC_TM_HIGH_THR_INT_EN,
- adc_tm_data[btm_chan].high_thr_int_chan_en,
- true);
+ pr_debug("high sensor mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_reg_update(
+ QPNP_ADC_TM_HIGH_THR_INT_EN, sensor_mask, true);
if (rc < 0) {
pr_err("high thr enable err:%d\n", btm_chan);
return rc;
}
}
- /* intention fall through to configure common chan meas */
- case QPNP_ADC_TM_M2_ADC_CH_SEL_CTL:
- case QPNP_ADC_TM_M3_ADC_CH_SEL_CTL:
- case QPNP_ADC_TM_M4_ADC_CH_SEL_CTL:
- /* Configure AMUX control register for channel selection */
- rc = qpnp_adc_tm_write_reg(btm_chan, amux_channel);
- if (rc < 0) {
- pr_err("btm_chan:%d selection failed\n", btm_chan);
- return rc;
- }
+ }
- /* Enable corresponding BTM channel measurement */
- rc = qpnp_adc_tm_meas_int_update(
- QPNP_ADC_TM_MULTI_MEAS_EN,
- adc_tm_data[btm_chan].multi_meas_en, true);
- if (rc < 0) {
- pr_err("multi measurement en failed\n");
- return rc;
- }
- break;
- default:
- return -EINVAL;
+ /* Enable corresponding BTM channel measurement */
+ rc = qpnp_adc_tm_reg_update(
+ QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
+ if (rc < 0) {
+ pr_err("multi measurement en failed\n");
+ return rc;
}
return rc;
@@ -477,12 +603,17 @@
static int32_t qpnp_adc_tm_configure(
struct qpnp_adc_amux_properties *chan_prop)
{
- u8 decimation = 0;
+ u8 decimation = 0, op_cntrl = 0;
int rc = 0;
uint32_t btm_chan = 0;
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable();
+ if (rc)
+ return rc;
+
/* Check if a conversion is in progress */
- rc = qpnp_adc_tm_enable_req_sts_check();
+ rc = qpnp_adc_tm_req_sts_check();
if (rc < 0) {
pr_err("adc-tm req_sts check failed\n");
return rc;
@@ -495,9 +626,9 @@
return rc;
}
- /* Configure AMUX channel */
- rc = qpnp_adc_tm_write_reg(QPNP_ADC_CH_SEL_CTL,
- chan_prop->amux_channel);
+ /* Configure AMUX channel select for the corresponding BTM channel*/
+ btm_chan = chan_prop->chan_prop->tm_channel_select;
+ rc = qpnp_adc_tm_write_reg(btm_chan, chan_prop->amux_channel);
if (rc < 0) {
pr_err("adc-tm channel selection err\n");
return rc;
@@ -529,14 +660,14 @@
}
/* Measurement interval setup */
- rc = qpnp_adc_tm_timer_interval_select(chan_prop->chan_prop);
+ rc = qpnp_adc_tm_timer_interval_select(btm_chan,
+ chan_prop->chan_prop);
if (rc < 0) {
pr_err("adc-tm timer select failed\n");
return rc;
}
/* Channel configuration setup */
- btm_chan = chan_prop->chan_prop->tm_channel_select;
rc = qpnp_adc_tm_channel_configure(btm_chan, chan_prop->chan_prop,
chan_prop->amux_channel);
if (rc < 0) {
@@ -544,19 +675,21 @@
return rc;
}
- /* Enable bank */
- rc = qpnp_adc_tm_enable(true);
- if (rc)
- return rc;
-
/* Recurring interval measurement enable */
- rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
- QPNP_ADC_MEAS_INTERVAL_OP, true);
+ rc = qpnp_adc_tm_read_reg(QPNP_ADC_MEAS_INTERVAL_OP_CTL, &op_cntrl);
+ op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
+ op_cntrl, true);
if (rc < 0) {
pr_err("adc-tm meas interval op configure failed\n");
return rc;
}
+ /* Enable bank */
+ rc = qpnp_adc_tm_enable();
+ if (rc)
+ return rc;
+
/* Request conversion */
rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
if (rc < 0) {
@@ -570,12 +703,13 @@
static int qpnp_adc_tm_get_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode *mode)
{
- struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+ struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
- if (!adc_tm || !mode)
+ if (!adc_tm_sensor || qpnp_adc_tm_check_revision(
+ adc_tm_sensor->btm_channel_num) || !mode)
return -EINVAL;
- *mode = adc_tm->mode;
+ *mode = adc_tm_sensor->mode;
return 0;
}
@@ -586,12 +720,14 @@
struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
struct qpnp_adc_tm_drv *adc_drv = qpnp_adc_tm;
int rc = 0, channel;
+ u8 sensor_mask = 0;
- if (!adc_tm)
+ if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
return -EINVAL;
if (mode == THERMAL_DEVICE_ENABLED) {
- adc_drv->adc->amux_prop->amux_channel = adc_tm->sensor_num;
+ adc_drv->adc->amux_prop->amux_channel =
+ adc_tm->vadc_channel_num;
channel = adc_tm->sensor_num;
adc_drv->adc->amux_prop->decimation =
adc_drv->adc->adc_channels[channel].adc_decimation;
@@ -616,17 +752,31 @@
return -EINVAL;
}
} else if (mode == THERMAL_DEVICE_DISABLED) {
- rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
- adc_tm_data[adc_tm->btm_channel_num].multi_meas_en,
- false);
+ sensor_mask = 1 << adc_tm->sensor_num;
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable();
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ return rc;
+ }
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check();
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ return rc;
+ }
+
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
if (rc < 0) {
pr_err("multi measurement update failed\n");
return rc;
}
- rc = qpnp_adc_tm_enable(false);
+ rc = qpnp_adc_tm_enable_if_channel_meas();
if (rc < 0) {
- pr_err("adc-tm disable failed\n");
+ pr_err("re-enabling measurement failed\n");
return rc;
}
}
@@ -641,7 +791,8 @@
{
struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
- if (!adc_tm || !type || type < 0)
+ if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num)
+ || !type || type < 0)
return -EINVAL;
switch (trip) {
@@ -669,7 +820,8 @@
uint16_t reg_low_thr_lsb, reg_low_thr_msb;
uint16_t reg_high_thr_lsb, reg_high_thr_msb;
- if (!adc_tm)
+ if (!adc_tm || qpnp_adc_tm_check_revision(
+ adc_tm_sensor->btm_channel_num))
return -EINVAL;
btm_channel_num = adc_tm_sensor->btm_channel_num;
@@ -733,10 +885,11 @@
uint16_t reg_high_thr_lsb, reg_high_thr_msb;
int rc = 0, btm_channel_num;
- if (!adc_tm)
+ if (!adc_tm || qpnp_adc_tm_check_revision(
+ adc_tm_sensor->btm_channel_num))
return -EINVAL;
- tm_config.channel = adc_tm_sensor->sensor_num;
+ tm_config.channel = adc_tm_sensor->vadc_channel_num;
switch (trip) {
case ADC_TM_TRIP_HIGH_WARM:
tm_config.high_thr_temp = temp;
@@ -748,6 +901,8 @@
return -EINVAL;
}
+ pr_debug("requested a high - %d and low - %d with trip - %d\n",
+ tm_config.high_thr_temp, tm_config.low_thr_temp, trip);
rc = qpnp_adc_tm_scale_therm_voltage_pu2(&tm_config);
if (rc < 0) {
pr_err("Failed to lookup the adc-tm thresholds\n");
@@ -801,131 +956,102 @@
return 0;
}
-static void notify_uspace_qpnp_adc_tm_fn(struct work_struct *work)
+static void notify_battery_therm(struct qpnp_adc_tm_sensor *adc_tm)
+{
+ /* Battery therm's warm temperature translates to low voltage */
+ if (adc_tm->low_thr_notify) {
+ /* HIGH_STATE = WARM_TEMP for battery client */
+ adc_tm->btm_param->threshold_notification(
+ ADC_TM_WARM_STATE, adc_tm->btm_param->btm_ctx);
+ adc_tm->low_thr_notify = false;
+ }
+
+ /* Battery therm's cool temperature translates to high voltage */
+ if (adc_tm->high_thr_notify) {
+ /* LOW_STATE = COOL_TEMP for battery client */
+ adc_tm->btm_param->threshold_notification(
+ ADC_TM_COOL_STATE, adc_tm->btm_param->btm_ctx);
+ adc_tm->high_thr_notify = false;
+ }
+
+ return;
+}
+
+static void notify_clients(struct qpnp_adc_tm_sensor *adc_tm)
+{
+ /* For non batt therm clients */
+ if (adc_tm->low_thr_notify) {
+ pr_debug("notify kernel with low state\n");
+ adc_tm->btm_param->threshold_notification(
+ ADC_TM_LOW_STATE, adc_tm->btm_param->btm_ctx);
+ adc_tm->low_thr_notify = false;
+ }
+
+ if (adc_tm->high_thr_notify) {
+ pr_debug("notify kernel with high state\n");
+ adc_tm->btm_param->threshold_notification(
+ ADC_TM_HIGH_STATE, adc_tm->btm_param->btm_ctx);
+ adc_tm->high_thr_notify = false;
+ }
+
+ return;
+}
+
+static void notify_adc_tm_fn(struct work_struct *work)
{
struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
struct qpnp_adc_tm_sensor, work);
- sysfs_notify(&adc_tm->tz_dev->device.kobj,
+ if (adc_tm->thermal_node) {
+ sysfs_notify(&adc_tm->tz_dev->device.kobj,
NULL, "btm");
-}
-
-static void notify_usb_fn(struct work_struct *work)
-{
- struct qpnp_adc_tm_drv *adc_tm = container_of(work,
- struct qpnp_adc_tm_drv, usbid_work);
- int rc;
- u8 status_low, status_high;
-
- if (adc_tm->usb_id_param->threshold_notification != NULL) {
- rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
- &status_low);
- if (rc) {
- pr_err("adc-tm read low status failed\n");
- return;
+ pr_debug("notifying uspace client\n");
+ } else {
+ if (adc_tm->btm_param->threshold_notification != NULL) {
+ if (adc_tm->scale_type == SCALE_RBATT_THERM)
+ notify_battery_therm(adc_tm);
+ else
+ notify_clients(adc_tm);
}
-
- rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
- &status_high);
- if (rc) {
- pr_err("adc-tm read high status failed\n");
- return;
- }
-
- if (status_low & 1)
- adc_tm->usb_id_param->threshold_notification(
- ADC_TM_LOW_STATE, adc_tm->usb_id_param->usbid_ctx);
- else if (status_high & 1)
- adc_tm->usb_id_param->threshold_notification(
- ADC_TM_HIGH_STATE, adc_tm->usb_id_param->usbid_ctx);
}
return;
}
-static void notify_batt_fn(struct work_struct *work)
-{
- struct qpnp_adc_tm_drv *adc_tm = container_of(work,
- struct qpnp_adc_tm_drv, batt_work);
- int rc;
- u8 status_low, status_high;
-
- if (adc_tm->battery_param->threshold_notification != NULL) {
- rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
- &status_low);
- if (rc) {
- pr_err("adc-tm read low status failed\n");
- return;
- }
-
- rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
- &status_high);
- if (rc) {
- pr_err("adc-tm read high status failed\n");
- return;
- }
-
- if (status_low & QPNP_ADC_TM_LOW_THR_INT_EN_M1)
- adc_tm->battery_param->threshold_notification(
- ADC_TM_LOW_STATE, adc_tm->battery_param->btm_ctx);
- else if (status_high & QPNP_ADC_TM_HIGH_THR_INT_EN_M1)
- adc_tm->battery_param->threshold_notification(
- ADC_TM_HIGH_STATE, adc_tm->battery_param->btm_ctx);
- }
-
- return;
-}
-
-static int qpnp_adc_tm_activate_trip_type_fn(uint32_t btm_channel_num,
- enum thermal_trip_activation_mode mode, u8 *data, uint32_t reg)
-{
- u8 thr_int = 0;
- int rc = 0;
-
- rc = qpnp_adc_tm_read_reg(reg, &thr_int);
- if (rc) {
- pr_err("multi meas read failed\n");
- return rc;
- }
-
- thr_int = adc_tm_data[btm_channel_num].low_thr_int_chan_en;
-
- if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
- thr_int |= *data;
- else
- thr_int &= ~*data;
-
- rc = qpnp_adc_tm_write_reg(reg, thr_int);
- if (rc)
- pr_err("multi meas write failed\n");
-
- return rc;
-}
-
static int qpnp_adc_tm_activate_trip_type(struct thermal_zone_device *thermal,
int trip, enum thermal_trip_activation_mode mode)
{
struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
- int rc = 0;
+ int rc = 0, sensor_mask = 0;
u8 thr_int_en = 0;
+ bool state = false;
- if (!adc_tm)
+ if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
return -EINVAL;
+ if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
+ state = true;
+
+ sensor_mask = 1 << adc_tm->sensor_num;
+
+ pr_debug("Sensor number:%x with state:%d\n", adc_tm->sensor_num, state);
+
switch (trip) {
case ADC_TM_TRIP_HIGH_WARM:
+ /* low_thr (lower voltage) for higher temp */
thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
low_thr_int_chan_en;
- rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
- mode, &thr_int_en, QPNP_ADC_TM_LOW_THR_INT_EN);
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, state);
if (rc)
pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
break;
case ADC_TM_TRIP_LOW_COOL:
+ /* high_thr (higher voltage) for cooler temp */
thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
high_thr_int_chan_en;
- rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
- mode, &thr_int_en, QPNP_ADC_TM_HIGH_THR_INT_EN);
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, state);
if (rc)
pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
break;
@@ -941,12 +1067,20 @@
struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
u8 status_low = 0, status_high = 0, qpnp_adc_tm_meas_en = 0;
u8 adc_tm_low_enable = 0, adc_tm_high_enable = 0;
- u8 thr_int_disable = 0;
- int rc = 0, sensor_notify_num = 0;
+ u8 sensor_mask = 0;
+ int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0, btm_chan_num;
if (!adc_tm || !adc_tm->adc_tm_initialized)
return -ENODEV;
+ mutex_lock(&adc_tm->adc->adc_lock);
+
+ rc = qpnp_adc_tm_req_sts_check();
+ if (rc) {
+ pr_err("adc-tm-tm req sts check failed with %d\n", rc);
+ goto fail;
+ }
+
rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
if (rc) {
pr_err("adc-tm-tm read status low failed with %d\n", rc);
@@ -972,100 +1106,107 @@
adc_tm_high_enable = qpnp_adc_tm_meas_en & status_high;
if (adc_tm_high_enable) {
- sensor_notify_num = (adc_tm_high_enable >> 3);
- switch (adc_tm_high_enable) {
- case 1:
- case 2:
- {
- if (adc_tm_high_enable == 1)
- thr_int_disable =
- QPNP_ADC_TM_HIGH_THR_INT_EN_M0;
- else if (adc_tm_high_enable == 2)
- thr_int_disable =
- QPNP_ADC_TM_HIGH_THR_INT_EN_M1;
+ sensor_notify_num = adc_tm_high_enable;
+ while (i < adc_tm->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
- rc = qpnp_adc_tm_meas_int_update(
+ btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+ pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+ qpnp_adc_tm_meas_en);
+ if (!adc_tm->sensor[sensor_num].thermal_node) {
+ /* For non thermal registered clients
+ such as usb_id, vbatt, pmic_therm */
+ sensor_mask = 1 << sensor_num;
+ pr_debug("non thermal node - mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_reg_update(
QPNP_ADC_TM_HIGH_THR_INT_EN,
- thr_int_disable, false);
+ sensor_mask, false);
if (rc < 0) {
pr_err("high threshold int read failed\n");
goto fail;
}
-
- if (adc_tm_high_enable == 1)
- schedule_work(&adc_tm->usbid_work);
- else if (adc_tm_high_enable == 2)
- schedule_work(&adc_tm->batt_work);
- }
- break;
- case 4:
- case 8:
- case 16:
- {
- /* High voltage threshold is triggered by low temp */
+ adc_tm->sensor[sensor_num].high_thr_notify = true;
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding high voltage threshold which
+ is triggered by low temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
rc = qpnp_adc_tm_activate_trip_type(
- adc_tm->sensor[sensor_notify_num].tz_dev,
+ adc_tm->sensor[sensor_num].tz_dev,
ADC_TM_TRIP_LOW_COOL,
THERMAL_TRIP_ACTIVATION_DISABLED);
if (rc < 0) {
- pr_err("notify error:%d\n", sensor_notify_num);
+ pr_err("notify error:%d\n", sensor_num);
goto fail;
}
- schedule_work(&adc_tm->sensor[sensor_notify_num].work);
- }
- break;
- default:
- rc = -EINVAL;
}
}
if (adc_tm_low_enable) {
- sensor_notify_num = (adc_tm_low_enable >> 3);
- switch (adc_tm_low_enable) {
- case 1:
- case 2:
- {
- if (adc_tm_low_enable == 1)
- thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M0;
- else if (adc_tm_low_enable == 2)
- thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M1;
+ sensor_notify_num = adc_tm_low_enable;
+ i = 0;
+ while (i < adc_tm->max_channels_available) {
+ if ((sensor_notify_num & 0x1) == 1)
+ sensor_num = i;
+ sensor_notify_num >>= 1;
+ i++;
+ }
- rc = qpnp_adc_tm_meas_int_update(
+ btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+ pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+ qpnp_adc_tm_meas_en);
+ if (!adc_tm->sensor[sensor_num].thermal_node) {
+ /* For non thermal registered clients
+ such as usb_id, vbatt, pmic_therm */
+ pr_debug("non thermal node - mask:%x\n", sensor_mask);
+ sensor_mask = 1 << sensor_num;
+ rc = qpnp_adc_tm_reg_update(
QPNP_ADC_TM_LOW_THR_INT_EN,
- thr_int_disable, false);
+ sensor_mask, false);
if (rc < 0) {
- pr_err("low threshold int disable failed\n");
+ pr_err("low threshold int read failed\n");
goto fail;
}
-
- if (adc_tm_low_enable == 1)
- schedule_work(&adc_tm->usbid_work);
- else if (adc_tm_low_enable == 2)
- schedule_work(&adc_tm->batt_work);
- }
- break;
- case 4:
- case 8:
- case 16:
- {
- /* Low voltage threshold is triggered by high temp */
+ adc_tm->sensor[sensor_num].low_thr_notify = true;
+ } else {
+ /* Uses the thermal sysfs registered device to disable
+ the corresponding low voltage threshold which
+ is triggered by high temp */
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
rc = qpnp_adc_tm_activate_trip_type(
- adc_tm->sensor[sensor_notify_num].tz_dev,
+ adc_tm->sensor[sensor_num].tz_dev,
ADC_TM_TRIP_HIGH_WARM,
THERMAL_TRIP_ACTIVATION_DISABLED);
if (rc < 0) {
- pr_err("notify error:%d\n", sensor_notify_num);
+ pr_err("notify error:%d\n", sensor_num);
goto fail;
}
- schedule_work(&adc_tm->sensor[sensor_notify_num].work);
- }
- break;
- default:
- rc = -EINVAL;
}
}
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi meas disable for channel failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas();
+ if (rc < 0) {
+ pr_err("re-enabling measurement failed\n");
+ return rc;
+ }
fail:
+ mutex_unlock(&adc_tm->adc->adc_lock);
+
+ schedule_work(&adc_tm->sensor[sensor_num].work);
+
return rc;
}
@@ -1074,6 +1215,8 @@
int rc;
rc = qpnp_adc_tm_read_status();
+ if (rc < 0)
+ pr_err("adc-tm high thr work failed\n");
return;
}
@@ -1082,6 +1225,8 @@
static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
{
+ qpnp_adc_tm_disable();
+
schedule_work(&trigger_completion_adc_tm_high_thr_work);
return IRQ_HANDLED;
@@ -1092,6 +1237,8 @@
int rc;
rc = qpnp_adc_tm_read_status();
+ if (rc < 0)
+ pr_err("adc-tm low thr work failed\n");
return;
}
@@ -1099,6 +1246,8 @@
static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
{
+ qpnp_adc_tm_disable();
+
schedule_work(&trigger_completion_adc_tm_low_thr_work);
return IRQ_HANDLED;
@@ -1120,7 +1269,7 @@
struct qpnp_vadc_result result;
int rc = 0;
- rc = qpnp_vadc_read(adc_tm_sensor->sensor_num, &result);
+ rc = qpnp_vadc_read(adc_tm_sensor->vadc_channel_num, &result);
if (rc)
return rc;
@@ -1139,24 +1288,47 @@
.set_trip_temp = qpnp_adc_tm_set_trip_temp,
};
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param)
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param)
{
struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
- uint32_t channel;
+ uint32_t channel, dt_index = 0, scale_type = 0;
int rc = 0;
if (!adc_tm || !adc_tm->adc_tm_initialized)
return -ENODEV;
if (param->threshold_notification == NULL) {
- pr_err("No USB_ID high/low voltage notificaton??\n");
+ pr_err("No notification for high/low temp??\n");
return -EINVAL;
}
mutex_lock(&adc_tm->adc->adc_lock);
- adc_tm->adc->amux_prop->amux_channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
- channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+ channel = param->channel;
+ while ((adc_tm->adc->adc_channels[dt_index].channel_num
+ != channel) && (dt_index < adc_tm->max_channels_available))
+ dt_index++;
+
+ if (dt_index >= adc_tm->max_channels_available) {
+ pr_err("not a valid ADC_TM channel\n");
+ rc = -EINVAL;
+ goto fail_unlock;
+ }
+
+ rc = qpnp_adc_tm_check_revision(
+ adc_tm->sensor[dt_index].btm_channel_num);
+ if (rc < 0)
+ goto fail_unlock;
+
+ scale_type = adc_tm->adc->adc_channels[dt_index].adc_scale_fn;
+ if (scale_type >= SCALE_RSCALE_NONE) {
+ rc = -EBADF;
+ goto fail_unlock;
+ }
+
+ pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
+ channel, scale_type, dt_index);
+ adc_tm->adc->amux_prop->amux_channel = channel;
adc_tm->adc->amux_prop->decimation =
adc_tm->adc->adc_channels[channel].adc_decimation;
adc_tm->adc->amux_prop->hw_settle_time =
@@ -1167,10 +1339,11 @@
ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
ADC_MEAS1_INTERVAL_1S;
- qpnp_adc_usb_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
+ adc_tm_rscale_fn[scale_type].chan(param,
+ &adc_tm->adc->amux_prop->chan_prop->low_thr,
&adc_tm->adc->amux_prop->chan_prop->high_thr);
adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
- QPNP_ADC_TM_M0_ADC_CH_SEL_CTL;
+ adc_tm->sensor[dt_index].btm_channel_num;
adc_tm->adc->amux_prop->chan_prop->timer_select =
ADC_MEAS_TIMER_SELECT1;
adc_tm->adc->amux_prop->chan_prop->state_request =
@@ -1181,144 +1354,103 @@
goto fail_unlock;
}
- adc_tm->usb_id_param = param;
+ adc_tm->sensor[dt_index].btm_param = param;
+ adc_tm->sensor[dt_index].scale_type = scale_type;
fail_unlock:
mutex_unlock(&adc_tm->adc->adc_lock);
return rc;
}
+EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
+
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param)
+{
+ struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+ uint32_t channel, dt_index = 0, btm_chan_num;
+ u8 sensor_mask = 0;
+ int rc = 0;
+
+ if (!adc_tm || !adc_tm->adc_tm_initialized)
+ return -ENODEV;
+
+ mutex_lock(&adc_tm->adc->adc_lock);
+
+ /* Disable bank */
+ rc = qpnp_adc_tm_disable();
+ if (rc < 0) {
+ pr_err("adc-tm disable failed\n");
+ goto fail;
+ }
+
+ /* Check if a conversion is in progress */
+ rc = qpnp_adc_tm_req_sts_check();
+ if (rc < 0) {
+ pr_err("adc-tm req_sts check failed\n");
+ goto fail;
+ }
+
+ channel = param->channel;
+ while ((adc_tm->adc->adc_channels[dt_index].channel_num
+ != channel) && (dt_index < adc_tm->max_channels_available))
+ dt_index++;
+
+ if (dt_index >= adc_tm->max_channels_available) {
+ pr_err("not a valid ADC_TMN channel\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ btm_chan_num = adc_tm->sensor[dt_index].btm_channel_num;
+ sensor_mask = 1 << adc_tm->sensor[dt_index].sensor_num;
+
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int write failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("high threshold int enable failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_reg_update(QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi measurement en failed\n");
+ goto fail;
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas();
+ if (rc < 0)
+ pr_err("re-enabling measurement failed\n");
+
+fail:
+ mutex_unlock(&adc_tm->adc->adc_lock);
+
+ return rc;
+}
+EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
+
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param)
+{
+ param->channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+ return qpnp_adc_tm_channel_measure(param);
+}
EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
-static int32_t qpnp_adc_tm_chan_usbid_chan_btm_end(
- uint32_t btm_chan_num)
-{
- int32_t rc = 0;
-
- rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_LOW_THR_INT_EN,
- adc_tm_data[btm_chan_num].low_thr_int_chan_en,
- false);
- if (rc < 0) {
- pr_err("low threshold int write failed\n");
- return rc;
- }
-
- rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
- adc_tm_data[btm_chan_num].high_thr_int_chan_en,
- false);
- if (rc < 0) {
- pr_err("high threshold int enable failed\n");
- return rc;
- }
-
- rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
- adc_tm_data[btm_chan_num].multi_meas_en,
- false);
- if (rc < 0) {
- pr_err("multi measurement en failed\n");
- return rc;
- }
-
- rc = qpnp_adc_tm_enable(false);
- if (rc < 0)
- pr_err("TM disable failed\n");
-
- return rc;
-}
-
int32_t qpnp_adc_tm_usbid_end(void)
{
- struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
- int rc = 0;
+ struct qpnp_adc_tm_btm_param param;
- if (!adc_tm || !adc_tm->adc_tm_initialized)
- return -ENODEV;
-
- mutex_lock(&adc_tm->adc->adc_lock);
-
- rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
- QPNP_ADC_TM_M0_ADC_CH_SEL_CTL);
- if (rc < 0)
- pr_err("disabling thresholds for usb channel failed\n");
-
- mutex_unlock(&adc_tm->adc->adc_lock);
-
- return rc;
+ return qpnp_adc_tm_disable_chan_meas(¶m);
}
EXPORT_SYMBOL(qpnp_adc_tm_usbid_end);
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param)
-{
- struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
- uint32_t channel;
- int rc = 0;
-
- if (!adc_tm || !adc_tm->adc_tm_initialized)
- return -ENODEV;
-
- if (param->threshold_notification == NULL) {
- pr_err("No battery high/low temp notificaton??\n");
- return -EINVAL;
- }
-
- mutex_lock(&adc_tm->adc->adc_lock);
-
- adc_tm->adc->amux_prop->amux_channel = LR_MUX1_BATT_THERM;
- channel = LR_MUX1_BATT_THERM;
- adc_tm->adc->amux_prop->decimation =
- adc_tm->adc->adc_channels[channel].adc_decimation;
- adc_tm->adc->amux_prop->hw_settle_time =
- adc_tm->adc->adc_channels[channel].hw_settle_time;
- adc_tm->adc->amux_prop->fast_avg_setup =
- adc_tm->adc->adc_channels[channel].fast_avg_setup;
- adc_tm->adc->amux_prop->mode_sel =
- ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
- adc_tm->adc->amux_prop->chan_prop->meas_interval2 =
- ADC_MEAS2_INTERVAL_1S;
- qpnp_adc_btm_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
- &adc_tm->adc->amux_prop->chan_prop->high_thr);
- adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
- QPNP_ADC_TM_M1_ADC_CH_SEL_CTL;
- adc_tm->adc->amux_prop->chan_prop->timer_select =
- ADC_MEAS_TIMER_SELECT2;
- adc_tm->adc->amux_prop->chan_prop->state_request =
- param->state_request;
- rc = qpnp_adc_tm_configure(adc_tm->adc->amux_prop);
- if (rc) {
- pr_err("adc-tm configure failed with %d\n", rc);
- goto fail_unlock;
- }
-
- adc_tm->battery_param = param;
-
-fail_unlock:
- mutex_unlock(&adc_tm->adc->adc_lock);
-
- return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_configure);
-
-int32_t qpnp_adc_tm_btm_end(void)
-{
- struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
- int rc = 0;
-
- if (!adc_tm || !adc_tm->adc_tm_initialized)
- return -ENODEV;
-
- mutex_lock(&adc_tm->adc->adc_lock);
-
- rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
- QPNP_ADC_TM_M1_ADC_CH_SEL_CTL);
- if (rc < 0)
- pr_err("disabling thresholds for batt channel failed\n");
-
- mutex_unlock(&adc_tm->adc->adc_lock);
-
- return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_end);
-
int32_t qpnp_adc_tm_is_ready(void)
{
struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
@@ -1335,7 +1467,7 @@
struct device_node *node = spmi->dev.of_node, *child;
struct qpnp_adc_tm_drv *adc_tm;
struct qpnp_adc_drv *adc_qpnp;
- int32_t count_adc_channel_list = 0, rc, i = 0, j = 0;
+ int32_t count_adc_channel_list = 0, rc, sen_idx = 0;
u8 thr_init = 0;
if (!node)
@@ -1363,6 +1495,7 @@
return -ENOMEM;
}
+ qpnp_adc_tm = adc_tm;
adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
GFP_KERNEL);
if (!adc_qpnp) {
@@ -1430,41 +1563,45 @@
for_each_child_of_node(node, child) {
char name[25];
int btm_channel_num;
+ bool thermal_node = false;
+
rc = of_property_read_u32(child,
"qcom,btm-channel-number", &btm_channel_num);
if (rc) {
pr_err("Invalid btm channel number\n");
goto fail;
}
-
- if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
- (btm_channel_num != QPNP_ADC_TM_M1_ADC_CH_SEL_CTL)) {
+ adc_tm->sensor[sen_idx].btm_channel_num = btm_channel_num;
+ adc_tm->sensor[sen_idx].vadc_channel_num =
+ adc_tm->adc->adc_channels[sen_idx].channel_num;
+ adc_tm->sensor[sen_idx].sensor_num = sen_idx;
+ pr_debug("btm_chan:%x, vadc_chan:%x\n", btm_channel_num,
+ adc_tm->adc->adc_channels[sen_idx].channel_num);
+ if (thermal_node) {
/* Register with the thermal zone */
- adc_tm->sensor[i].mode = THERMAL_DEVICE_DISABLED;
- snprintf(name, sizeof(name), "qpnp_adc_tm_sensor%d", i);
- adc_tm->sensor[i].sensor_num =
- adc_tm->adc->adc_channels[j].channel_num;
- adc_tm->sensor[i].btm_channel_num = btm_channel_num;
- adc_tm->sensor[i].meas_interval =
+ pr_debug("thermal node%x\n", btm_channel_num);
+ adc_tm->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
+ adc_tm->sensor[sen_idx].thermal_node = true;
+ snprintf(name, sizeof(name),
+ adc_tm->adc->adc_channels[sen_idx].name);
+ adc_tm->sensor[sen_idx].meas_interval =
QPNP_ADC_TM_MEAS_INTERVAL;
- adc_tm->sensor[i].low_thr = QPNP_ADC_TM_M0_LOW_THR;
- adc_tm->sensor[i].high_thr = QPNP_ADC_TM_M0_HIGH_THR;
- adc_tm->sensor[i].tz_dev =
+ adc_tm->sensor[sen_idx].low_thr =
+ QPNP_ADC_TM_M0_LOW_THR;
+ adc_tm->sensor[sen_idx].high_thr =
+ QPNP_ADC_TM_M0_HIGH_THR;
+ adc_tm->sensor[sen_idx].tz_dev =
thermal_zone_device_register(name,
ADC_TM_TRIP_NUM,
- &adc_tm->sensor[i],
+ &adc_tm->sensor[sen_idx],
&qpnp_adc_tm_thermal_ops, 0, 0, 0, 0);
- if (IS_ERR(adc_tm->sensor[i].tz_dev))
+ if (IS_ERR(adc_tm->sensor[sen_idx].tz_dev))
pr_err("thermal device register failed.\n");
- INIT_WORK(&adc_tm->sensor[i].work,
- notify_uspace_qpnp_adc_tm_fn);
- i++;
}
- j++;
+ INIT_WORK(&adc_tm->sensor[sen_idx].work, notify_adc_tm_fn);
+ sen_idx++;
}
- INIT_WORK(&adc_tm->usbid_work, notify_usb_fn);
- INIT_WORK(&adc_tm->batt_work, notify_batt_fn);
- qpnp_adc_tm = adc_tm;
+ adc_tm->max_channels_available = count_adc_channel_list;
dev_set_drvdata(&spmi->dev, adc_tm);
rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
if (rc < 0) {
@@ -1486,6 +1623,7 @@
adc_tm->adc_tm_initialized = true;
+ pr_debug("OK\n");
return 0;
fail:
qpnp_adc_tm = NULL;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 63acde1..8806004 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -200,7 +200,6 @@
struct work_struct clock_off_w; /* work for actual clock off */
struct workqueue_struct *hsuart_wq; /* hsuart workqueue */
struct mutex clk_mutex; /* mutex to guard against clock off/clock on */
- struct work_struct reset_bam_rx; /* work for reset bam rx endpoint */
struct work_struct disconnect_rx_endpoint; /* disconnect rx_endpoint */
bool tty_flush_receive;
enum uart_core_type uart_type;
@@ -219,6 +218,7 @@
/* BLSP UART required BUS Scaling data */
struct msm_bus_scale_pdata *bus_scale_table;
bool rx_discard_flush_issued;
+ int rx_count_callback;
};
#define MSM_UARTDM_BURST_SIZE 16 /* DM burst size (in bytes) */
@@ -231,6 +231,7 @@
#define BUS_SCALING 1
#define BUS_RESET 0
#define RX_FLUSH_COMPLETE_TIMEOUT 300 /* In jiffies */
+#define BLSP_UART_CLK_FMAX 63160000
static struct dentry *debug_base;
static struct msm_hs_port q_uart_port[UARTDM_NR];
@@ -750,6 +751,17 @@
mb();
if (bps > 460800) {
uport->uartclk = bps * 16;
+ if (is_blsp_uart(msm_uport)) {
+ /* BLSP based UART supports maximum clock frequency
+ * of 63.16 Mhz. With this (63.16 Mhz) clock frequency
+ * UART can support baud rate of 3.94 Mbps which is
+ * equivalent to 4 Mbps.
+ * UART hardware is robust enough to handle this
+ * deviation to achieve baud rate ~4 Mbps.
+ */
+ if (bps == 4000000)
+ uport->uartclk = BLSP_UART_CLK_FMAX;
+ }
} else {
uport->uartclk = 7372800;
}
@@ -823,22 +835,6 @@
}
-/* Reset BAM RX Endpoint Pipe Index from workqueue context*/
-
-static void hsuart_reset_bam_rx_work(struct work_struct *w)
-{
- struct msm_hs_port *msm_uport = container_of(w, struct msm_hs_port,
- reset_bam_rx);
- struct uart_port *uport = &msm_uport->uport;
- struct msm_hs_rx *rx = &msm_uport->rx;
- struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
-
- sps_disconnect(sps_pipe_handle);
- msm_hs_spsconnect_rx(uport);
-
- msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
-}
-
/*
* termios : new ktermios
* oldtermios: old ktermios previous setting
@@ -1073,13 +1069,6 @@
if (!is_blsp_uart(msm_uport) && msm_uport->rx.flush != FLUSH_SHUTDOWN)
msm_uport->rx.flush = FLUSH_STOP;
- /* During uart port close, due to spurious rx stale interrupt,
- * the rx state machine is causing BUG_ON to be hit in
- * msm_hs_shutdown causing kernel panic.
- * Hence fixing the same by handling the rx state machine.
- */
- if (is_blsp_uart(msm_uport) && msm_uport->rx.flush == FLUSH_DATA_READY)
- msm_uport->rx.flush = FLUSH_SHUTDOWN;
}
/* Transmit the next chunk of data */
@@ -1178,10 +1167,6 @@
printk(KERN_ERR "Error: rx started in buffer state = %x",
buffer_pending);
- if (is_blsp_uart(msm_uport)) {
- /* Issue RX BAM Start IFC command */
- msm_hs_write(uport, UARTDM_CR_ADDR, START_RX_BAM_IFC);
- }
msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE);
msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE);
@@ -1204,6 +1189,19 @@
/* Calling next DMOV API. Hence mb() here. */
mb();
+ if (is_blsp_uart(msm_uport)) {
+ /*
+ * RX-transfer will be automatically re-activated
+ * after last data of previous transfer was read.
+ */
+ data = (RX_STALE_AUTO_RE_EN | RX_TRANS_AUTO_RE_ACTIVATE |
+ RX_DMRX_CYCLIC_EN);
+ msm_hs_write(uport, UARTDM_RX_TRANS_CTRL_ADDR, data);
+ /* Issue RX BAM Start IFC command */
+ msm_hs_write(uport, UARTDM_CR_ADDR, START_RX_BAM_IFC);
+ mb();
+ }
+
msm_uport->rx.flush = FLUSH_NONE;
if (is_blsp_uart(msm_uport)) {
@@ -1276,7 +1274,6 @@
{
int retval;
int rx_count;
- static int remaining_rx_count, bytes_pending;
unsigned long status;
unsigned long flags;
unsigned int error_f = 0;
@@ -1284,17 +1281,24 @@
struct msm_hs_port *msm_uport;
unsigned int flush;
struct tty_struct *tty;
+ struct sps_event_notify *notify;
+ struct msm_hs_rx *rx;
+ struct sps_pipe *sps_pipe_handle;
+ u32 sps_flags = SPS_IOVEC_FLAG_EOT;
msm_uport = container_of((struct tasklet_struct *)tlet_ptr,
struct msm_hs_port, rx.tlet);
uport = &msm_uport->uport;
tty = uport->state->port.tty;
+ notify = &msm_uport->notify;
+ rx = &msm_uport->rx;
status = msm_hs_read(uport, UARTDM_SR_ADDR);
spin_lock_irqsave(&uport->lock, flags);
- msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
+ if (!is_blsp_uart(msm_uport))
+ msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
/* overflow is not connect to data in a FIFO */
if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
@@ -1351,24 +1355,13 @@
if (flush >= FLUSH_DATA_INVALID)
goto out;
- rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
-
if (is_blsp_uart(msm_uport)) {
- if (rx_count > UARTDM_RX_BUF_SIZE) {
- if (bytes_pending) {
- rx_count = remaining_rx_count;
- bytes_pending = 0;
- } else {
- remaining_rx_count = rx_count -
- UARTDM_RX_BUF_SIZE;
- if (remaining_rx_count)
- bytes_pending = 1;
- rx_count = UARTDM_RX_BUF_SIZE;
- }
- }
+ rx_count = msm_uport->rx_count_callback;
+ } else {
+ rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
+ /* order the read of rx.buffer */
+ rmb();
}
- /* order the read of rx.buffer */
- rmb();
if (0 != (uport->read_status_mask & CREAD)) {
retval = tty_insert_flip_string(tty, msm_uport->rx.buffer,
@@ -1382,9 +1375,17 @@
/* order the read of rx.buffer and the start of next rx xfer */
wmb();
- if (!msm_uport->rx.buffer_pending)
- msm_hs_start_rx_locked(uport);
-
+ if (!msm_uport->rx.buffer_pending) {
+ if (is_blsp_uart(msm_uport)) {
+ msm_uport->rx.flush = FLUSH_NONE;
+ sps_pipe_handle = rx->prod.pipe_handle;
+ /* Queue transfer request to SPS */
+ sps_transfer_one(sps_pipe_handle, rx->rbuffer,
+ UARTDM_RX_BUF_SIZE, msm_uport, sps_flags);
+ } else {
+ msm_hs_start_rx_locked(uport);
+ }
+ }
out:
if (msm_uport->rx.buffer_pending) {
if (hs_serial_debug_mask)
@@ -1502,7 +1503,10 @@
struct msm_hs_port *msm_uport =
(struct msm_hs_port *)
((struct sps_event_notify *)notify)->user;
+ struct uart_port *uport;
+ unsigned long flags;
+ uport = &(msm_uport->uport);
msm_uport->notify = *notify;
pr_debug("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
__func__, notify->event_id,
@@ -1510,8 +1514,12 @@
notify->data.transfer.iovec.size,
notify->data.transfer.iovec.flags);
- if (msm_uport->rx.flush == FLUSH_NONE)
+ if (msm_uport->rx.flush == FLUSH_NONE) {
+ spin_lock_irqsave(&uport->lock, flags);
+ msm_uport->rx_count_callback = notify->data.transfer.iovec.size;
+ spin_unlock_irqrestore(&uport->lock, flags);
tasklet_schedule(&msm_uport->rx.tlet);
+ }
}
/*
@@ -1691,6 +1699,8 @@
int ret;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
struct circ_buf *tx_buf = &uport->state->xmit;
+ struct msm_hs_rx *rx = &msm_uport->rx;
+ struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
mutex_lock(&msm_uport->clk_mutex);
spin_lock_irqsave(&uport->lock, flags);
@@ -1717,26 +1727,26 @@
switch (msm_uport->clk_req_off_state) {
case CLK_REQ_OFF_START:
msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED;
- if (is_blsp_uart(msm_uport)) {
- /* Stale interrupt when RX-FIFO is empty
- * will fire if STALE_IRQ_EMPTY bit is set
- * for UART Core v1.4
- */
- msm_hs_write(uport, UARTDM_BCR_ADDR,
- UARTDM_BCR_STALE_IRQ_EMPTY);
+
+ if (!is_blsp_uart(msm_uport)) {
+ msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
+ /*
+ * Before returning make sure that device writel
+ * completed. Hence mb() requires here.
+ */
+ mb();
}
- msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
- /*
- * Before returning make sure that device writel completed.
- * Hence mb() requires here.
- */
- mb();
spin_unlock_irqrestore(&uport->lock, flags);
mutex_unlock(&msm_uport->clk_mutex);
return 0; /* RXSTALE flush not complete - retry */
case CLK_REQ_OFF_RXSTALE_ISSUED:
case CLK_REQ_OFF_FLUSH_ISSUED:
spin_unlock_irqrestore(&uport->lock, flags);
+ if (is_blsp_uart(msm_uport)) {
+ msm_uport->clk_req_off_state =
+ CLK_REQ_OFF_RXSTALE_FLUSHED;
+ sps_disconnect(sps_pipe_handle);
+ }
mutex_unlock(&msm_uport->clk_mutex);
return 0; /* RXSTALE flush not complete - retry */
case CLK_REQ_OFF_RXSTALE_FLUSHED:
@@ -1846,24 +1856,13 @@
mb();
if (msm_uport->clk_req_off_state ==
- CLK_REQ_OFF_RXSTALE_ISSUED) {
+ CLK_REQ_OFF_RXSTALE_ISSUED)
msm_uport->clk_req_off_state =
- CLK_REQ_OFF_FLUSH_ISSUED;
+ CLK_REQ_OFF_FLUSH_ISSUED;
- if (is_blsp_uart(msm_uport)) {
- /* Reset BCR Register for UARTDM Core v14*/
- msm_hs_write(uport, UARTDM_BCR_ADDR, 0x0);
- }
- }
-
- if (rx->flush == FLUSH_NONE) {
+ if (!is_blsp_uart(msm_uport) && (rx->flush == FLUSH_NONE)) {
rx->flush = FLUSH_DATA_READY;
- if (is_blsp_uart(msm_uport)) {
- queue_work(msm_uport->hsuart_wq,
- &msm_uport->reset_bam_rx);
- } else {
- msm_dmov_flush(msm_uport->dma_rx_channel, 1);
- }
+ msm_dmov_flush(msm_uport->dma_rx_channel, 1);
}
}
/* tx ready interrupt */
@@ -1993,8 +1992,14 @@
mb();
}
hrtimer_try_to_cancel(&msm_uport->clk_off_timer);
- if (msm_uport->rx.flush == FLUSH_SHUTDOWN)
+ if (msm_uport->rx.flush == FLUSH_SHUTDOWN) {
+ if (is_blsp_uart(msm_uport)) {
+ spin_unlock_irqrestore(&uport->lock, flags);
+ msm_hs_spsconnect_rx(uport);
+ spin_lock_irqsave(&uport->lock, flags);
+ }
msm_hs_start_rx_locked(uport);
+ }
if (msm_uport->rx.flush == FLUSH_STOP)
msm_uport->rx.flush = FLUSH_IGNORE;
msm_uport->clk_state = MSM_HS_CLK_ON;
@@ -2265,9 +2270,10 @@
tx->command_ptr->dst_row_addr =
msm_uport->uport.mapbase + UARTDM_TF_ADDR;
+
+ msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
}
- msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
/* Enable reading the current CTS, no harm even if CTS is ignored */
msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
@@ -2378,7 +2384,10 @@
}
/* Set up Uart Receive */
- msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
+ if (is_blsp_uart(msm_uport))
+ msm_hs_write(uport, UARTDM_RFWR_ADDR, 32);
+ else
+ msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
@@ -2975,9 +2984,6 @@
INIT_WORK(&msm_uport->clock_off_w, hsuart_clock_off_work);
- /* Init work for Reset Rx bam endpoints */
- INIT_WORK(&msm_uport->reset_bam_rx, hsuart_reset_bam_rx_work);
-
/* Init work for sps_disconnect in stop_rx_locked */
INIT_WORK(&msm_uport->disconnect_rx_endpoint,
hsuart_disconnect_rx_endpoint_work);
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index 9fa4f55..cdd0450 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -68,6 +68,14 @@
*/
#define UARTDM_BCR_STALE_IRQ_EMPTY 0x2
+/* TRANSFER_CONTROL Register for UARTDM Core v1.4 */
+#define UARTDM_RX_TRANS_CTRL_ADDR 0xcc
+
+/* TRANSFER_CONTROL Register bits */
+#define RX_STALE_AUTO_RE_EN 0x1
+#define RX_TRANS_AUTO_RE_ACTIVATE 0x2
+#define RX_DMRX_CYCLIC_EN 0x4
+
/* write only register */
#define UARTDM_CSR_115200 0xFF
#define UARTDM_CSR_57600 0xEE
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 265a685..f9a26cf 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -541,8 +541,7 @@
else
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
- if (of_get_property(node, "tx-fifo-resize", NULL))
- dwc->needs_fifo_resize = true;
+ dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
pm_runtime_no_callbacks(dev);
pm_runtime_set_active(dev);
@@ -667,11 +666,22 @@
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id of_dwc3_match[] = {
+ {
+ .compatible = "synopsys,dwc3"
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, of_dwc3_match);
+#endif
+
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
.remove = __devexit_p(dwc3_remove),
.driver = {
.name = "dwc3",
+ .of_match_table = of_match_ptr(of_dwc3_match),
},
};
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index e5aca6f..9fad90c 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -31,6 +31,7 @@
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/qpnp-misc.h>
#include <linux/usb/msm_hsusb.h>
#include <linux/regulator/consumer.h>
#include <linux/power_supply.h>
@@ -187,7 +188,7 @@
enum usb_chg_state chg_state;
int pmic_id_irq;
struct work_struct id_work;
- struct qpnp_adc_tm_usbid_param adc_param;
+ struct qpnp_adc_tm_btm_param adc_param;
struct delayed_work init_adc_work;
bool id_adc_detect;
u8 dcd_retries;
@@ -535,6 +536,7 @@
static int dwc3_msm_dbm_ep_unconfig(u8 usb_ep)
{
u8 dbm_ep;
+ u32 data;
dev_dbg(context->dev, "%s\n", __func__);
@@ -548,10 +550,18 @@
context->ep_num_mapping[dbm_ep] = 0;
- dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), 0);
+ data = dwc3_msm_read_reg(context->base, DBM_EP_CFG(dbm_ep));
+ data &= (~0x1);
+ dwc3_msm_write_reg(context->base, DBM_EP_CFG(dbm_ep), data);
/* Reset the dbm endpoint */
dwc3_msm_dbm_ep_soft_reset(dbm_ep, true);
+ /*
+ * 10 usec delay is required before deasserting DBM endpoint reset
+ * according to hardware programming guide.
+ */
+ udelay(10);
+ dwc3_msm_dbm_ep_soft_reset(dbm_ep, false);
return 0;
}
@@ -888,6 +898,8 @@
}
(*new_ep_ops) = (*ep->ops);
new_ep_ops->queue = dwc3_msm_ep_queue;
+ new_ep_ops->disable = ep->ops->disable;
+
ep->ops = new_ep_ops;
/*
@@ -1328,24 +1340,27 @@
dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1, 0x07, 0x5);
}
-static void dwc3_msm_block_reset(void)
+static void dwc3_msm_block_reset(bool core_reset)
{
+
struct dwc3_msm *mdwc = context;
int ret = 0;
- ret = dwc3_msm_link_clk_reset(1);
- if (ret)
- return;
+ if (core_reset) {
+ ret = dwc3_msm_link_clk_reset(1);
+ if (ret)
+ return;
- usleep_range(1000, 1200);
- ret = dwc3_msm_link_clk_reset(0);
- if (ret)
- return;
+ usleep_range(1000, 1200);
+ ret = dwc3_msm_link_clk_reset(0);
+ if (ret)
+ return;
- usleep_range(10000, 12000);
+ usleep_range(10000, 12000);
- /* Reinitialize QSCRATCH registers after block reset */
- dwc3_msm_qscratch_reg_init(mdwc);
+ /* Reinitialize QSCRATCH registers after block reset */
+ dwc3_msm_qscratch_reg_init(mdwc);
+ }
/* Reset the DBM */
dwc3_msm_dbm_soft_reset(1);
@@ -2071,16 +2086,25 @@
static void dwc3_id_work(struct work_struct *w)
{
struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm, id_work);
+ int ret;
/* Give external client a chance to handle */
- if (!mdwc->ext_inuse) {
- if (usb_ext) {
- int ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
- dwc3_ext_notify_online);
- dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
- __func__, ret);
- mdwc->ext_inuse = (ret == 0);
+ if (!mdwc->ext_inuse && usb_ext) {
+ if (mdwc->pmic_id_irq)
+ disable_irq(mdwc->pmic_id_irq);
+
+ ret = usb_ext->notify(usb_ext->ctxt, mdwc->id_state,
+ dwc3_ext_notify_online);
+ dev_dbg(mdwc->dev, "%s: external handler returned %d\n",
+ __func__, ret);
+
+ if (mdwc->pmic_id_irq) {
+ /* ID may have changed while IRQ disabled; update it */
+ mdwc->id_state = !!irq_read_line(mdwc->pmic_id_irq);
+ enable_irq(mdwc->pmic_id_irq);
}
+
+ mdwc->ext_inuse = (ret == 0);
}
if (!mdwc->ext_inuse) { /* notify OTG */
@@ -2092,10 +2116,14 @@
static irqreturn_t dwc3_pmic_id_irq(int irq, void *data)
{
struct dwc3_msm *mdwc = data;
+ enum dwc3_id_state id;
/* If we can't read ID line state for some reason, treat it as float */
- mdwc->id_state = !!irq_read_line(irq);
- queue_work(system_nrt_wq, &mdwc->id_work);
+ id = !!irq_read_line(irq);
+ if (mdwc->id_state != id) {
+ mdwc->id_state = id;
+ queue_work(system_nrt_wq, &mdwc->id_work);
+ }
return IRQ_HANDLED;
}
@@ -2144,7 +2172,7 @@
mdwc->adc_param.high_thr = adc_high_threshold;
mdwc->adc_param.timer_interval = adc_meas_interval;
mdwc->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
- mdwc->adc_param.usbid_ctx = mdwc;
+ mdwc->adc_param.btm_ctx = mdwc;
mdwc->adc_param.threshold_notification = dwc3_adc_notification;
ret = qpnp_adc_tm_usbid_configure(&mdwc->adc_param);
@@ -2355,7 +2383,7 @@
goto free_hs_ldo_init;
}
- msm->ext_xceiv.id = DWC3_ID_FLOAT;
+ msm->id_state = msm->ext_xceiv.id = DWC3_ID_FLOAT;
msm->ext_xceiv.otg_capability = of_property_read_bool(node,
"qcom,otg-capability");
msm->charger.charging_disabled = of_property_read_bool(node,
@@ -2383,17 +2411,30 @@
if (msm->ext_xceiv.otg_capability) {
msm->pmic_id_irq = platform_get_irq_byname(pdev, "pmic_id_irq");
if (msm->pmic_id_irq > 0) {
- ret = devm_request_irq(&pdev->dev, msm->pmic_id_irq,
- dwc3_pmic_id_irq,
- IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING,
- "dwc3_msm_pmic_id", msm);
- if (ret) {
- dev_err(&pdev->dev, "irqreq IDINT failed\n");
+ /* check if PMIC ID IRQ is supported */
+ ret = qpnp_misc_irqs_available(&pdev->dev);
+
+ if (ret == -EPROBE_DEFER) {
+ /* qpnp hasn't probed yet; defer dwc probe */
goto disable_hs_ldo;
+ } else if (ret == 0) {
+ msm->pmic_id_irq = 0;
+ } else {
+ ret = devm_request_irq(&pdev->dev,
+ msm->pmic_id_irq,
+ dwc3_pmic_id_irq,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "dwc3_msm_pmic_id", msm);
+ if (ret) {
+ dev_err(&pdev->dev, "irqreq IDINT failed\n");
+ goto disable_hs_ldo;
+ }
+ enable_irq_wake(msm->pmic_id_irq);
}
- enable_irq_wake(msm->pmic_id_irq);
- } else {
+ }
+
+ if (msm->pmic_id_irq <= 0) {
/* If no PMIC ID IRQ, use ADC for ID pin detection */
queue_work(system_nrt_wq, &msm->init_adc_work.work);
device_create_file(&pdev->dev, &dev_attr_adc_enable);
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 01fad76..ca1f817 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -206,6 +206,20 @@
return ret;
}
dwc3_otg_notify_host_mode(otg, on);
+
+ /*
+ * Perform USB hardware RESET (both core reset and DBM reset)
+ * when moving from host to peripheral. This is required for
+ * peripheral mode to work.
+ */
+ if (ext_xceiv && ext_xceiv->otg_capability &&
+ ext_xceiv->ext_block_reset)
+ ext_xceiv->ext_block_reset(true);
+
+ /* re-init core and OTG registers as block reset clears these */
+ dwc3_post_host_reset_core_init(dwc);
+ if (ext_xceiv && !ext_xceiv->otg_capability)
+ dwc3_otg_reset(dotg);
}
return 0;
@@ -253,7 +267,6 @@
{
struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
- struct dwc3 *dwc = dotg->dwc;
if (!otg->gadget)
return -EINVAL;
@@ -262,20 +275,11 @@
dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
__func__, otg->gadget->name);
- /*
- * Hardware reset is required to support below scenarios:
- * 1. Host <-> peripheral switching
- * 2. Once an endpoint is configured in DBM (BAM) mode, it
- * can be unconfigured only after RESET
- */
+ /* Core reset is not required during start peripheral. Only
+ * DBM reset is required, hence perform only DBM reset here */
if (ext_xceiv && ext_xceiv->otg_capability &&
ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset();
-
- /* re-init core and OTG registers as block reset clears these */
- dwc3_post_host_reset_core_init(dwc);
- if (ext_xceiv && !ext_xceiv->otg_capability)
- dwc3_otg_reset(dotg);
+ ext_xceiv->ext_block_reset(false);
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
@@ -422,6 +426,9 @@
if (!init) {
init = true;
+ if (!work_busy(&dotg->sm_work))
+ schedule_work(&dotg->sm_work);
+
complete(&dotg->dwc3_xcvr_vbus_init);
dev_dbg(phy->dev, "XCVR: BSV init complete\n");
return;
@@ -490,6 +497,9 @@
power_supply_set_supply_type(dotg->psy, power_supply_type);
+ if ((dotg->charger->chg_type == DWC3_CDP_CHARGER) && mA > 2)
+ mA = DWC3_IDEV_CHG_MAX;
+
if (dotg->charger->max_power == mA)
return 0;
@@ -603,8 +613,11 @@
* driver initialization. Wait for it.
*/
ret = wait_for_completion_timeout(&dotg->dwc3_xcvr_vbus_init, HZ * 5);
- if (!ret)
+ if (!ret) {
dev_err(phy->dev, "%s: completion timeout\n", __func__);
+ /* We can safely assume no cable connected */
+ set_bit(ID, &dotg->inputs);
+ }
ext_xceiv = dotg->ext_xceiv;
dwc3_otg_reset(dotg);
diff --git a/drivers/usb/dwc3/dwc3_otg.h b/drivers/usb/dwc3/dwc3_otg.h
index d3b1b4a..c2fab53 100644
--- a/drivers/usb/dwc3/dwc3_otg.h
+++ b/drivers/usb/dwc3/dwc3_otg.h
@@ -109,7 +109,7 @@
void (*notify_ext_events)(struct usb_otg *otg,
enum dwc3_ext_events ext_event);
/* for block reset USB core */
- void (*ext_block_reset)(void);
+ void (*ext_block_reset)(bool core_reset);
};
/* for external transceiver driver */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 5b97148..d4bdf99 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -77,8 +77,8 @@
#include "f_rndis.c"
#include "rndis.c"
#include "f_qc_ecm.c"
-#include "u_bam_data.c"
#include "f_mbim.c"
+#include "u_bam_data.c"
#include "f_ecm.c"
#include "f_qc_rndis.c"
#include "u_ether.c"
@@ -865,10 +865,18 @@
fmbim_cleanup();
}
+
+/* mbim transport string */
+static char mbim_transports[MAX_XPORT_STR_LEN];
+
static int mbim_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
- return mbim_bind_config(c, 0);
+ char *trans;
+
+ pr_debug("%s: mbim transport is %s", __func__, mbim_transports);
+ trans = strim(mbim_transports);
+ return mbim_bind_config(c, 0, trans);
}
static int mbim_function_ctrlrequest(struct android_usb_function *f,
@@ -878,12 +886,34 @@
return mbim_ctrlrequest(cdev, c);
}
+static ssize_t mbim_transports_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", mbim_transports);
+}
+
+static ssize_t mbim_transports_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ strlcpy(mbim_transports, buf, sizeof(mbim_transports));
+ return size;
+}
+
+static DEVICE_ATTR(mbim_transports, S_IRUGO | S_IWUSR, mbim_transports_show,
+ mbim_transports_store);
+
+static struct device_attribute *mbim_function_attributes[] = {
+ &dev_attr_mbim_transports,
+ NULL
+};
+
static struct android_usb_function mbim_function = {
.name = "usb_mbim",
.cleanup = mbim_function_cleanup,
.bind_config = mbim_function_bind_config,
.init = mbim_function_init,
.ctrlrequest = mbim_function_ctrlrequest,
+ .attributes = mbim_function_attributes,
};
#ifdef CONFIG_SND_PCM
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 893f315..5a3d753 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -84,6 +84,7 @@
wait_queue_head_t read_wq;
wait_queue_head_t write_wq;
+ enum transport_type xport;
u8 port_num;
struct data_port bam_port;
struct mbim_notify_port not_port;
@@ -143,6 +144,9 @@
#define NTB_OUT_SIZE (0x1000)
#define NDP_IN_DIVISOR (0x4)
+#define NTB_DEFAULT_IN_SIZE_IPA (0x2000)
+#define NTB_OUT_SIZE_IPA (0x2000)
+
#define FORMATS_SUPPORTED USB_CDC_NCM_NTB16_SUPPORTED
static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
@@ -341,6 +345,7 @@
/* MBIM control descriptors */
(struct usb_descriptor_header *) &mbim_control_intf,
(struct usb_descriptor_header *) &mbim_header_desc,
+ (struct usb_descriptor_header *) &mbim_union_desc,
(struct usb_descriptor_header *) &mbb_desc,
(struct usb_descriptor_header *) &ext_mbb_desc,
(struct usb_descriptor_header *) &hs_mbim_notify_desc,
@@ -659,26 +664,49 @@
return 0;
}
+int mbim_configure_params(void)
+{
+ struct teth_aggr_params aggr_params;
+ int ret = 0;
+
+ aggr_params.dl.aggr_prot = TETH_AGGR_PROTOCOL_MBIM;
+ aggr_params.dl.max_datagrams = ntb_parameters.wNtbOutMaxDatagrams;
+ aggr_params.dl.max_transfer_size_byte = ntb_parameters.dwNtbInMaxSize;
+
+ aggr_params.ul.aggr_prot = TETH_AGGR_PROTOCOL_MBIM;
+ aggr_params.ul.max_datagrams = ntb_parameters.wNtbOutMaxDatagrams;
+ aggr_params.ul.max_transfer_size_byte = ntb_parameters.dwNtbOutMaxSize;
+
+ ret = teth_bridge_set_aggr_params(&aggr_params);
+ if (ret)
+ pr_err("%s: teth_bridge_set_aggr_params failed\n", __func__);
+
+ return ret;
+}
+
static int mbim_bam_connect(struct f_mbim *dev)
{
int ret;
u8 src_connection_idx, dst_connection_idx;
struct usb_gadget *gadget = dev->cdev->gadget;
+ enum peer_bam bam_name = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
+ IPA_P_BAM : A2_P_BAM;
pr_info("dev:%p portno:%d\n", dev, dev->port_num);
- src_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
- USB_TO_PEER_PERIPHERAL, dev->port_num);
- dst_connection_idx = usb_bam_get_connection_idx(gadget->name, A2_P_BAM,
- PEER_PERIPHERAL_TO_USB, dev->port_num);
+ src_connection_idx = usb_bam_get_connection_idx(gadget->name, bam_name,
+ USB_TO_PEER_PERIPHERAL, dev->port_num);
+ dst_connection_idx = usb_bam_get_connection_idx(gadget->name, bam_name,
+ PEER_PERIPHERAL_TO_USB, dev->port_num);
if (src_connection_idx < 0 || dst_connection_idx < 0) {
pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
return ret;
}
ret = bam_data_connect(&dev->bam_port, dev->port_num,
- USB_GADGET_XPORT_BAM2BAM, src_connection_idx,
- dst_connection_idx, USB_FUNC_MBIM);
+ dev->xport, src_connection_idx, dst_connection_idx,
+ USB_FUNC_MBIM);
+
if (ret) {
pr_err("bam_data_setup failed: err:%d\n",
ret);
@@ -1603,7 +1631,8 @@
* Context: single threaded during gadget setup
* Returns zero on success, else negative errno.
*/
-int mbim_bind_config(struct usb_configuration *c, unsigned portno)
+int mbim_bind_config(struct usb_configuration *c, unsigned portno,
+ char *xport_name)
{
struct f_mbim *mbim = NULL;
int status = 0;
@@ -1662,6 +1691,19 @@
mbim->function.disable = mbim_disable;
mbim->function.suspend = mbim_suspend;
mbim->function.resume = mbim_resume;
+ mbim->xport = str_to_xport(xport_name);
+
+ if (mbim->xport != USB_GADGET_XPORT_BAM2BAM_IPA) {
+ /* Use BAM2BAM by default if not IPA */
+ mbim->xport = USB_GADGET_XPORT_BAM2BAM;
+ } else {
+ /* For IPA we use limit of 16 */
+ ntb_parameters.wNtbOutMaxDatagrams = 16;
+ /* For IPA this is proven to give maximum throughput */
+ ntb_parameters.dwNtbInMaxSize =
+ cpu_to_le32(NTB_DEFAULT_IN_SIZE_IPA);
+ ntb_parameters.dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE_IPA);
+ }
INIT_LIST_HEAD(&mbim->cpkt_req_q);
INIT_LIST_HEAD(&mbim->cpkt_resp_q);
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 6518095..cece500 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -410,7 +410,6 @@
clear_eps(f);
clear_desc(c->cdev->gadget, f);
- msm_dwc3_restart_usb_session();
}
static void qdss_eps_disable(struct usb_function *f)
@@ -467,13 +466,13 @@
qdss->usb_connected = 0;
spin_unlock_irqrestore(&qdss->lock, flags);
+ /*cancell all active xfers*/
+ qdss_eps_disable(f);
+
status = uninit_data(qdss->data);
if (status)
pr_err("%s: uninit_data error\n", __func__);
- /*cancell all active xfers*/
- qdss_eps_disable(f);
-
schedule_work(&qdss->disconnect_w);
}
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 801d24d..7ac5b64 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -687,6 +687,12 @@
rndis_reset_cmplt_type *resp;
rndis_resp_t *r;
struct rndis_params *params = rndis_per_dev_params + configNr;
+ u32 length;
+ u8 *xbuf;
+
+ /* drain the response queue */
+ while ((xbuf = rndis_get_next_response(configNr, &length)))
+ rndis_free_response(configNr, xbuf);
r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
if (!r)
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
index 83f885a..eec9e37 100644
--- a/drivers/usb/gadget/u_bam_data.c
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -183,6 +183,8 @@
int ret;
if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ if (d->func_type == USB_FUNC_MBIM)
+ teth_bridge_disconnect();
if (d->func_type == USB_FUNC_ECM)
ecm_ipa_disconnect(d->ipa_params.priv);
ret = usb_bam_disconnect_ipa(&d->ipa_params);
@@ -195,13 +197,28 @@
{
struct bam_data_port *port = container_of(w, struct bam_data_port,
connect_w);
+ struct teth_bridge_connect_params connect_params;
struct bam_data_ch_info *d = &port->data_ch;
+ ipa_notify_cb usb_notify_cb;
+ void *priv;
u32 sps_params;
int ret;
pr_debug("%s: Connect workqueue started", __func__);
if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
+ if (d->func_type == USB_FUNC_MBIM) {
+ ret = teth_bridge_init(&usb_notify_cb, &priv);
+ if (ret) {
+ pr_err("%s:teth_bridge_init() failed\n",
+ __func__);
+ return;
+ }
+ d->ipa_params.notify = usb_notify_cb;
+ d->ipa_params.priv = priv;
+ d->ipa_params.ipa_ep_cfg.mode.mode = IPA_BASIC;
+ }
+
d->ipa_params.client = IPA_CLIENT_USB_CONS;
d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
if (d->func_type == USB_FUNC_ECM) {
@@ -227,6 +244,23 @@
__func__, ret);
return;
}
+
+ if (d->func_type == USB_FUNC_MBIM) {
+ connect_params.ipa_usb_pipe_hdl =
+ d->ipa_params.prod_clnt_hdl;
+ connect_params.usb_ipa_pipe_hdl =
+ d->ipa_params.cons_clnt_hdl;
+ connect_params.tethering_mode =
+ TETH_TETHERING_MODE_MBIM;
+ ret = teth_bridge_connect(&connect_params);
+ if (ret) {
+ pr_err("%s:teth_bridge_connect() failed\n",
+ __func__);
+ return;
+ }
+ mbim_configure_params();
+ }
+
if (d->func_type == USB_FUNC_ECM) {
ret = ecm_ipa_connect(d->ipa_params.cons_clnt_hdl,
d->ipa_params.prod_clnt_hdl,
@@ -417,6 +451,7 @@
d->dst_connection_idx = dst_connection_idx;
d->trans = trans;
+ d->func_type = func;
if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
d->ipa_params.src_pipe = &(d->src_pipe_idx);
@@ -425,8 +460,6 @@
d->ipa_params.dst_idx = dst_connection_idx;
}
- d->func_type = func;
-
queue_work(bam_data_wq, &port->connect_w);
return 0;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index ca4b01a..9879122 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -2106,7 +2106,9 @@
}
if (mehci->async_irq) {
- disable_irq_wake(mehci->async_irq);
+ /* Async IRQ is used only in absence of dedicated wakeup irq */
+ if (!mehci->wakeup_irq)
+ disable_irq_wake(mehci->async_irq);
free_irq(mehci->async_irq, mehci);
}
/*
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 66363eb..521ace0 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -117,6 +117,8 @@
return -ENOMEM;
}
+ hcd_to_bus(hcd)->skip_resume = true;
+
hcd->irq = platform_get_irq(pdev, 0);
if (hcd->irq < 0) {
dev_err(&pdev->dev, "Unable to get IRQ resource\n");
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index faa5625..6727996 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -1057,6 +1057,8 @@
return -ENOMEM;
}
+ hcd_to_bus(hcd)->skip_resume = true;
+
hcd->irq = platform_get_irq(pdev, 0);
if (hcd->irq < 0) {
dev_err(&pdev->dev, "Unable to get IRQ resource\n");
diff --git a/drivers/usb/host/ehci-msm72k.c b/drivers/usb/host/ehci-msm72k.c
index 76cd977..bab330c 100644
--- a/drivers/usb/host/ehci-msm72k.c
+++ b/drivers/usb/host/ehci-msm72k.c
@@ -681,6 +681,8 @@
if (!hcd)
return -ENOMEM;
+ hcd_to_bus(hcd)->skip_resume = true;
+
hcd->irq = platform_get_irq(pdev, 0);
if (hcd->irq < 0) {
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index d48a631..1a0c0aa 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -39,6 +39,7 @@
#define PIPE_PRODUCER 1
#define MAX_PIPE_NUM 16
#define HBM_QH_MAP_PIPE 0xffffffc0
+#define QTD_CERR_MASK 0xfffff3ff
struct hbm_msm {
u32 *base;
@@ -257,6 +258,7 @@
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct list_head qtd_list;
+ struct ehci_qtd *qtd;
INIT_LIST_HEAD(&qtd_list);
@@ -272,5 +274,11 @@
if (!qh_urb_transaction(ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;
+
+ /* set err counter in qTD token to zero */
+ qtd = list_entry(qtd_list.next, struct ehci_qtd, qtd_list);
+ if (qtd != NULL)
+ qtd->hw_token &= QTD_CERR_MASK;
+
return hbm_submit_async(ehci, urb, &qtd_list, mem_flags);
}
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 7760d28..5750e0d 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3651,7 +3651,7 @@
cmd_buf.vmid_idx = MSM_OTG_VMID_IDX;
cmd_buf.mem_type = MSM_OTG_MEM_TYPE;
- ret = scm_call(SCM_SVC_CP, MSM_OTG_CMD_ID, &cmd_buf,
+ ret = scm_call(SCM_SVC_MP, MSM_OTG_CMD_ID, &cmd_buf,
sizeof(cmd_buf), NULL, 0);
if (ret)
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 88f8be5..590723a 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -132,7 +132,7 @@
default n
config FB_MSM_OVERLAY
- depends on FB_MSM_MDP40 && ANDROID_PMEM
+ depends on FB_MSM_MDP40
bool "MDP4 overlay support"
default n
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 77eb9c2..63a842d 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1609,7 +1609,6 @@
outpdw(MDP_BASE + 0x0014, 0x0); /* start DMA */
} else if (term == MDP_OVERLAY0_TERM) {
mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp_lut_enable();
outpdw(MDP_BASE + 0x0004, 0);
} else if (term == MDP_OVERLAY1_TERM) {
mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index e50055f..e415a95 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -29,7 +29,6 @@
#include <linux/fb.h>
#include <linux/msm_mdp.h>
#include <linux/file.h>
-#include <linux/android_pmem.h>
#include <linux/major.h>
#include <asm/system.h>
#include <asm/mach-types.h>
@@ -772,6 +771,7 @@
break;
case MDP_YCRYCB_H2V1:
+ case MDP_CBYCRY_H2V1:
if (pipe->src_x & 0x1)
pipe->src_x += 1;
*luma_off += pipe->src_x * 2 +
@@ -973,6 +973,7 @@
case MDP_RGBX_8888:
return OVERLAY_TYPE_RGB;
case MDP_YCRYCB_H2V1:
+ case MDP_CBYCRY_H2V1:
case MDP_Y_CRCB_H2V1:
case MDP_Y_CBCR_H2V1:
case MDP_Y_CRCB_H1V2:
@@ -1168,6 +1169,24 @@
pipe->unpack_tight = 1;
pipe->unpack_align_msb = 0;
pipe->unpack_count = 3;
+ pipe->element3 = C1_B_Cb; /* B */
+ pipe->element2 = C0_G_Y; /* G */
+ pipe->element1 = C2_R_Cr; /* R */
+ pipe->element0 = C0_G_Y; /* G */
+ pipe->bpp = 2; /* 2 bpp */
+ pipe->chroma_sample = MDP4_CHROMA_H2V1;
+ break;
+ case MDP_CBYCRY_H2V1:
+ pipe->frame_format = MDP4_FRAME_FORMAT_LINEAR;
+ pipe->fetch_plane = OVERLAY_PLANE_INTERLEAVED;
+ pipe->a_bit = 0; /* alpha, 4 bits */
+ pipe->r_bit = 3; /* R, 8 bits */
+ pipe->b_bit = 3; /* B, 8 bits */
+ pipe->g_bit = 3; /* G, 8 bits */
+ pipe->alpha_enable = 0;
+ pipe->unpack_tight = 1;
+ pipe->unpack_align_msb = 0;
+ pipe->unpack_count = 3;
pipe->element3 = C0_G_Y; /* G */
pipe->element2 = C2_R_Cr; /* R */
pipe->element1 = C0_G_Y; /* G */
@@ -3109,9 +3128,6 @@
{
struct file *file;
int put_needed, ret = 0, fb_num;
-#ifdef CONFIG_ANDROID_PMEM
- unsigned long vstart;
-#endif
*p_need = 0;
if (img->flags & MDP_BLIT_SRC_GEM) {
@@ -3146,13 +3162,6 @@
return mdp4_overlay_iommu_map_buf(img->memory_id, pipe, plane,
start, len, srcp_ihdl);
#endif
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(img->memory_id, start, &vstart,
- len, srcp_file))
- return 0;
- else
- return -EINVAL;
-#endif
}
#ifdef CONFIG_FB_MSM_MIPI_DSI
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 415b575..2e795fd 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -22,7 +22,6 @@
#include <linux/fb.h>
#include <linux/msm_mdp.h>
#include <linux/file.h>
-#include <linux/android_pmem.h>
#include <linux/major.h>
#include "linux/proc_fs.h"
@@ -548,40 +547,8 @@
format == MDP_Y_CRCB_H2V2) ? 2 : (format == MDP_Y_CBCR_H2V1 || \
format == MDP_Y_CRCB_H2V1) ? 1 : 1)
-#ifdef CONFIG_ANDROID_PMEM
-static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
- uint32_t *len0, uint32_t *len1)
-{
- *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
- if (IS_PSEUDOPLNR(img->format))
- *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
- else
- *len1 = 0;
-}
-
-static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
- struct file *p_src_file, struct file *p_dst_file)
-{
- uint32_t src0_len, src1_len;
-
- if (!(req->flags & MDP_BLIT_NON_CACHED)) {
- /* flush src images to memory before dma to mdp */
- get_len(&req->src, &req->src_rect, src_bpp,
- &src0_len, &src1_len);
-
- flush_pmem_file(p_src_file,
- req->src.offset, src0_len);
-
- if (IS_PSEUDOPLNR(req->src.format))
- flush_pmem_file(p_src_file,
- req->src.offset + src0_len, src1_len);
- }
-
-}
-#else
static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
struct file *p_src_file, struct file *p_dst_file) { }
-#endif
static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
@@ -1286,9 +1253,6 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
#endif
-#ifdef CONFIG_ANDROID_PMEM
- unsigned long vstart;
-#endif
if (req->flags & MDP_MEMORY_ID_TYPE_FB) {
file = fget_light(img->memory_id, &put_needed);
@@ -1321,21 +1285,10 @@
return -EINVAL;
#endif
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(img->memory_id, start, &vstart, len, srcp_file))
- return ret;
- else
- return -EINVAL;
-#endif
}
void put_img(struct file *p_src_file, struct ion_handle *p_ihdl)
{
-#ifdef CONFIG_ANDROID_PMEM
- if (p_src_file)
- put_pmem_file(p_src_file);
-#endif
-
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
if (!IS_ERR_OR_NULL(p_ihdl))
ion_free(ppp_display_iclient, p_ihdl);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 8ceb62e..c847ee6 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -60,6 +60,7 @@
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
struct regulator *fs;
+ u32 max_mdp_clk_rate;
struct workqueue_struct *clk_ctrl_wq;
struct work_struct clk_ctrl_worker;
@@ -81,6 +82,7 @@
u8 clk_ena;
u8 fs_ena;
u8 vsync_ena;
+ unsigned long min_mdp_clk;
u32 res_init;
u32 bus_hdl;
@@ -88,6 +90,8 @@
u32 smp_mb_cnt;
u32 smp_mb_size;
+ u32 rot_block_size;
+
struct mdss_hw_settings *hw_settings;
struct mdss_mdp_pipe *vig_pipes;
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index abef27d..7dc4f49 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -333,6 +333,9 @@
return -ENODEV;
}
+ debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
+ (u32 *)&mdata->min_mdp_clk);
+
mdata->debug_data = mdd;
return 0;
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 4a06be5..b365f36 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -252,7 +252,7 @@
struct dsi_panel_cmds_list {
struct dsi_cmd_desc *buf;
- char size;
+ u32 size;
char ctrl_state;
};
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 94261cc..4e74858 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -16,7 +16,6 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
-#include <linux/android_pmem.h>
#include <linux/bootmem.h>
#include <linux/console.h>
#include <linux/debugfs.h>
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index e8a3795..b93efd9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2283,15 +2283,14 @@
/* If power down is already underway, wait for it to finish */
flush_work_sync(&hdmi_ctrl->power_off_work);
- if (!hdmi_ctrl->panel_power_on) {
+ if (!hdmi_ctrl->panel_power_on)
hdmi_tx_hpd_off(hdmi_ctrl);
- } else {
+ else
hdmi_ctrl->hpd_off_pending = true;
- hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
- DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
- hdmi_ctrl->sdev.state);
- }
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
+ DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+ hdmi_ctrl->sdev.state);
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index f9b05fc..217ac18 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -127,6 +127,7 @@
static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
char *prop_name);
static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd,
u32 size, u32 *phys, void **virt)
@@ -520,13 +521,21 @@
return ret;
}
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate)
+void mdss_mdp_set_clk_rate(unsigned long rate)
{
+ struct mdss_data_type *mdata = mdss_res;
unsigned long clk_rate;
struct clk *clk = mdss_mdp_get_clk(MDSS_CLK_MDP_SRC);
+ unsigned long min_clk_rate;
+
+ min_clk_rate = max(rate, mdata->min_mdp_clk);
+
if (clk) {
mutex_lock(&mdp_clk_lock);
- clk_rate = clk_round_rate(clk, min_clk_rate);
+ if (min_clk_rate < mdata->max_mdp_clk_rate)
+ clk_rate = clk_round_rate(clk, min_clk_rate);
+ else
+ clk_rate = mdata->max_mdp_clk_rate;
if (IS_ERR_VALUE(clk_rate)) {
pr_err("unable to round rate err=%ld\n", clk_rate);
} else if (clk_rate != clk_get_rate(clk)) {
@@ -637,6 +646,15 @@
{
int ret;
+ ret = of_property_read_u32(mdata->pdev->dev.of_node,
+ "qcom,max-clk-rate", &mdata->max_mdp_clk_rate);
+ if (ret) {
+ pr_err("failed to get max mdp clock rate\n");
+ return ret;
+ }
+
+ pr_debug("max mdp clk rate=%d\n", mdata->max_mdp_clk_rate);
+
ret = devm_request_irq(&mdata->pdev->dev, mdata->irq, mdss_irq_handler,
IRQF_DISABLED, "MDSS", mdata);
if (ret) {
@@ -1012,7 +1030,7 @@
vbif_arr = of_get_property(pdev->dev.of_node, "qcom,vbif-settings",
&vbif_len);
- if (!vbif_arr || (mdp_len & 1)) {
+ if (!vbif_arr || (vbif_len & 1)) {
pr_warn("MDSS VBIF settings not found\n");
vbif_len = 0;
}
@@ -1083,6 +1101,12 @@
return rc;
}
+ rc = mdss_mdp_parse_dt_misc(pdev);
+ if (rc) {
+ pr_err("Error in device tree : misc\n");
+ return rc;
+ }
+
return 0;
}
@@ -1367,6 +1391,19 @@
return rc;
}
+static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
+{
+ struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+ u32 data;
+ int rc;
+
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-rot-block-size",
+ &data);
+ mdata->rot_block_size = (!rc ? data : 128);
+
+ return 0;
+}
+
static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
char *prop_name, u32 *offsets, int len)
{
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 43456ca..14c1e52 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
u32 flush_bits;
u32 play_cnt;
+ u32 underrun_cnt;
u16 width;
u16 height;
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 8515782..e850321 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -71,7 +71,7 @@
}
}
if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
- bus_ab_quota = bus_ab_quota << MDSS_MDP_BUS_FACTOR_SHIFT;
+ bus_ab_quota = bus_ib_quota << MDSS_MDP_BUS_FACTOR_SHIFT;
bus_ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR(bus_ib_quota);
bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index f8cd0ce..18c38a0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -164,6 +164,9 @@
#define MDSS_MDP_REG_SSPP_STILE_FRAME_SIZE 0x02C
#define MDSS_MDP_REG_SSPP_SRC_FORMAT 0x030
#define MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN 0x034
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0 0x050
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1 0x054
+#define MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2 0x058
#define MDSS_MDP_REG_SSPP_SRC_OP_MODE 0x038
#define MDSS_MDP_OP_DEINTERLACE BIT(22)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index e2c3b23..dab8674 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -244,12 +244,17 @@
rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
+
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
+ ctl->intf_num);
}
mdss_mdp_video_set_vsync_handler(ctl, NULL);
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
NULL, NULL);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+ NULL, NULL);
ctx->ref_cnt--;
ctl->priv_data = NULL;
@@ -304,6 +309,17 @@
return rc;
}
+static void mdss_mdp_video_underrun_intr_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ if (unlikely(!ctl))
+ return;
+
+ ctl->underrun_cnt++;
+ pr_warn("display underrun detected for ctl=%d count=%d\n", ctl->num,
+ ctl->underrun_cnt);
+}
+
static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_video_ctx *ctx;
@@ -332,6 +348,8 @@
pr_debug("enabling timing gen for intf=%d\n", ctl->intf_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num);
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
wmb();
@@ -390,6 +408,8 @@
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
mdss_mdp_video_vsync_intr_done, ctl);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
+ mdss_mdp_video_underrun_intr_done, ctl);
itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index c6b6e3f..b7b3c23 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -17,8 +17,6 @@
#include "mdss_mdp.h"
#include "mdss_mdp_rotator.h"
-#define ROT_BLK_SIZE 128
-
enum mdss_mdp_writeback_type {
MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
MDSS_MDP_WRITEBACK_TYPE_LINE,
@@ -251,7 +249,7 @@
pr_debug("rot setup wb_num=%d\n", ctx->wb_num);
ctx->opmode = BIT(6); /* ROT EN */
- if (ROT_BLK_SIZE == 128)
+ if (ctl->mdata->rot_block_size == 128)
ctx->opmode |= BIT(4); /* block size 128 */
ctx->opmode |= rot->bwc_mode;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c6b3472..0749f0c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1023,13 +1023,13 @@
if (offset > fbi->fix.smem_len) {
pr_err("invalid fb offset=%u total length=%u\n",
offset, fbi->fix.smem_len);
- return;
+ goto pan_display_error;
}
ret = mdss_mdp_overlay_start(mfd);
if (ret) {
pr_err("unable to start overlay %d (%d)\n", mfd->index, ret);
- return;
+ goto pan_display_error;
}
if (is_mdss_iommu_attached())
@@ -1044,18 +1044,18 @@
ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
if (ret) {
pr_err("unable to allocate base pipe\n");
- return;
+ goto pan_display_error;
}
if (mdss_mdp_pipe_map(pipe)) {
pr_err("unable to map base pipe\n");
- return;
+ goto pan_display_error;
}
ret = mdss_mdp_pipe_queue_data(pipe, &data);
mdss_mdp_pipe_unmap(pipe);
if (ret) {
pr_err("unable to queue data\n");
- return;
+ goto pan_display_error;
}
if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
@@ -1063,17 +1063,17 @@
MDSS_MDP_MIXER_MUX_RIGHT);
if (ret) {
pr_err("unable to allocate right base pipe\n");
- return;
+ goto pan_display_error;
}
if (mdss_mdp_pipe_map(pipe)) {
pr_err("unable to map right base pipe\n");
- return;
+ goto pan_display_error;
}
ret = mdss_mdp_pipe_queue_data(pipe, &data);
mdss_mdp_pipe_unmap(pipe);
if (ret) {
pr_err("unable to queue right data\n");
- return;
+ goto pan_display_error;
}
}
mutex_unlock(&mfd->ov_lock);
@@ -1081,6 +1081,10 @@
if ((fbi->var.activate & FB_ACTIVATE_VBL) ||
(fbi->var.activate & FB_ACTIVATE_FORCE))
mdss_mdp_overlay_kickoff(mfd->ctl);
+ return;
+
+pan_display_error:
+ mutex_unlock(&mfd->ov_lock);
}
/* function is called in irq context should have minimum processing */
@@ -1467,7 +1471,7 @@
if (!mfd->panel_info->cont_splash_enabled) {
rc = mdss_mdp_overlay_start(mfd);
- if (!IS_ERR_VALUE(rc))
+ if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL))
rc = mdss_mdp_overlay_kickoff(mfd->ctl);
} else {
rc = mdss_mdp_ctl_setup(mfd->ctl);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 4699e0d..ca741b1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -19,7 +19,9 @@
#include "mdss_mdp.h"
-#define SMP_MB_CNT (mdss_res->smp_mb_cnt)
+#define SMP_MB_SIZE (mdss_res->smp_mb_size)
+#define SMP_MB_CNT (mdss_res->smp_mb_cnt)
+#define SMP_ENTRIES_PER_MB (SMP_MB_SIZE / 16)
static DEFINE_MUTEX(mdss_mdp_sspp_lock);
static DEFINE_MUTEX(mdss_mdp_smp_lock);
@@ -29,6 +31,17 @@
u32 ndx);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
+ u32 reg, u32 val)
+{
+ writel_relaxed(val, pipe->base + reg);
+}
+
+static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
+{
+ return readl_relaxed(pipe->base + reg);
+}
+
static u32 mdss_mdp_smp_mmb_reserve(unsigned long *smp, size_t n)
{
u32 i, mmb;
@@ -45,9 +58,10 @@
return i;
}
-static void mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
+static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
{
u32 mmb, off, data, s;
+ int cnt = 0;
for_each_set_bit(mmb, smp, SMP_MB_CNT) {
off = (mmb / 3) * 4;
@@ -57,7 +71,9 @@
data |= client_id << s;
MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_W0 + off, data);
MDSS_MDP_REG_WRITE(MDSS_MDP_REG_SMP_ALLOC_R0 + off, data);
+ cnt++;
}
+ return cnt;
}
static void mdss_mdp_smp_mmb_free(unsigned long *smp)
@@ -70,6 +86,24 @@
}
}
+static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
+{
+ u32 entries, val, wm[3];
+
+ entries = mb_cnt * SMP_ENTRIES_PER_MB;
+ val = entries >> 2;
+
+ wm[0] = val;
+ wm[1] = wm[0] + val;
+ wm[2] = wm[1] + val;
+
+ pr_debug("pnum=%d watermarks %u,%u,%u\n", pipe->num,
+ wm[0], wm[1], wm[2]);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_0, wm[0]);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_1, wm[1]);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_REQPRIO_FIFO_WM_2, wm[2]);
+}
+
static void mdss_mdp_smp_free(struct mdss_mdp_pipe *pipe)
{
mutex_lock(&mdss_mdp_smp_lock);
@@ -81,24 +115,31 @@
static int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
u32 num_blks = 0, reserved = 0;
struct mdss_mdp_plane_sizes ps;
int i, rc;
- rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format, pipe->src.w,
- pipe->src.h, &ps);
- if (rc)
- return rc;
+ if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+ pipe->src_fmt->is_yuv) {
+ ps.num_planes = 2;
+ ps.ystride[0] = pipe->src.w;
+ ps.ystride[1] = pipe->src.w;
+ } else {
+ rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
+ pipe->src.w, pipe->src.h, &ps);
+ if (rc)
+ return rc;
+ }
if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
return -EINVAL;
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < ps.num_planes; i++) {
- num_blks = DIV_ROUND_UP(2 * ps.ystride[i],
- mdss_res->smp_mb_size);
+ num_blks = DIV_ROUND_UP(2 * ps.ystride[i], SMP_MB_SIZE);
- if (mdss_res->mdp_rev == MDSS_MDP_HW_REV_100)
+ if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
num_blks = roundup_pow_of_two(num_blks);
pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
@@ -123,9 +164,12 @@
static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
{
int i;
+ int cnt = 0;
+
mutex_lock(&mdss_mdp_smp_lock);
- for (i = 0; i < pipe->src_planes.num_planes; i++)
- mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+ for (i = 0; i < MAX_PLANES; i++)
+ cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i, &pipe->smp[i]);
+ mdss_mdp_smp_set_wm_levels(pipe, cnt);
mutex_unlock(&mdss_mdp_smp_lock);
return 0;
}
@@ -319,17 +363,6 @@
}
-static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
- u32 reg, u32 val)
-{
- writel_relaxed(val, pipe->base + reg);
-}
-
-static inline u32 mdss_mdp_pipe_read(struct mdss_mdp_pipe *pipe, u32 reg)
-{
- return readl_relaxed(pipe->base + reg);
-}
-
static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe)
{
u32 img_size, src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 911e29f..b54e0ec 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -12,7 +12,6 @@
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
-#include <linux/android_pmem.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/file.h>
@@ -36,6 +35,10 @@
MDP_INTR_VSYNC_INTF_1,
MDP_INTR_VSYNC_INTF_2,
MDP_INTR_VSYNC_INTF_3,
+ MDP_INTR_UNDERRUN_INTF_0,
+ MDP_INTR_UNDERRUN_INTF_1,
+ MDP_INTR_UNDERRUN_INTF_2,
+ MDP_INTR_UNDERRUN_INTF_3,
MDP_INTR_PING_PONG_0,
MDP_INTR_PING_PONG_1,
MDP_INTR_PING_PONG_2,
@@ -57,6 +60,9 @@
{
int index = -1;
switch (intr_type) {
+ case MDSS_MDP_IRQ_INTF_UNDER_RUN:
+ index = MDP_INTR_UNDERRUN_INTF_0 + (intf_num - MDSS_MDP_INTF0);
+ break;
case MDSS_MDP_IRQ_INTF_VSYNC:
index = MDP_INTR_VSYNC_INTF_0 + (intf_num - MDSS_MDP_INTF0);
break;
@@ -129,6 +135,18 @@
if (isr == 0)
goto mdp_isr_done;
+ if (isr & MDSS_MDP_INTR_INTF_0_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_0);
+
+ if (isr & MDSS_MDP_INTR_INTF_1_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_1);
+
+ if (isr & MDSS_MDP_INTR_INTF_2_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_2);
+
+ if (isr & MDSS_MDP_INTR_INTF_3_UNDERRUN)
+ mdss_mdp_intr_done(MDP_INTR_UNDERRUN_INTF_3);
+
if (isr & MDSS_MDP_INTR_PING_PONG_0_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_0);
@@ -310,7 +328,6 @@
data->srcp_file = NULL;
} else if (data->srcp_file) {
pr_debug("pmem buf=0x%x\n", data->addr);
- put_pmem_file(data->srcp_file);
data->srcp_file = NULL;
} else if (!IS_ERR_OR_NULL(data->srcp_ihdl)) {
pr_debug("ion hdl=%p buf=0x%x\n", data->srcp_ihdl, data->addr);
@@ -388,8 +405,7 @@
if (data->flags & MDP_SECURE_OVERLAY_SESSION) {
domain = MDSS_IOMMU_DOMAIN_SECURE;
ret = msm_ion_secure_buffer(iclient,
- data->srcp_ihdl, 0x2,
- ION_UNSECURE_DELAYED);
+ data->srcp_ihdl, 0x2, 0);
if (IS_ERR_VALUE(ret)) {
ion_free(iclient, data->srcp_ihdl);
pr_err("failed to secure handle (%d)\n",
@@ -402,8 +418,7 @@
ret = ion_map_iommu(iclient, data->srcp_ihdl,
mdss_get_iommu_domain(domain),
- 0, SZ_4K, 0, start, len, 0,
- ION_IOMMU_UNMAP_DELAYED);
+ 0, SZ_4K, 0, start, len, 0, 0);
} else {
ret = ion_phys(iclient, data->srcp_ihdl, start,
(size_t *) len);
@@ -414,10 +429,6 @@
pr_err("failed to map ion handle (%d)\n", ret);
return ret;
}
- } else {
- unsigned long vstart;
- ret = get_pmem_file(img->memory_id, start, &vstart, len,
- &data->srcp_file);
}
if (!ret && (img->offset < data->len)) {
diff --git a/drivers/video/msm/mdss/mhl_msc.c b/drivers/video/msm/mdss/mhl_msc.c
index add65ac..96e8b67 100644
--- a/drivers/video/msm/mdss/mhl_msc.c
+++ b/drivers/video/msm/mdss/mhl_msc.c
@@ -103,8 +103,6 @@
return postpone_send;
}
-
-
void mhl_msc_send_work(struct work_struct *work)
{
struct mhl_tx_ctrl *mhl_ctrl =
@@ -202,7 +200,6 @@
return 0;
}
-
int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl,
struct msc_command_struct *req)
{
@@ -286,8 +283,6 @@
return 0;
}
-
-
int mhl_msc_send_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
u8 sub_cmd, u8 cmd_data)
{
@@ -315,7 +310,6 @@
return mhl_queue_msc_command(mhl_ctrl, &req, MSC_PRIORITY_SEND);
}
-
int mhl_msc_read_devcap(struct mhl_tx_ctrl *mhl_ctrl, u8 offset)
{
struct msc_command_struct req;
@@ -340,20 +334,17 @@
return ret;
}
-
static void mhl_handle_input(struct mhl_tx_ctrl *mhl_ctrl,
u8 key_code, u16 input_key_code)
{
int key_press = (key_code & 0x80) == 0;
- pr_debug("%s: send key events[%x][%d]\n",
- __func__, key_code, key_press);
+ pr_debug("%s: send key events[%x][%x][%d]\n",
+ __func__, key_code, input_key_code, key_press);
input_report_key(mhl_ctrl->input, input_key_code, key_press);
input_sync(mhl_ctrl->input);
}
-
-
int mhl_rcp_recv(struct mhl_tx_ctrl *mhl_ctrl, u8 key_code)
{
u8 index = key_code & 0x7f;
@@ -392,7 +383,6 @@
return 0;
}
-
static int mhl_rap_action(struct mhl_tx_ctrl *mhl_ctrl, u8 action_code)
{
switch (action_code) {
@@ -400,7 +390,14 @@
mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE);
break;
case MHL_RAP_CONTENT_OFF:
- mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE);
+ /*
+ * instead of only disabling tmds
+ * send power button press - CONTENT_OFF
+ */
+ input_report_key(mhl_ctrl->input, KEY_VENDOR, 1);
+ input_sync(mhl_ctrl->input);
+ input_report_key(mhl_ctrl->input, KEY_VENDOR, 0);
+ input_sync(mhl_ctrl->input);
break;
default:
break;
@@ -413,9 +410,9 @@
u8 error_code;
bool tmds_en;
+ tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
switch (action_code) {
case MHL_RAP_POLL:
- tmds_en = mhl_check_tmds_enabled(mhl_ctrl);
if (tmds_en)
error_code = MHL_RAPK_NO_ERROR;
else
@@ -423,8 +420,12 @@
break;
case MHL_RAP_CONTENT_ON:
case MHL_RAP_CONTENT_OFF:
- mhl_rap_action(mhl_ctrl, action_code);
- error_code = MHL_RAPK_NO_ERROR;
+ if (tmds_en) {
+ mhl_rap_action(mhl_ctrl, action_code);
+ error_code = MHL_RAPK_NO_ERROR;
+ } else {
+ error_code = MHL_RAPK_UNSUPPORTED_ACTION_CODE;
+ }
break;
default:
error_code = MHL_RAPK_UNRECOGNIZED_ACTION_CODE;
@@ -437,7 +438,6 @@
error_code);
}
-
int mhl_msc_recv_msc_msg(struct mhl_tx_ctrl *mhl_ctrl,
u8 sub_cmd, u8 cmd_data)
{
@@ -504,6 +504,7 @@
/* SET_INT: GRT_WRT */
pr_debug("%s: recvd req to permit/grant write",
__func__);
+ complete_all(&mhl_ctrl->req_write_done);
mhl_msc_write_burst(
mhl_ctrl,
MHL_SCRATCHPAD_OFFSET,
@@ -599,31 +600,53 @@
u8 start_reg,
u8 length, u8 *data)
{
- int rc = 0;
+ int i, reg;
+ int timeout, retry = 20;
if (!(mhl_ctrl->devcap[DEVCAP_OFFSET_FEATURE_FLAG] &
MHL_FEATURE_SP_SUPPORT)) {
pr_debug("MHL: SCRATCHPAD_NOT_SUPPORTED\n");
- rc = -EFAULT;
- } else {
- if (mhl_ctrl->scrpd_busy) {
- pr_debug("MHL: scratchpad_busy\n");
- rc = -EBUSY;
- } else {
- int i, reg;
- for (i = 0, reg = start_reg; (i < length) &&
- (reg < MHL_SCRATCHPAD_SIZE); i++, reg++)
- mhl_ctrl->scrpd.data[reg] = data[i];
- mhl_ctrl->scrpd.length = length;
- mhl_ctrl->scrpd.offset = start_reg;
- mhl_msc_send_set_int(
- mhl_ctrl,
- MHL_RCHANGE_INT,
- MHL_INT_REQ_WRT,
- MSC_PRIORITY_SEND);
- }
+ return -EFAULT;
}
- return rc;
+
+ /*
+ * scratchpad remains busy as long as a peer's permission or
+ * write bursts are pending; experimentally it was found that
+ * 50ms is optimal
+ */
+ while (mhl_ctrl->scrpd_busy && retry--)
+ msleep(50);
+ if (!retry) {
+ pr_debug("MHL: scratchpad_busy\n");
+ return -EBUSY;
+ }
+
+ for (i = 0, reg = start_reg; (i < length) &&
+ (reg < MHL_SCRATCHPAD_SIZE); i++, reg++)
+ mhl_ctrl->scrpd.data[reg] = data[i];
+ mhl_ctrl->scrpd.length = length;
+ mhl_ctrl->scrpd.offset = start_reg;
+
+ retry = 5;
+ do {
+ init_completion(&mhl_ctrl->req_write_done);
+ mhl_msc_send_set_int(
+ mhl_ctrl,
+ MHL_RCHANGE_INT,
+ MHL_INT_REQ_WRT,
+ MSC_PRIORITY_SEND);
+ timeout = wait_for_completion_interruptible_timeout(
+ &mhl_ctrl->req_write_done,
+ msecs_to_jiffies(MHL_BURST_WAIT));
+ if (!timeout)
+ mhl_ctrl->scrpd_busy = false;
+ } while (retry-- && timeout == 0);
+ if (!timeout) {
+ pr_err("%s: timed out!\n", __func__);
+ return -EAGAIN;
+ }
+
+ return 0;
}
/* write scratchpad entry */
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index ccddf44..a3a1a4e 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -36,7 +36,7 @@
#define COMPATIBLE_NAME "qcom,mhl-sii8334"
#define MAX_CURRENT 700000
-#define pr_debug_intr(...) pr_debug("\n")
+#define pr_debug_intr(...)
#define MSC_START_BIT_MSC_CMD (0x01 << 0)
#define MSC_START_BIT_VS_CMD (0x01 << 1)
@@ -475,9 +475,10 @@
POWER_SUPPLY_PROP_CURRENT_MAX,
};
-static void cbus_reset(struct i2c_client *client)
+static void cbus_reset(struct mhl_tx_ctrl *mhl_ctrl)
{
uint8_t i;
+ struct i2c_client *client = mhl_ctrl->i2c_handle;
/*
* REG_SRST
@@ -492,7 +493,10 @@
MHL_SII_REG_NAME_WR(REG_INTR4_MASK,
BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6);
- MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
+ if (mhl_ctrl->chip_rev_id < 1)
+ MHL_SII_REG_NAME_WR(REG_INTR5_MASK, BIT3 | BIT4);
+ else
+ MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00);
/* Unmask CBUS1 Intrs */
MHL_SII_REG_NAME_WR(REG_CBUS_INTR_ENABLE,
@@ -523,7 +527,7 @@
/* Increase DDC translation layer timer*/
MHL_SII_CBUS_WR(0x0007, 0xF2);
/* Drive High Time */
- MHL_SII_CBUS_WR(0x0036, 0x03);
+ MHL_SII_CBUS_WR(0x0036, 0x0B);
/* Use programmed timing */
MHL_SII_CBUS_WR(0x0039, 0x30);
/* CBUS Drive Strength */
@@ -590,6 +594,8 @@
static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
bool mhl_disc_en)
{
+ uint8_t regval;
+
/*
* ============================================
* POWER UP
@@ -599,11 +605,6 @@
/* Power up 1.2V core */
MHL_SII_PAGE1_WR(0x003D, 0x3F);
- /*
- * Wait for the source power to be enabled
- * before enabling pll clocks.
- */
- msleep(50);
/* Enable Tx PLL Clock */
MHL_SII_PAGE2_WR(0x0011, 0x01);
/* Enable Tx Clock Path and Equalizer */
@@ -611,22 +612,26 @@
/* Tx Source Termination ON */
MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10);
/* Enable 1X MHL Clock output */
- MHL_SII_REG_NAME_WR(REG_MHLTX_CTL6, 0xAC);
+ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL6, 0xBC);
/* Tx Differential Driver Config */
MHL_SII_REG_NAME_WR(REG_MHLTX_CTL2, 0x3C);
- MHL_SII_REG_NAME_WR(REG_MHLTX_CTL4, 0xD9);
+ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL4, 0xC8);
/* PLL Bandwidth Control */
- MHL_SII_REG_NAME_WR(REG_MHLTX_CTL8, 0x02);
+ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL7, 0x03);
+ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL8, 0x0A);
/*
* ============================================
* Analog PLL Control
* ============================================
*/
/* Enable Rx PLL clock */
- MHL_SII_REG_NAME_WR(REG_TMDS_CCTRL, 0x00);
- MHL_SII_PAGE0_WR(0x00F8, 0x0C);
+ MHL_SII_REG_NAME_WR(REG_TMDS_CCTRL, 0x08);
+ MHL_SII_PAGE0_WR(0x00F8, 0x8C);
MHL_SII_PAGE0_WR(0x0085, 0x02);
MHL_SII_PAGE2_WR(0x0000, 0x00);
+ regval = MHL_SII_PAGE2_RD(0x0005);
+ regval &= ~BIT5;
+ MHL_SII_PAGE2_WR(0x0005, regval);
MHL_SII_PAGE2_WR(0x0013, 0x60);
/* PLL Cal ref sel */
MHL_SII_PAGE2_WR(0x0017, 0x03);
@@ -646,6 +651,7 @@
/* Rx PLL Bandwidth value from I2C */
MHL_SII_PAGE2_WR(0x0045, 0x06);
MHL_SII_PAGE2_WR(0x004B, 0x06);
+ MHL_SII_PAGE2_WR(0x004C, 0x60);
/* Manual zone control */
MHL_SII_PAGE2_WR(0x004C, 0xE0);
/* PLL Mode value */
@@ -658,20 +664,21 @@
*/
MHL_SII_REG_NAME_WR(REG_DISC_CTRL2, 0xAD);
/* 1.8V CBUS VTH */
- MHL_SII_REG_NAME_WR(REG_DISC_CTRL5, 0x55);
+ MHL_SII_REG_NAME_WR(REG_DISC_CTRL5, 0x57);
/* RGND and single Discovery attempt */
MHL_SII_REG_NAME_WR(REG_DISC_CTRL6, 0x11);
/* Ignore VBUS */
MHL_SII_REG_NAME_WR(REG_DISC_CTRL8, 0x82);
- MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x24);
/* Enable CBUS Discovery */
if (mhl_disc_en) {
+ MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x24);
/* Enable MHL Discovery */
MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x27);
/* Pull-up resistance off for IDLE state */
MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C);
} else {
+ MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x26);
/* Disable MHL Discovery */
MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x26);
MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C);
@@ -684,14 +691,14 @@
MHL_SII_PAGE3_WR(0x3C, 0x80);
if (mhl_ctrl->cur_state != POWER_STATE_D3)
- MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT5 | BIT4, BIT4);
+ MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT6 | BIT5 | BIT4, BIT4);
/* Enable Auto Soft RESET */
MHL_SII_REG_NAME_WR(REG_SRST, 0x084);
/* HDMI Transcode mode enable */
MHL_SII_PAGE0_WR(0x000D, 0x1C);
- cbus_reset(client);
+ cbus_reset(mhl_ctrl);
init_cbus_regs(client);
}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 57bf9f2..797d4a3 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -38,7 +38,6 @@
#include <linux/vmalloc.h>
#include <linux/debugfs.h>
#include <linux/console.h>
-#include <linux/android_pmem.h>
#include <linux/leds.h>
#include <linux/pm_runtime.h>
#include <linux/sync.h>
@@ -1747,9 +1746,12 @@
mutex_lock(&mfd->sync_mutex);
if (mfd->is_committing) {
mutex_unlock(&mfd->sync_mutex);
- ret = wait_for_completion_timeout(&mfd->commit_comp,
+ ret = wait_for_completion_interruptible_timeout(
+ &mfd->commit_comp,
msecs_to_jiffies(WAIT_FENCE_TIMEOUT));
if (ret <= 0)
+ ret = -ERESTARTSYS;
+ else if (!ret)
pr_err("%s wait for commit_comp timeout %d %d",
__func__, ret, mfd->is_committing);
} else {
@@ -3502,17 +3504,17 @@
static int msmfb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
struct mdp_buf_sync *buf_sync)
{
- int i, fence_cnt = 0, ret;
+ int i, fence_cnt = 0, ret = 0;
int acq_fen_fd[MDP_MAX_FENCE_FD];
struct sync_fence *fence;
- if ((buf_sync->acq_fen_fd_cnt == 0) ||
- (buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+ if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
(mfd->timeline == NULL))
return -EINVAL;
- ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
- buf_sync->acq_fen_fd_cnt * sizeof(int));
+ if (buf_sync->acq_fen_fd_cnt)
+ ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
+ buf_sync->acq_fen_fd_cnt * sizeof(int));
if (ret) {
pr_err("%s:copy_from_user failed", __func__);
return ret;
@@ -3531,6 +3533,10 @@
fence_cnt = i;
if (ret)
goto buf_sync_err_1;
+ mfd->acq_fen_cnt = fence_cnt;
+ if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+ msm_fb_wait_for_fence(mfd);
+
mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
mfd->timeline_value + 2);
if (mfd->cur_rel_sync_pt == NULL) {
@@ -3557,7 +3563,6 @@
pr_err("%s:copy_to_user failed", __func__);
goto buf_sync_err_2;
}
- mfd->acq_fen_cnt = buf_sync->acq_fen_fd_cnt;
mutex_unlock(&mfd->sync_mutex);
return ret;
buf_sync_err_2:
diff --git a/drivers/video/msm/msm_fb_def.h b/drivers/video/msm/msm_fb_def.h
index dcd648b..34cf427 100644
--- a/drivers/video/msm/msm_fb_def.h
+++ b/drivers/video/msm/msm_fb_def.h
@@ -34,7 +34,6 @@
#include <linux/vmalloc.h>
#include <linux/debugfs.h>
#include <linux/console.h>
-#include <linux/android_pmem.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/time.h>
diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h
index 41f7c29..2ad1ab2 100644
--- a/include/drm/kgsl_drm.h
+++ b/include/drm/kgsl_drm.h
@@ -86,7 +86,7 @@
struct drm_kgsl_gem_create_from_ion)
/* Maximum number of sub buffers per GEM object */
-#define DRM_KGSL_GEM_MAX_BUFFERS 2
+#define DRM_KGSL_GEM_MAX_BUFFERS 3
/* Memory types - these define the source and caching policies
of the GEM memory chunk */
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 281c72a..235248c 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -25,12 +25,12 @@
* struct devfreq_dev_status - Data given from devfreq user device to
* governors. Represents the performance
* statistics.
- * @total_time The total time represented by this instance of
+ * @total_time: The total time represented by this instance of
* devfreq_dev_status
- * @busy_time The time that the device was working among the
+ * @busy_time: The time that the device was working among the
* total_time.
- * @current_frequency The operating frequency.
- * @private_data An entry not specified by the devfreq framework.
+ * @current_frequency: The operating frequency.
+ * @private_data: An entry not specified by the devfreq framework.
* A device and a specific governor may have their
* own protocol with private_data. However, because
* this is governor-specific, a governor using this
@@ -54,23 +54,27 @@
/**
* struct devfreq_dev_profile - Devfreq's user device profile
- * @initial_freq The operating frequency when devfreq_add_device() is
+ * @initial_freq: The operating frequency when devfreq_add_device() is
* called.
- * @polling_ms The polling interval in ms. 0 disables polling.
- * @target The device should set its operating frequency at
+ * @polling_ms: The polling interval in ms. 0 disables polling.
+ * @target: The device should set its operating frequency at
* freq or lowest-upper-than-freq value. If freq is
* higher than any operable frequency, set maximum.
* Before returning, target function should set
* freq at the current frequency.
* The "flags" parameter's possible values are
* explained above with "DEVFREQ_FLAG_*" macros.
- * @get_dev_status The device should provide the current performance
+ * @get_dev_status: The device should provide the current performance
* status to devfreq, which is used by governors.
- * @exit An optional callback that is called when devfreq
+ * @get_cur_freq: The device should provide the current frequency
+ * at which it is operating.
+ * @exit: An optional callback that is called when devfreq
* is removing the devfreq object due to error or
* from devfreq_remove_device() call. If the user
* has registered devfreq->nb at a notifier-head,
* this is the time to unregister it.
+ * @freq_table: Optional list of frequencies to support statistics.
+ * @max_state: The size of freq_table.
*/
struct devfreq_dev_profile {
unsigned long initial_freq;
@@ -79,63 +83,63 @@
int (*target)(struct device *dev, unsigned long *freq, u32 flags);
int (*get_dev_status)(struct device *dev,
struct devfreq_dev_status *stat);
+ int (*get_cur_freq)(struct device *dev, unsigned long *freq);
void (*exit)(struct device *dev);
+
+ unsigned int *freq_table;
+ unsigned int max_state;
};
/**
* struct devfreq_governor - Devfreq policy governor
- * @name Governor's name
- * @get_target_freq Returns desired operating frequency for the device.
+ * @node: list node - contains registered devfreq governors
+ * @name: Governor's name
+ * @get_target_freq: Returns desired operating frequency for the device.
* Basically, get_target_freq will run
* devfreq_dev_profile.get_dev_status() to get the
* status of the device (load = busy_time / total_time).
* If no_central_polling is set, this callback is called
* only with update_devfreq() notified by OPP.
- * @init Called when the devfreq is being attached to a device
- * @exit Called when the devfreq is being removed from a
- * device. Governor should stop any internal routines
- * before return because related data may be
- * freed after exit().
- * @no_central_polling Do not use devfreq's central polling mechanism.
- * When this is set, devfreq will not call
- * get_target_freq with devfreq_monitor(). However,
- * devfreq will call get_target_freq with
- * devfreq_update() notified by OPP framework.
+ * @event_handler: Callback for devfreq core framework to notify events
+ * to governors. Events include per device governor
+ * init and exit, opp changes out of devfreq, suspend
+ * and resume of per device devfreq during device idle.
*
* Note that the callbacks are called with devfreq->lock locked by devfreq.
*/
struct devfreq_governor {
+ struct list_head node;
+
const char name[DEVFREQ_NAME_LEN];
int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
- int (*init)(struct devfreq *this);
- void (*exit)(struct devfreq *this);
- const bool no_central_polling;
+ int (*event_handler)(struct devfreq *devfreq,
+ unsigned int event, void *data);
};
/**
* struct devfreq - Device devfreq structure
- * @node list node - contains the devices with devfreq that have been
+ * @node: list node - contains the devices with devfreq that have been
* registered.
- * @lock a mutex to protect accessing devfreq.
- * @dev device registered by devfreq class. dev.parent is the device
+ * @lock: a mutex to protect accessing devfreq.
+ * @dev: device registered by devfreq class. dev.parent is the device
* using devfreq.
- * @profile device-specific devfreq profile
- * @governor method how to choose frequency based on the usage.
- * @nb notifier block used to notify devfreq object that it should
+ * @profile: device-specific devfreq profile
+ * @governor: method how to choose frequency based on the usage.
+ * @governor_name: devfreq governor name for use with this devfreq
+ * @nb: notifier block used to notify devfreq object that it should
* reevaluate operable frequencies. Devfreq users may use
* devfreq.nb to the corresponding register notifier call chain.
- * @polling_jiffies interval in jiffies.
- * @previous_freq previously configured frequency value.
- * @next_polling the number of remaining jiffies to poll with
- * "devfreq_monitor" executions to reevaluate
- * frequency/voltage of the device. Set by
- * profile's polling_ms interval.
- * @data Private data of the governor. The devfreq framework does not
+ * @work: delayed work for load monitoring.
+ * @previous_freq: previously configured frequency value.
+ * @data: Private data of the governor. The devfreq framework does not
* touch this.
- * @being_removed a flag to mark that this object is being removed in
- * order to prevent trying to remove the object multiple times.
- * @min_freq Limit minimum frequency requested by user (0: none)
- * @max_freq Limit maximum frequency requested by user (0: none)
+ * @min_freq: Limit minimum frequency requested by user (0: none)
+ * @max_freq: Limit maximum frequency requested by user (0: none)
+ * @stop_polling: devfreq polling status of a device.
+ * @total_trans: Number of devfreq transitions
+ * @trans_table: Statistics of devfreq transitions
+ * @time_in_state: Statistics of devfreq states
+ * @last_stat_updated: The last time stat updated
*
* This structure stores the devfreq information for a give device.
*
@@ -152,26 +156,33 @@
struct device dev;
struct devfreq_dev_profile *profile;
const struct devfreq_governor *governor;
+ char governor_name[DEVFREQ_NAME_LEN];
struct notifier_block nb;
+ struct delayed_work work;
- unsigned long polling_jiffies;
unsigned long previous_freq;
- unsigned int next_polling;
void *data; /* private data for governors */
- bool being_removed;
-
unsigned long min_freq;
unsigned long max_freq;
+ bool stop_polling;
+
+ /* information for device freqeuncy transition */
+ unsigned int total_trans;
+ unsigned int *trans_table;
+ unsigned long *time_in_state;
+ unsigned long last_stat_updated;
};
#if defined(CONFIG_PM_DEVFREQ)
extern struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- const struct devfreq_governor *governor,
+ const char *governor_name,
void *data);
extern int devfreq_remove_device(struct devfreq *devfreq);
+extern int devfreq_suspend_device(struct devfreq *devfreq);
+extern int devfreq_resume_device(struct devfreq *devfreq);
/* Helper functions for devfreq user device driver with OPP. */
extern struct opp *devfreq_recommended_opp(struct device *dev,
@@ -181,23 +192,13 @@
extern int devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq);
-#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
-extern const struct devfreq_governor devfreq_powersave;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
-extern const struct devfreq_governor devfreq_performance;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
-extern const struct devfreq_governor devfreq_userspace;
-#endif
#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
-extern const struct devfreq_governor devfreq_simple_ondemand;
/**
* struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
* and devfreq_add_device
- * @ upthreshold If the load is over this value, the frequency jumps.
+ * @upthreshold: If the load is over this value, the frequency jumps.
* Specify 0 to use the default. Valid value = 0 to 100.
- * @ downdifferential If the load is under upthreshold - downdifferential,
+ * @downdifferential: If the load is under upthreshold - downdifferential,
* the governor may consider slowing the frequency down.
* Specify 0 to use the default. Valid value = 0 to 100.
* downdifferential < upthreshold must hold.
@@ -214,7 +215,7 @@
#else /* !CONFIG_PM_DEVFREQ */
static struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
- struct devfreq_governor *governor,
+ const char *governor_name,
void *data)
{
return NULL;
@@ -225,6 +226,16 @@
return 0;
}
+static int devfreq_suspend_device(struct devfreq *devfreq)
+{
+ return 0;
+}
+
+static int devfreq_resume_device(struct devfreq *devfreq)
+{
+ return 0;
+}
+
static struct opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags)
{
@@ -243,11 +254,6 @@
return -EINVAL;
}
-#define devfreq_powersave NULL
-#define devfreq_performance NULL
-#define devfreq_userspace NULL
-#define devfreq_simple_ondemand NULL
-
#endif /* CONFIG_PM_DEVFREQ */
#endif /* __LINUX_DEVFREQ_H__ */
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index d208f1e..7939832 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -26,6 +26,7 @@
#define UART_MODE 4
#define SOCKET_MODE 5
#define CALLBACK_MODE 6
+#define MEMORY_DEVICE_MODE_NRT 7
/* different values that go in for diag_data_type */
#define DATA_TYPE_EVENT 0
#define DATA_TYPE_F3 1
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 2cea256..6e50578 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -189,28 +189,28 @@
/* Events associated with each demux filter */
enum dmx_event {
/* New PES packet is ready to be consumed */
- DMX_EVENT_NEW_PES,
+ DMX_EVENT_NEW_PES = 0x00000001,
/* New section is ready to be consumed */
- DMX_EVENT_NEW_SECTION,
+ DMX_EVENT_NEW_SECTION = 0x00000002,
/* New recording chunk is ready to be consumed */
- DMX_EVENT_NEW_REC_CHUNK,
+ DMX_EVENT_NEW_REC_CHUNK = 0x00000004,
/* New PCR value is ready */
- DMX_EVENT_NEW_PCR,
+ DMX_EVENT_NEW_PCR = 0x00000008,
/* Overflow */
- DMX_EVENT_BUFFER_OVERFLOW,
+ DMX_EVENT_BUFFER_OVERFLOW = 0x00000010,
/* Section was dropped due to CRC error */
- DMX_EVENT_SECTION_CRC_ERROR,
+ DMX_EVENT_SECTION_CRC_ERROR = 0x00000020,
/* End-of-stream, no more data from this filter */
- DMX_EVENT_EOS,
+ DMX_EVENT_EOS = 0x00000040,
/* New Elementary Stream data is ready */
- DMX_EVENT_NEW_ES_DATA
+ DMX_EVENT_NEW_ES_DATA = 0x00000080
};
/* Flags passed in filter events */
@@ -552,7 +552,6 @@
int handle;
};
-
struct dmx_decoder_buffers {
/*
* Specify if linear buffer support is requested. If set, buffers_num
@@ -587,6 +586,35 @@
__u32 key_ladder_id;
};
+struct dmx_events_mask {
+ /*
+ * Bitmask of events to be disabled (dmx_event).
+ * Disabled events will not be notified to the user.
+ * By default all events are enabled except for
+ * DMX_EVENT_NEW_ES_DATA.
+ * Overflow event can't be disabled.
+ */
+ __u32 disable_mask;
+
+ /*
+ * Bitmask of events that will not wake-up the user
+ * when user calls poll with POLLPRI flag.
+ * Events that are used as wake-up source should not be
+ * disabled in disable_mask or they would not be used
+ * as a wake-up source.
+ * By default all enabled events are set as wake-up events.
+ * Overflow event can't be disabled as a wake-up source.
+ */
+ __u32 no_wakeup_mask;
+
+ /*
+ * Number of ready wake-up events which will trigger
+ * a wake-up when user calls poll with POLLPRI flag.
+ * Default is set to 1.
+ */
+ __u32 wakeup_threshold;
+};
+
#define DMX_START _IO('o', 41)
#define DMX_STOP _IO('o', 42)
#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
@@ -611,6 +639,8 @@
#define DMX_SET_DECODER_BUFFER _IOW('o', 63, struct dmx_decoder_buffers)
#define DMX_REUSE_DECODER_BUFFER _IO('o', 64)
#define DMX_SET_SECURE_MODE _IOW('o', 65, struct dmx_secure_mode)
+#define DMX_SET_EVENTS_MASK _IOW('o', 66, struct dmx_events_mask)
+#define DMX_GET_EVENTS_MASK _IOR('o', 67, struct dmx_events_mask)
#endif /*_DVBDMX_H_*/
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a2b59d7..1ca1b83 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1074,6 +1074,90 @@
#define WLAN_HT_SMPS_CONTROL_STATIC 1
#define WLAN_HT_SMPS_CONTROL_DYNAMIC 3
+/**
+ * struct ieee80211_vht_mcs_info - VHT MCS information
+ * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams
+ * @rx_highest: Indicates highest long GI VHT PPDU data rate
+ * STA can receive. Rate expressed in units of 1 Mbps.
+ * If this field is 0 this value should not be used to
+ * consider the highest RX data rate supported.
+ * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams
+ * @tx_highest: Indicates highest long GI VHT PPDU data rate
+ * STA can transmit. Rate expressed in units of 1 Mbps.
+ * If this field is 0 this value should not be used to
+ * consider the highest TX data rate supported.
+ */
+struct ieee80211_vht_mcs_info {
+ __le16 rx_mcs_map;
+ __le16 rx_highest;
+ __le16 tx_mcs_map;
+ __le16 tx_highest;
+} __packed;
+
+/**
+ * struct ieee80211_vht_cap - VHT capabilities
+ *
+ * This structure is the "VHT capabilities element" as
+ * described in 802.11ac D3.0 8.4.2.160
+ * @vht_cap_info: VHT capability info
+ * @supp_mcs: VHT MCS supported rates
+ */
+struct ieee80211_vht_cap {
+ __le32 vht_cap_info;
+ struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+/**
+ * struct ieee80211_vht_operation - VHT operation IE
+ *
+ * This structure is the "VHT operation element" as
+ * described in 802.11ac D3.0 8.4.2.161
+ * @chan_width: Operating channel width
+ * @center_freq_seg1_idx: center freq segment 1 index
+ * @center_freq_seg2_idx: center freq segment 2 index
+ * @basic_mcs_set: VHT Basic MCS rate set
+ */
+struct ieee80211_vht_operation {
+ u8 chan_width;
+ u8 center_freq_seg1_idx;
+ u8 center_freq_seg2_idx;
+ __le16 basic_mcs_set;
+} __packed;
+
+
+#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0
+#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1
+#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2
+#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3
+
+/* 802.11ac VHT Capabilities */
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001
+#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
+#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
+#define IEEE80211_VHT_CAP_RXLDPC 0x00000010
+#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020
+#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040
+#define IEEE80211_VHT_CAP_TXSTBC 0x00000080
+#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100
+#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200
+#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
+#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
+#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
+#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000
+#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000
+#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000
+#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000
+#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000
+#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
+#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
+#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000
+#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000
+
/* Authentication algorithms */
#define WLAN_AUTH_OPEN 0
#define WLAN_AUTH_SHARED_KEY 1
@@ -1334,6 +1418,9 @@
WLAN_EID_DSE_REGISTERED_LOCATION = 58,
WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59,
WLAN_EID_EXT_CHANSWITCH_ANN = 60,
+
+ WLAN_EID_VHT_CAPABILITY = 191,
+ WLAN_EID_VHT_OPERATION = 192,
};
/* Action category code */
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 0806d31..9461c76 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -44,6 +44,8 @@
* @disable_flat_portion_ocv: feature to disable ocv updates while in sleep
* @ocv_dis_high_soc: the high soc percent when ocv should be disabled
* @ocv_dis_low_soc: the low soc percent when ocv should be enabled
+ * @low_voltage_detect: feature to enable 0 SOC reporting on low volatge
+ * @vbatt_cutoff_retries: number of tries before we report a 0 SOC
*/
struct pm8921_bms_platform_data {
struct pm8xxx_bms_core_data bms_cdata;
@@ -65,6 +67,8 @@
int disable_flat_portion_ocv;
int ocv_dis_high_soc;
int ocv_dis_low_soc;
+ int low_voltage_detect;
+ int vbatt_cutoff_retries;
};
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
diff --git a/include/linux/mhl_8334.h b/include/linux/mhl_8334.h
index d6f8356..d8eb494 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -157,6 +157,7 @@
struct scrpd_struct scrpd;
int scrpd_busy;
int wr_burst_pending;
+ struct completion req_write_done;
};
int mhl_i2c_reg_read(struct i2c_client *client,
diff --git a/include/linux/mhl_defs.h b/include/linux/mhl_defs.h
index aa63e03..f5dacfd 100644
--- a/include/linux/mhl_defs.h
+++ b/include/linux/mhl_defs.h
@@ -135,7 +135,7 @@
/* manually define highest number */
#define MHL_MAX_BUFFER_SIZE MHL_SCRATCHPAD_SIZE
-
+#define MHL_BURST_WAIT (1000)
enum {
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index f26b903..a5f36b5 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -110,7 +110,12 @@
#define SDHCI_QUIRK2_SLOW_INT_CLR (1<<2)
/* Ignore CMD CRC errors for tuning commands */
#define SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING (1<<3)
-
+/*
+ * If the base clock can be scalable, then there should be no further
+ * clock dividing as the input clock itself will be scaled down to
+ * required frequency.
+ */
+#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK (1<<4)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index a683ed4..95c4e6a 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -40,6 +40,7 @@
ION_CP_MFC_HEAP_ID = 12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+ ION_SYSTEM_CONTIG_HEAP_ID = 21,
ION_ADSP_HEAP_ID = 22,
ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
ION_SF_HEAP_ID = 24,
@@ -90,6 +91,7 @@
#define ION_ADSP_HEAP_NAME "adsp"
#define ION_VMALLOC_HEAP_NAME "vmalloc"
+#define ION_KMALLOC_HEAP_NAME "kmalloc"
#define ION_AUDIO_HEAP_NAME "audio"
#define ION_SF_HEAP_NAME "sf"
#define ION_MM_HEAP_NAME "mm"
diff --git a/include/linux/msm_ipa.h b/include/linux/msm_ipa.h
index b377a6c..5151654 100644
--- a/include/linux/msm_ipa.h
+++ b/include/linux/msm_ipa.h
@@ -173,6 +173,7 @@
WLAN_AP_DISCONNECT,
WLAN_STA_CONNECT,
WLAN_STA_DISCONNECT,
+ IPA_EVENT_MAX
};
/**
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 4e62b4f..b7d393f 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -20,6 +20,8 @@
#define KGSL_CONTEXT_TRASH_STATE 0x00000020
#define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040
#define KGSL_CONTEXT_USER_GENERATED_TS 0x00000080
+#define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200
+
#define KGSL_CONTEXT_INVALID 0xffffffff
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 6a2c95d..5deff7a 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -95,6 +95,7 @@
MDP_RGB_888, /* RGB 888 planer */
MDP_Y_CRCB_H2V2, /* Y and CrCb, pseudo planer w/ Cr is in MSB */
MDP_YCRYCB_H2V1, /* YCrYCb interleave */
+ MDP_CBYCRY_H2V1, /* CbYCrY interleave */
MDP_Y_CRCB_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CBCR_H2V1, /* Y and CrCb, pseduo planer w/ Cr is in MSB */
MDP_Y_CRCB_H1V2,
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index cc864f0..35279bf 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -282,7 +282,8 @@
VDEC_CODECTYPE_MPEG1 = 0x9,
VDEC_CODECTYPE_MPEG2 = 0xa,
VDEC_CODECTYPE_VC1 = 0xb,
- VDEC_CODECTYPE_VC1_RCV = 0xc
+ VDEC_CODECTYPE_VC1_RCV = 0xc,
+ VDEC_CODECTYPE_HEVC = 0xd,
};
enum vdec_mpeg2_profile {
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index ce5ddf3..0ab5143 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1221,6 +1221,60 @@
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
+ * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from
+ * userspace. If unset it is assumed the hint comes directly from
+ * a user. If set code could specify exactly what type of source
+ * was used to provide the hint. For the different types of
+ * allowed user regulatory hints see nl80211_user_reg_hint_type.
+ *
+ * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected
+ * the connection request from a station. nl80211_connect_failed_reason
+ * enum has different reasons of connection failure.
+ *
+ * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts
+ * with the Authentication transaction sequence number field.
+ *
+ * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION)
+ *
+ * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32)
+ *
+ * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with
+ * the START_AP and SET_BSS commands
+ * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the
+ * START_AP and SET_BSS commands. This can have the values 0 or 1;
+ * if not given in START_AP 0 is assumed, if not given in SET_BSS
+ * no change is made.
+ *
+ * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode
+ * defined in &enum nl80211_mesh_power_mode.
+ *
+ * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy,
+ * carried in a u32 attribute
+ *
+ * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for
+ * MAC ACL.
+ *
+ * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum
+ * number of MAC addresses that a device can support for MAC
+ * ACL.
+ *
+ * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace,
+ * contains a value of enum nl80211_radar_event (u32).
+ *
+ * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver
+ * has and handles. The format is the same as the IE contents. See
+ * 802.11-2012 8.4.2.29 for more information.
+ * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver
+ * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields.
+ *
+ * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to
+ * the driver, e.g., to enable TDLS power save (PU-APSD).
+ *
+ * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are
+ * advertised to the driver, e.g., to enable TDLS off channel operations
+ * and PU-APSD.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1472,6 +1526,41 @@
NL80211_ATTR_BG_SCAN_PERIOD,
+ NL80211_ATTR_WDEV,
+
+ NL80211_ATTR_USER_REG_HINT_TYPE,
+
+ NL80211_ATTR_CONN_FAILED_REASON,
+
+ NL80211_ATTR_SAE_DATA,
+
+ NL80211_ATTR_VHT_CAPABILITY,
+
+ NL80211_ATTR_SCAN_FLAGS,
+
+ NL80211_ATTR_CHANNEL_WIDTH,
+ NL80211_ATTR_CENTER_FREQ1,
+ NL80211_ATTR_CENTER_FREQ2,
+
+ NL80211_ATTR_P2P_CTWINDOW,
+ NL80211_ATTR_P2P_OPPPS,
+
+ NL80211_ATTR_LOCAL_MESH_POWER_MODE,
+
+ NL80211_ATTR_ACL_POLICY,
+
+ NL80211_ATTR_MAC_ADDRS,
+
+ NL80211_ATTR_MAC_ACL_MAX,
+
+ NL80211_ATTR_RADAR_EVENT,
+
+ NL80211_ATTR_EXT_CAPA,
+ NL80211_ATTR_EXT_CAPA_MASK,
+
+ NL80211_ATTR_STA_CAPABILITY,
+ NL80211_ATTR_STA_EXT_CAPABILITY,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1515,6 +1604,7 @@
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
#define NL80211_HT_CAPABILITY_LEN 26
+#define NL80211_VHT_CAPABILITY_LEN 12
#define NL80211_MAX_NR_CIPHER_SUITES 5
#define NL80211_MAX_NR_AKM_SUITES 2
@@ -1783,6 +1873,9 @@
* @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n
* @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n
+ * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as
+ * defined in 802.11ac
+ * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE
* @NL80211_BAND_ATTR_MAX: highest band attribute currently defined
* @__NL80211_BAND_ATTR_AFTER_LAST: internal use
*/
@@ -1796,6 +1889,9 @@
NL80211_BAND_ATTR_HT_AMPDU_FACTOR,
NL80211_BAND_ATTR_HT_AMPDU_DENSITY,
+ NL80211_BAND_ATTR_VHT_MCS_SET,
+ NL80211_BAND_ATTR_VHT_CAPA,
+
/* keep last */
__NL80211_BAND_ATTR_AFTER_LAST,
NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1
diff --git a/include/linux/opp.h b/include/linux/opp.h
index 2a4e5fa..214e0eb 100644
--- a/include/linux/opp.h
+++ b/include/linux/opp.h
@@ -48,6 +48,14 @@
struct srcu_notifier_head *opp_get_notifier(struct device *dev);
+#ifdef CONFIG_OF
+int of_init_opp_table(struct device *dev);
+#else
+static inline int of_init_opp_table(struct device *dev)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_OF */
#else
static inline unsigned long opp_get_voltage(struct opp *opp)
{
diff --git a/include/linux/qpnp-misc.h b/include/linux/qpnp-misc.h
new file mode 100644
index 0000000..b241e5d
--- /dev/null
+++ b/include/linux/qpnp-misc.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __QPNP_MISC_H
+#define __QPNP_MISC_H
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_QPNP_MISC
+/**
+ * qpnp_misc_irqs_available - check if IRQs are available
+ *
+ * @consumer_dev: device struct
+ *
+ * This function returns true if the MISC interrupts are available
+ * based on a check in the MISC peripheral revision registers.
+ *
+ * Any consumer of this function needs to reference a MISC device phandle
+ * using the qcom,misc-ref in their device tree node.
+ */
+
+int qpnp_misc_irqs_available(struct device *consumer_dev);
+#else
+static int qpnp_misc_irq_available(struct device *consumer_dev)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 05d75ce..fc6ab91 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -195,7 +195,7 @@
};
/**
- * enum qpnp_adc_scale_fn_type - Scaling function for pm8921 pre calibrated
+ * enum qpnp_adc_scale_fn_type - Scaling function for pm8941 pre calibrated
* digital data relative to ADC reference.
* %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage.
* %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters.
@@ -217,6 +217,26 @@
SCALE_NONE,
};
+
+/**
+ * enum qpnp_adc_tm_rscale_fn_type - Scaling function used to convert the
+ * channels input voltage/temperature to corresponding ADC code that is
+ * applied for thresholds. Check the corresponding channels scaling to
+ * determine the appropriate temperature/voltage units that are passed
+ * to the scaling function. Example battery follows the power supply
+ * framework that needs its units to be in decidegreesC so it passes
+ * deci-degreesC. PA_THERM clients pass the temperature in degrees.
+ * The order below should match the one in the driver for
+ * adc_tm_rscale_fn[].
+ */
+enum qpnp_adc_tm_rscale_fn_type {
+ SCALE_R_VBATT = 0,
+ SCALE_RBATT_THERM,
+ SCALE_R_USB_ID,
+ SCALE_RPMIC_THERM,
+ SCALE_RSCALE_NONE,
+};
+
/**
* enum qpnp_adc_fast_avg_ctl - Provides ability to obtain single result
* from the ADC that is an average of multiple measurement
@@ -560,16 +580,11 @@
};
/**
- * Channel selection registers for each of the 5 configurable measurements
- * Channels allotment is fixed for the given channels below.
- * The USB_ID and BATT_THERM channels are used only by the kernel space
- * USB and Battery drivers.
+ * Channel selection registers for each of the configurable measurements
+ * Channels allotment is set at device config for a channel.
+ * The USB_ID, BATT_THERM, PMIC_THERM and VBAT channels are used by the
+ * kernel space USB, Battery and IADC drivers.
* The other 3 channels are configurable for use by userspace clients.
- * USB_ID uses QPNP_ADC_TM_M0_ADC_CH_SEL_CTL
- * BATT_TEMP uses QPNP_ADC_TM_M1_ADC_CH_SEL_CTL
- * PA_THERM1 uses QPNP_ADC_TM_M2_ADC_CH_SEL_CTL
- * PA_THERM2 uses QPNP_ADC_TM_M3_ADC_CH_SEL_CTL
- * EMMC_THERM uses QPNP_ADC_TM_M4_ADC_CH_SEL_CTL
*/
enum qpnp_adc_tm_channel_select {
QPNP_ADC_TM_M0_ADC_CH_SEL_CTL = 0x48,
@@ -577,6 +592,9 @@
QPNP_ADC_TM_M2_ADC_CH_SEL_CTL = 0x70,
QPNP_ADC_TM_M3_ADC_CH_SEL_CTL = 0x78,
QPNP_ADC_TM_M4_ADC_CH_SEL_CTL = 0x80,
+ QPNP_ADC_TM_M5_ADC_CH_SEL_CTL = 0x88,
+ QPNP_ADC_TM_M6_ADC_CH_SEL_CTL = 0x90,
+ QPNP_ADC_TM_M7_ADC_CH_SEL_CTL = 0x98,
QPNP_ADC_TM_CH_SELECT_NONE
};
@@ -619,75 +637,84 @@
* enum qpnp_tm_state - This lets the client know whether the threshold
* that was crossed was high/low.
* %ADC_TM_HIGH_STATE: Client is notified of crossing the requested high
- * threshold.
+ * voltage threshold.
+ * %ADC_TM_COOL_STATE: Client is notified of crossing the requested cool
+ * temperature threshold.
* %ADC_TM_LOW_STATE: Client is notified of crossing the requested low
- * threshold.
+ * voltage threshold.
+ * %ADC_TM_WARM_STATE: Client is notified of crossing the requested high
+ * temperature threshold.
*/
enum qpnp_tm_state {
ADC_TM_HIGH_STATE = 0,
+ ADC_TM_COOL_STATE = ADC_TM_HIGH_STATE,
ADC_TM_LOW_STATE,
+ ADC_TM_WARM_STATE = ADC_TM_LOW_STATE,
ADC_TM_STATE_NUM,
};
/**
* enum qpnp_state_request - Request to enable/disable the corresponding
* high/low voltage/temperature thresholds.
- * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage/temperature threshold.
+ * %ADC_TM_HIGH_THR_ENABLE: Enable high voltage threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Enables cool temperature threshold.
* %ADC_TM_LOW_THR_ENABLE: Enable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Enables warm temperature threshold.
* %ADC_TM_HIGH_LOW_THR_ENABLE: Enable high and low voltage/temperature
* threshold.
* %ADC_TM_HIGH_THR_DISABLE: Disable high voltage/temperature threshold.
+ * %ADC_TM_COOL_THR_ENABLE = Disables cool temperature threshold.
* %ADC_TM_LOW_THR_DISABLE: Disable low voltage/temperature threshold.
+ * %ADC_TM_WARM_THR_ENABLE = Disables warm temperature threshold.
* %ADC_TM_HIGH_THR_DISABLE: Disable high and low voltage/temperature
* threshold.
*/
enum qpnp_state_request {
ADC_TM_HIGH_THR_ENABLE = 0,
+ ADC_TM_COOL_THR_ENABLE = ADC_TM_HIGH_THR_ENABLE,
ADC_TM_LOW_THR_ENABLE,
+ ADC_TM_WARM_THR_ENABLE = ADC_TM_LOW_THR_ENABLE,
ADC_TM_HIGH_LOW_THR_ENABLE,
ADC_TM_HIGH_THR_DISABLE,
+ ADC_TM_COOL_THR_DISABLE = ADC_TM_HIGH_THR_DISABLE,
ADC_TM_LOW_THR_DISABLE,
+ ADC_TM_WARM_THR_DISABLE = ADC_TM_LOW_THR_DISABLE,
ADC_TM_HIGH_LOW_THR_DISABLE,
ADC_TM_THR_NUM,
};
/**
- * struct qpnp_adc_tm_usbid_param - Represent USB_ID threshold
- * monitoring configuration.
- * @high_thr: High voltage threshold for which notification is requested.
- * @low_thr: Low voltage threshold for which notification is requested.
- * @state_request: Enable/disable the corresponding high and low voltage
- * thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_1 type.
- * @threshold_notification: Notification callback once threshold are crossed.
- * @usbid_ctx: A context of void type.
- */
-struct qpnp_adc_tm_usbid_param {
- int32_t high_thr;
- int32_t low_thr;
- enum qpnp_state_request state_request;
- enum qpnp_adc_meas_timer_1 timer_interval;
- void *usbid_ctx;
- void (*threshold_notification) (enum qpnp_tm_state state,
- void *ctx);
-};
-
-/**
* struct qpnp_adc_tm_btm_param - Represent Battery temperature threshold
* monitoring configuration.
* @high_temp: High temperature threshold for which notification is requested.
* @low_temp: Low temperature threshold for which notification is requested.
+ * @high_thr_voltage: High voltage for which notification is requested.
+ * @low_thr_voltage: Low voltage for which notification is requested.
* @state_request: Enable/disable the corresponding high and low temperature
* thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval1: Select polling rate from qpnp_adc_meas_timer_1 type.
+ * @timer_interval2: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval3: Select polling rate from qpnp_adc_meas_timer_3 type.
* @btmid_ctx: A context of void type.
* @threshold_notification: Notification callback once threshold are crossed.
+ * units to be used for High/Low temperature and voltage notification -
+ * This depends on the clients usage. Check the rscaling function
+ * for the appropriate channel nodes.
+ * @Batt therm clients temperature units is decidegreesCentigrate.
+ * @USB_ID inputs the voltage units in milli-volts.
+ * @PA_THERM inputs the units in degC.
+ * @PMIC_THERM inputs the units in millidegC.
*/
struct qpnp_adc_tm_btm_param {
int32_t high_temp;
int32_t low_temp;
+ int32_t high_thr;
+ int32_t low_thr;
+ enum qpnp_vadc_channels channel;
enum qpnp_state_request state_request;
- enum qpnp_adc_meas_timer_2 timer_interval;
+ enum qpnp_adc_meas_timer_1 timer_interval;
+ enum qpnp_adc_meas_timer_2 timer_interval2;
+ enum qpnp_adc_meas_timer_3 timer_interval3;
void *btm_ctx;
void (*threshold_notification) (enum qpnp_tm_state state,
void *ctx);
@@ -841,6 +868,17 @@
};
/**
+ * struct qpnp_adc_tm_reverse_scale_fn - Reverse scaling prototype
+ * @chan: Function pointer to one of the scaling functions
+ * which takes the adc properties, channel properties,
+ * and returns the physical result
+ */
+struct qpnp_adc_tm_reverse_scale_fn {
+ int32_t (*chan) (struct qpnp_adc_tm_btm_param *,
+ uint32_t *, uint32_t *);
+};
+
+/**
* struct qpnp_iadc_calib - IADC channel calibration structure.
* @channel - Channel for which the historical offset and gain is
* calculated. Available channels are internal rsense,
@@ -1107,6 +1145,21 @@
int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
enum qpnp_adc_calib_type calib_type);
/**
+ * qpnp_adc_scale_millidegc_pmic_voltage_thr() - Performs reverse calibration
+ * on the low/high temperature threshold values passed by the
+ * client. The function coverts milldegC to voltage threshold
+ * and accounts for the corresponding channels scaling as (2mV/K).
+ * @param: The input parameters that contain the low/high temperature
+ * values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ * the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ * the above calibrated voltage value.
+ */
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+ struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold);
+/**
* qpnp_adc_btm_scaler() - Performs reverse calibration on the low/high
* temperature threshold values passed by the client.
* The function maps the temperature to voltage and applies
@@ -1147,7 +1200,21 @@
* @high_threshold: The low threshold value that needs to be updated with
* the above calibrated voltage value.
*/
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold);
+/**
+ * qpnp_adc_vbatt_rscaler() - Performs reverse calibration on the low/high
+ * voltage threshold values passed by the client.
+ * The function applies ratiometric calibration on the
+ * voltage values.
+ * @param: The input parameters that contain the low/high voltage
+ * threshold values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ * the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ * the above calibrated voltage value.
+ */
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold);
/**
* qpnp_vadc_iadc_sync_request() - Performs Voltage ADC read and
@@ -1217,13 +1284,21 @@
enum qpnp_adc_calib_type calib_type)
{ return -ENXIO; }
static inline int32_t qpnp_adc_usb_scaler(
- struct qpnp_adc_tm_usbid_param *param,
+ struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_vbatt_rscaler(
+ struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{ return -ENXIO; }
static inline int32_t qpnp_adc_btm_scaler(
struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{ return -ENXIO; }
+static inline int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+ struct qpnp_adc_tm_btm_param *param,
+ uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
static inline int32_t qpnp_adc_tm_scale_therm_voltage_pu2(
struct qpnp_adc_tm_config *param)
{ return -ENXIO; }
@@ -1314,7 +1389,7 @@
* Clients pass the low/high voltage along with the threshold
* notification callback.
*/
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param);
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param);
/**
* qpnp_adc_tm_usbid_end() - Disables the monitoring of channel 0 thats
* assigned for monitoring USB_ID. Disables the low/high
@@ -1323,23 +1398,25 @@
*/
int32_t qpnp_adc_tm_usbid_end(void);
/**
- * qpnp_adc_tm_usbid_configure() - Configures Channel 1 of VADC_BTM to
- * monitor batt_therm channel using 100k internal pull-up.
- * Battery driver passes the high/low voltage threshold along
+ * qpnp_adc_tm_channel_measure() - Configures kernel clients a channel to
+ * monitor the corresponding ADC channel for threshold detection.
+ * Driver passes the high/low voltage threshold along
* with the notification callback once the set thresholds
* are crossed.
* @param: Structure pointer of qpnp_adc_tm_btm_param type.
* Clients pass the low/high temperature along with the threshold
* notification callback.
*/
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param);
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param);
/**
- * qpnp_adc_tm_btm_end() - Disables the monitoring of channel 1 thats
- * assigned for monitoring batt_therm. Disables the low/high
- * threshold activation for channel 1 as well.
- * @param: none.
+ * qpnp_adc_tm_disable_chan_meas() - Disables the monitoring of channel thats
+ * assigned for monitoring kernel clients. Disables the low/high
+ * threshold activation for the corresponding channel.
+ * @param: Structure pointer of qpnp_adc_tm_btm_param type.
+ * This is used to identify the channel for which the corresponding
+ * channels high/low threshold notification will be disabled.
*/
-int32_t qpnp_adc_tm_btm_end(void);
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param);
/**
* qpnp_adc_tm_is_ready() - Clients can use this API to check if the
* device is ready to use.
@@ -1349,14 +1426,14 @@
int32_t qpnp_adc_tm_is_ready(void);
#else
static inline int32_t qpnp_adc_tm_usbid_configure(
- struct qpnp_adc_tm_usbid_param *param)
+ struct qpnp_adc_tm_btm_param *param)
{ return -ENXIO; }
static inline int32_t qpnp_adc_tm_usbid_end(void)
{ return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_configure(
+static inline int32_t qpnp_adc_tm_channel_measure(
struct qpnp_adc_tm_btm_param *param)
{ return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_end(void)
+static inline int32_t qpnp_adc_tm_disable_chan_meas(void)
{ return -ENXIO; }
static inline int32_t qpnp_adc_tm_is_ready(void)
{ return -ENXIO; }
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
new file mode 100644
index 0000000..538ad15
--- /dev/null
+++ b/include/linux/regulator/cpr-regulator.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __REGULATOR_CPR_REGULATOR_H__
+#define __REGULATOR_CPR_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+
+#define CPR_REGULATOR_DRIVER_NAME "qcom,cpr-regulator"
+
+#define CPR_PVS_EFUSE_BITS_MAX 5
+#define CPR_PVS_EFUSE_BINS_MAX (1 << CPR_PVS_EFUSE_BITS_MAX)
+
+/**
+ * enum cpr_corner_enum - CPR corner enum values
+ * %CPR_CORNER_SVS: Lowest voltage for APC
+ * %CPR_CORNER_NORMAL: Normal mode voltage
+ * %CPR_CORNER_TURBO: Turbo mode voltage
+ * %CPR_CORNER_SUPER_TURBO: Super Turbo mode voltage
+ *
+ * These should be used in regulator_set_voltage() for CPR
+ * regulator as if they had units of uV.
+ */
+enum cpr_corner_enum {
+ CPR_CORNER_SVS = 1,
+ CPR_CORNER_NORMAL,
+ CPR_CORNER_TURBO,
+ CPR_CORNER_SUPER_TURBO,
+ CPR_CORNER_MAX,
+};
+
+/**
+ * enum pvs_process_enum - PVS process enum values
+ * %APC_PVS_NO: No PVS
+ * %APC_PVS_SLOW: Slow PVS process
+ * %APC_PVS_NOM: Nominal PVS process
+ * %APC_PVS_FAST: Fast PVS process
+ */
+enum apc_pvs_process_enum {
+ APC_PVS_NO,
+ APC_PVS_SLOW,
+ APC_PVS_NOM,
+ APC_PVS_FAST,
+ NUM_APC_PVS,
+};
+
+#ifdef CONFIG_MSM_CPR_REGULATOR
+
+int __init cpr_regulator_init(void);
+
+#else
+
+static inline int __init cpr_regulator_init(void)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_MSM_CPR_REGULATOR */
+
+#endif /* __REGULATOR_CPR_REGULATOR_H__ */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index a1d0445..74b09cb 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -402,6 +402,7 @@
#define V4L2_PIX_FMT_DIVX_311 v4l2_fourcc('D', 'I', 'V', '3') /* DIVX311 */
#define V4L2_PIX_FMT_DIVX v4l2_fourcc('D', 'I', 'V', 'X') /* DIVX */
#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* ON2 VP8 stream */
+#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') /* for HEVC stream */
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
@@ -1851,6 +1852,8 @@
};
#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_GOB \
(V4L2_CID_MPEG_MSM_VIDC_BASE+27)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_DELIVERY_MODE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+28)
/* 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)
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index dcdfc2b..6071e91 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -32,7 +32,7 @@
struct page **pages;
unsigned int nr_pages;
phys_addr_t phys_addr;
- void *caller;
+ const void *caller;
};
/*
@@ -62,7 +62,7 @@
extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
unsigned long start, unsigned long end, gfp_t gfp_mask,
- pgprot_t prot, int node, void *caller);
+ pgprot_t prot, int node, const void *caller);
extern void vfree(const void *addr);
extern void *vmap(struct page **pages, unsigned int count,
@@ -85,14 +85,15 @@
extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
extern struct vm_struct *get_vm_area_caller(unsigned long size,
- unsigned long flags, void *caller);
+ unsigned long flags, const void *caller);
extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end);
extern struct vm_struct *__get_vm_area_caller(unsigned long size,
unsigned long flags,
unsigned long start, unsigned long end,
- void *caller);
+ const void *caller);
extern struct vm_struct *remove_vm_area(const void *addr);
+extern struct vm_struct *find_vm_area(const void *addr);
extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
struct page ***pages);
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index c53d604..f632ad6 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -8,6 +8,7 @@
enum core_id {
MSM_VIDC_CORE_0 = 0,
+ MSM_VIDC_CORE_1, /* for Q6 core */
MSM_VIDC_CORES_MAX,
};
@@ -45,6 +46,7 @@
int msm_vidc_dqevent(void *instance, struct v4l2_event *event);
int msm_vidc_wait(void *instance);
int msm_vidc_s_parm(void *instance, struct v4l2_streamparm *a);
+int msm_vidc_enum_framesizes(void *instance, struct v4l2_frmsizeenum *fsize);
#endif
struct msm_vidc_interlace_payload {
unsigned int format;
diff --git a/include/media/msmb_camera.h b/include/media/msmb_camera.h
index 123c86c..21a1c44 100644
--- a/include/media/msmb_camera.h
+++ b/include/media/msmb_camera.h
@@ -102,9 +102,9 @@
/*word 6*/
unsigned int notify;
/*word 7*/
- unsigned int nop1;
+ unsigned int arg_value;
/*word 8*/
- unsigned int nop2;
+ unsigned int ret_value;
/*word 9*/
unsigned int nop3;
/*word 10*/
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 34b3139..7f70a01 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -9,6 +9,8 @@
#define ISP_VERSION_40 40
#define ISP_VERSION_32 32
#define ISP_NATIVE_BUF_BIT 0x10000
+#define ISP0_BIT 0x20000
+#define ISP1_BIT 0x40000
#define ISP_STATS_STREAM_BIT 0x80000000
enum ISP_START_PIXEL_PATTERN {
@@ -115,7 +117,7 @@
uint32_t output_stride;
uint32_t output_scan_lines;
uint32_t output_plane_format; /*Y/Cb/Cr/CbCr*/
-
+ uint32_t plane_addr_offset;
uint8_t csid_src; /*RDI 0-2*/
uint8_t rdi_cid;/*CID 1-16*/
};
@@ -192,6 +194,7 @@
enum msm_isp_stats_type stats_type;
uint32_t framedrop_pattern;
uint32_t irq_subsample_pattern;
+ uint32_t buffer_offset;
uint32_t stream_handle;
uint8_t comp_flag;
};
@@ -259,11 +262,18 @@
enum msm_vfe_reg_cfg_type cmd_type;
};
+enum msm_isp_buf_type {
+ ISP_PRIVATE_BUF,
+ ISP_SHARE_BUF,
+ MAX_ISP_BUF_TYPE,
+};
+
struct msm_isp_buf_request {
uint32_t session_id;
uint32_t stream_id;
uint8_t num_buf;
uint32_t handle;
+ enum msm_isp_buf_type buf_type;
};
struct msm_isp_qbuf_info {
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
index fc27ef6..3546004 100644
--- a/include/media/msmb_ispif.h
+++ b/include/media/msmb_ispif.h
@@ -76,6 +76,17 @@
struct msm_ispif_params_entry entries[INTF_MAX];
};
+struct msm_isp_info {
+ uint32_t max_resolution;
+ uint32_t id;
+ uint32_t ver;
+};
+
+struct msm_ispif_vfe_info {
+ int num_vfe;
+ struct msm_isp_info info[VFE_MAX];
+};
+
enum ispif_cfg_type_t {
ISPIF_CLK_ENABLE,
ISPIF_CLK_DISABLE,
@@ -86,6 +97,7 @@
ISPIF_STOP_IMMEDIATELY,
ISPIF_RELEASE,
ISPIF_ENABLE_REG_DUMP,
+ ISPIF_SET_VFE_INFO,
};
struct ispif_cfg_data {
@@ -93,6 +105,7 @@
union {
int reg_dump; /* ISPIF_ENABLE_REG_DUMP */
uint32_t csid_version; /* ISPIF_INIT */
+ struct msm_ispif_vfe_info vfe_info; /* ISPIF_SET_VFE_INFO */
struct msm_ispif_param_data params; /* CFG, START, STOP */
};
};
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1645608..52811ae 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -211,6 +211,22 @@
};
/**
+ * struct ieee80211_sta_vht_cap - STA's VHT capabilities
+ *
+ * This structure describes most essential parameters needed
+ * to describe 802.11ac VHT capabilities for an STA.
+ *
+ * @vht_supported: is VHT supported by the STA
+ * @cap: VHT capabilities map as described in 802.11ac spec
+ * @vht_mcs: Supported VHT MCS rates
+ */
+struct ieee80211_sta_vht_cap {
+ bool vht_supported;
+ u32 cap; /* use IEEE80211_VHT_CAP_ */
+ struct ieee80211_vht_mcs_info vht_mcs;
+};
+
+/**
* struct ieee80211_supported_band - frequency band definition
*
* This structure describes a frequency band a wiphy
@@ -233,6 +249,7 @@
int n_channels;
int n_bitrates;
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
};
/*
@@ -445,12 +462,14 @@
/**
* enum station_parameters_apply_mask - station parameter values to apply
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
+ * @STATION_PARAM_APPLY_CAPABILITY: apply new capability
*
* Not all station parameters have in-band "no change" signalling,
* for those that don't these flags will are used.
*/
enum station_parameters_apply_mask {
STATION_PARAM_APPLY_UAPSD = BIT(0),
+ STATION_PARAM_APPLY_CAPABILITY = BIT(1),
};
/**
@@ -471,6 +490,7 @@
* @plink_action: plink action to take
* @plink_state: set the peer link state for a station
* @ht_capa: HT capabilities of station
+ * @vht_capa: VHT capabilities of station
* @uapsd_queues: bitmap of queues configured for uapsd. same format
* as the AC bitmap in the QoS info field
* @max_sp: max Service Period. same format as the MAX_SP in the
@@ -478,6 +498,9 @@
* @sta_modify_mask: bitmap indicating which parameters changed
* (for those that don't have a natural "no change" value),
* see &enum station_parameters_apply_mask
+ * @capability: station capability
+ * @ext_capab: extended capabilities of the station
+ * @ext_capab_len: number of extended capabilities
*/
struct station_parameters {
u8 *supported_rates;
@@ -490,8 +513,12 @@
u8 plink_action;
u8 plink_state;
struct ieee80211_ht_cap *ht_capa;
+ struct ieee80211_vht_cap *vht_capa;
u8 uapsd_queues;
u8 max_sp;
+ u16 capability;
+ u8 *ext_capab;
+ u8 ext_capab_len;
};
/**
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index f6f44a7..04e683f 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -2418,6 +2418,16 @@
u32 sample_rate;
} __packed;
+struct asm_amrwbplus_cfg {
+ u32 size_bytes;
+ u32 version;
+ u32 num_channels;
+ u32 amr_band_mode;
+ u32 amr_dtx_mode;
+ u32 amr_frame_fmt;
+ u32 amr_lsf_idx;
+} __packed;
+
struct asm_softpause_params {
u32 enable;
u32 period;
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 5744a43..f9d2a40 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -294,6 +294,8 @@
int q6asm_media_format_block_wmapro(struct audio_client *ac,
void *cfg);
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg);
/* PP specific */
int q6asm_equalizer(struct audio_client *ac, void *eq);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index ae34bf5..d1e73a4 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -61,6 +61,7 @@
DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
{
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
.clock_base =
{
{
@@ -1619,8 +1620,6 @@
struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
int i;
- raw_spin_lock_init(&cpu_base->lock);
-
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
cpu_base->clock_base[i].cpu_base = cpu_base;
timerqueue_init_head(&cpu_base->clock_base[i].active);
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 7aac5f6..fcde89a 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -511,7 +511,7 @@
int error;
if (state == PM_SUSPEND_ON
- && !(strncmp(buf, "off", 3) && strncmp(buf, "off\n", 4)))
+ && strcmp(buf, "off") && strcmp(buf, "off\n"))
return -EINVAL;
error = pm_autosleep_set_state(state);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 07a3858..5065adb 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1280,7 +1280,7 @@
struct vm_struct *vmlist;
static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
- unsigned long flags, void *caller)
+ unsigned long flags, const void *caller)
{
vm->flags = flags;
vm->addr = (void *)va->va_start;
@@ -1306,7 +1306,7 @@
}
static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
- unsigned long flags, void *caller)
+ unsigned long flags, const void *caller)
{
setup_vmalloc_vm(vm, va, flags, caller);
insert_vmalloc_vmlist(vm);
@@ -1314,7 +1314,7 @@
static struct vm_struct *__get_vm_area_node(unsigned long size,
unsigned long align, unsigned long flags, unsigned long start,
- unsigned long end, int node, gfp_t gfp_mask, void *caller)
+ unsigned long end, int node, gfp_t gfp_mask, const void *caller)
{
struct vmap_area *va;
struct vm_struct *area;
@@ -1375,7 +1375,7 @@
struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end,
- void *caller)
+ const void *caller)
{
return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL,
caller);
@@ -1397,13 +1397,21 @@
}
struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
- void *caller)
+ const void *caller)
{
return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
-1, GFP_KERNEL, caller);
}
-static struct vm_struct *find_vm_area(const void *addr)
+/**
+ * find_vm_area - find a continuous kernel virtual area
+ * @addr: base address
+ *
+ * Search for the kernel VM area starting at @addr, and return it.
+ * It is up to the caller to do all required locking to keep the returned
+ * pointer valid.
+ */
+struct vm_struct *find_vm_area(const void *addr)
{
struct vmap_area *va;
@@ -1568,9 +1576,9 @@
static void *__vmalloc_node(unsigned long size, unsigned long align,
gfp_t gfp_mask, pgprot_t prot,
- int node, void *caller);
+ int node, const void *caller);
static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
- pgprot_t prot, int node, void *caller)
+ pgprot_t prot, int node, const void *caller)
{
const int order = 0;
struct page **pages;
@@ -1643,7 +1651,7 @@
*/
void *__vmalloc_node_range(unsigned long size, unsigned long align,
unsigned long start, unsigned long end, gfp_t gfp_mask,
- pgprot_t prot, int node, void *caller)
+ pgprot_t prot, int node, const void *caller)
{
struct vm_struct *area;
void *addr;
@@ -1704,7 +1712,7 @@
*/
static void *__vmalloc_node(unsigned long size, unsigned long align,
gfp_t gfp_mask, pgprot_t prot,
- int node, void *caller)
+ int node, const void *caller)
{
return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END,
gfp_mask, prot, node, caller);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 5063fa3..8861f91 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -145,6 +145,12 @@
{
struct fib_info *fi = container_of(head, struct fib_info, rcu);
+ change_nexthops(fi) {
+ if (nexthop_nh->nh_dev)
+ dev_put(nexthop_nh->nh_dev);
+ } endfor_nexthops(fi);
+
+ release_net(fi->fib_net);
if (fi->fib_metrics != (u32 *) dst_default_metrics)
kfree(fi->fib_metrics);
kfree(fi);
@@ -156,13 +162,7 @@
pr_warn("Freeing alive fib_info %p\n", fi);
return;
}
- change_nexthops(fi) {
- if (nexthop_nh->nh_dev)
- dev_put(nexthop_nh->nh_dev);
- nexthop_nh->nh_dev = NULL;
- } endfor_nexthops(fi);
fib_info_cnt--;
- release_net(fi->fib_net);
call_rcu(&fi->rcu, free_fib_info_rcu);
}
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 677d659..685553b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -984,9 +984,11 @@
return -ENOENT;
}
- /* in station mode, supported rates are only valid with TDLS */
+ /* in station mode, some updates are only valid with TDLS */
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
- params->supported_rates &&
+ (params->supported_rates || params->ht_capa || params->vht_capa ||
+ params->sta_modify_mask ||
+ (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) &&
!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
mutex_unlock(&local->sta_mtx);
return -EINVAL;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index db8fae5..96d1d5d 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -378,6 +378,7 @@
IEEE80211_STA_UAPSD_ENABLED = BIT(7),
IEEE80211_STA_NULLFUNC_ACKED = BIT(8),
IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9),
+ IEEE80211_STA_DISABLE_VHT = BIT(11),
};
struct ieee80211_mgd_auth_data {
@@ -1474,6 +1475,8 @@
struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
enum nl80211_channel_type channel_type);
+u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ u32 cap);
/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1633648..018e3fb 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -673,7 +673,7 @@
int result, i;
enum ieee80211_band band;
int channels, max_bitrates;
- bool supp_ht;
+ bool supp_ht, supp_vht;
static const u32 cipher_suites[] = {
/* keep WEP first, it may be removed below */
WLAN_CIPHER_SUITE_WEP40,
@@ -706,6 +706,7 @@
channels = 0;
max_bitrates = 0;
supp_ht = false;
+ supp_vht = false;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
struct ieee80211_supported_band *sband;
@@ -723,6 +724,7 @@
if (max_bitrates < sband->n_bitrates)
max_bitrates = sband->n_bitrates;
supp_ht = supp_ht || sband->ht_cap.ht_supported;
+ supp_vht = supp_vht || sband->vht_cap.vht_supported;
}
local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
@@ -798,6 +800,10 @@
if (supp_ht)
local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap);
+ if (supp_vht)
+ local->scan_ies_len +=
+ 2 + sizeof(struct ieee80211_vht_cap);
+
if (!local->ops->hw_scan) {
/* For hw_scan, driver needs to set these up. */
local->hw.wiphy->max_scan_ssids = 4;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 20c680b..a48a35c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -383,6 +383,26 @@
ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
}
+static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb,
+ struct ieee80211_supported_band *sband)
+{
+ u8 *pos;
+ u32 cap;
+ struct ieee80211_sta_vht_cap vht_cap;
+
+ BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));
+
+ memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));
+
+ /* determine capability flags */
+ cap = vht_cap.cap;
+
+ /* reserve and fill IE */
+ pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
+ ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
+}
+
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
@@ -428,6 +448,7 @@
4 + /* power capability */
2 + 2 * sband->n_channels + /* supported channels */
2 + sizeof(struct ieee80211_ht_cap) + /* HT */
+ 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
assoc_data->ie_len + /* extra IEs */
9, /* WMM */
GFP_KERNEL);
@@ -560,6 +581,9 @@
ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie,
sband, local->oper_channel, ifmgd->ap_smps);
+ if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
+ ieee80211_add_vht_ie(sdata, skb, sband);
+
/* if present, add any custom non-vendor IEs that go after HT */
if (assoc_data->ie_len && assoc_data->ie) {
noffset = ieee80211_ie_split_vendor(assoc_data->ie,
@@ -3289,6 +3313,7 @@
ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;
ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
+ ifmgd->flags &= ~IEEE80211_STA_DISABLE_VHT;
ifmgd->beacon_crc_valid = false;
@@ -3299,14 +3324,21 @@
* We can set this to true for non-11n hardware, that'll be checked
* separately along with the peer capabilities.
*/
- for (i = 0; i < req->crypto.n_ciphers_pairwise; i++)
+ for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) {
if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 ||
req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP ||
- req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104)
+ req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) {
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
+ netdev_info(sdata->dev,
+ "disabling HT/VHT due to WEP/TKIP use\n");
+ }
+ }
- if (req->flags & ASSOC_REQ_DISABLE_HT)
+ if (req->flags & ASSOC_REQ_DISABLE_HT) {
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
+ }
/* Also disable HT if we don't support it or the AP doesn't use WMM */
sband = local->hw.wiphy->bands[req->bss->channel->band];
@@ -3314,6 +3346,14 @@
local->hw.queues < 4 || !bss->wmm_used)
ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
+ /* disable VHT if we don't support it or the AP doesn't use WMM */
+ if (!sband->vht_cap.vht_supported ||
+ local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) {
+ ifmgd->flags |= IEEE80211_STA_DISABLE_VHT;
+ netdev_info(sdata->dev,
+ "disabling VHT as WMM/QoS is not supported\n");
+ }
+
memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
sizeof(ifmgd->ht_capa_mask));
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 32f7a3b..8ee7267 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1031,6 +1031,10 @@
pos += noffset - offset;
}
+ if (sband->vht_cap.vht_supported)
+ pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
+ sband->vht_cap.cap);
+
return pos - buffer;
}
@@ -1611,6 +1615,27 @@
return pos;
}
+u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
+ u32 cap)
+{
+ __le32 tmp;
+
+ *pos++ = WLAN_EID_VHT_CAPABILITY;
+ *pos++ = sizeof(struct ieee80211_vht_cap);
+ memset(pos, 0, sizeof(struct ieee80211_vht_cap));
+
+ /* capability flags */
+ tmp = cpu_to_le32(cap);
+ memcpy(pos, &tmp, sizeof(u32));
+ pos += sizeof(u32);
+
+ /* VHT MCS set */
+ memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
+ pos += sizeof(vht_cap->vht_mcs);
+
+ return pos;
+}
+
u8 *ieee80211_ie_build_ht_info(u8 *pos,
struct ieee80211_sta_ht_cap *ht_cap,
struct ieee80211_channel *channel,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 68a6b17..69318b0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -206,6 +206,12 @@
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_WDEV] = { .type = NLA_U64 },
+ [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
+ [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
+ [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+ [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
+ [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
};
/* policy for the key attributes */
@@ -811,6 +817,15 @@
dev->wiphy.bands[band]->ht_cap.ampdu_density);
}
+ /* add VHT info */
+ if (dev->wiphy.bands[band]->vht_cap.vht_supported &&
+ (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET,
+ sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs),
+ &dev->wiphy.bands[band]->vht_cap.vht_mcs) ||
+ nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA,
+ dev->wiphy.bands[band]->vht_cap.cap)))
+ goto nla_put_failure;
+
/* add frequencies */
nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS);
if (!nl_freqs)
@@ -2622,6 +2637,54 @@
return ERR_PTR(ret);
}
+static struct nla_policy
+nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
+ [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
+ [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
+};
+
+static int nl80211_set_station_tdls(struct genl_info *info,
+ struct station_parameters *params)
+{
+ struct nlattr *tb[NL80211_STA_WME_MAX + 1];
+ struct nlattr *nla;
+ int err;
+
+ /* Dummy STA entry gets updated once the peer capabilities are known */
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
+ params->ht_capa =
+ nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+ if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ params->vht_capa =
+ nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+
+ /* parse WME attributes if present */
+ if (!info->attrs[NL80211_ATTR_STA_WME])
+ return 0;
+
+ nla = info->attrs[NL80211_ATTR_STA_WME];
+ err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
+ nl80211_sta_wme_policy);
+ if (err)
+ return err;
+
+ if (tb[NL80211_STA_WME_UAPSD_QUEUES])
+ params->uapsd_queues = nla_get_u8(
+ tb[NL80211_STA_WME_UAPSD_QUEUES]);
+ if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
+ return -EINVAL;
+
+ if (tb[NL80211_STA_WME_MAX_SP])
+ params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
+
+ if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
+ return -EINVAL;
+
+ params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
+
+ return 0;
+}
+
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2650,6 +2713,19 @@
nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
}
+ if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
+ params.capability =
+ nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
+ params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
+ }
+
+ if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
+ params.ext_capab =
+ nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
+ params.ext_capab_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
+ }
+
if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
params.listen_interval =
nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
@@ -2698,6 +2774,14 @@
BIT(NL80211_STA_FLAG_MFP)))
return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
+ return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
+ return -EINVAL;
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
+ info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ return -EINVAL;
+
/* must be last in here for error handling */
params.vlan = get_vlan(info, rdev);
if (IS_ERR(params.vlan))
@@ -2712,7 +2796,17 @@
* to change the flag.
*/
params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
- /* fall through */
+ /* Include parameters for TDLS peer (driver will check) */
+ err = nl80211_set_station_tdls(info, ¶ms);
+ if (err)
+ return err;
+ /* disallow things sta doesn't support */
+ if (params.plink_action)
+ return -EINVAL;
+ if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+ BIT(NL80211_STA_FLAG_WME)))
+ return -EINVAL;
+ break;
case NL80211_IFTYPE_ADHOC:
/* disallow things sta doesn't support */
if (params.plink_action)
@@ -2721,6 +2815,9 @@
return -EINVAL;
if (params.listen_interval >= 0)
return -EINVAL;
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
+ info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ return -EINVAL;
/* reject any changes other than AUTHORIZED */
if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
return -EINVAL;
@@ -2733,6 +2830,13 @@
return -EINVAL;
if (params.listen_interval >= 0)
return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
+ return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
+ return -EINVAL;
+ if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
+ info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ return -EINVAL;
/*
* No special handling for TDLS here -- the userspace
* mesh code doesn't have this bug.
@@ -2757,12 +2861,6 @@
return err;
}
-static struct nla_policy
-nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
- [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
- [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
-};
-
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2797,10 +2895,27 @@
if (!params.aid || params.aid > IEEE80211_MAX_AID)
return -EINVAL;
+ if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
+ params.capability =
+ nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
+ params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
+ }
+
+ if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
+ params.ext_capab =
+ nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
+ params.ext_capab_len =
+ nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
+ }
+
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
params.ht_capa =
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
+ if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
+ params.vht_capa =
+ nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
+
if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
@@ -2862,6 +2977,7 @@
return -EINVAL;
break;
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
/* Only TDLS peers can be added */
if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
return -EINVAL;
diff --git a/scripts/build-all.py b/scripts/build-all.py
index 4789af7..3cecbe2 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -88,6 +88,7 @@
r'[fm]sm[0-9]*_defconfig',
r'apq*_defconfig',
r'qsd*_defconfig',
+ r'msmzinc*_defconfig',
)
for p in arch_pats:
for n in glob.glob('arch/arm/configs/' + p):
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 634493b..ca8cfaa 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -2135,12 +2135,12 @@
dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
if (w->shift == 5) {
- e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
- e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
- req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
- } else if (w->shift == 4) {
e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
+ req_clsh_state = WCD9XXX_CLSH_STATE_HPHL;
+ } else if (w->shift == 4) {
+ e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
+ e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
req_clsh_state = WCD9XXX_CLSH_STATE_HPHR;
} else {
pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 9cb303e..5f4490b 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -363,6 +363,7 @@
s32 dmic_5_6_clk_cnt;
u32 anc_slot;
+ bool anc_func;
/*track taiko interface type*/
u8 intf_type;
@@ -530,52 +531,53 @@
return 0;
}
-static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int taiko_get_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- u8 ear_pa_gain;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
- ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
-
- ear_pa_gain = ear_pa_gain >> 5;
-
- if (ear_pa_gain == 0x00) {
- ucontrol->value.integer.value[0] = 0;
- } else if (ear_pa_gain == 0x04) {
- ucontrol->value.integer.value[0] = 1;
- } else {
- pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
- __func__, ear_pa_gain);
- return -EINVAL;
- }
-
- pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
-
+ ucontrol->value.integer.value[0] = (taiko->anc_func == true ? 1 : 0);
return 0;
}
-static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int taiko_put_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- u8 ear_pa_gain;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
- pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
- ucontrol->value.integer.value[0]);
+ mutex_lock(&dapm->codec->mutex);
+ taiko->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
- switch (ucontrol->value.integer.value[0]) {
- case 0:
- ear_pa_gain = 0x00;
- break;
- case 1:
- ear_pa_gain = 0x80;
- break;
- default:
- return -EINVAL;
+ dev_dbg(codec->dev, "%s: anc_func %x", __func__, taiko->anc_func);
+
+ if (taiko->anc_func == true) {
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_enable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_enable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_enable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_enable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_disable_pin(dapm, "HPHR");
+ snd_soc_dapm_disable_pin(dapm, "HPHL");
+ snd_soc_dapm_disable_pin(dapm, "HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "EAR");
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_enable_pin(dapm, "HPHR");
+ snd_soc_dapm_enable_pin(dapm, "HPHL");
+ snd_soc_dapm_enable_pin(dapm, "HEADPHONE");
+ snd_soc_dapm_enable_pin(dapm, "EAR PA");
+ snd_soc_dapm_enable_pin(dapm, "EAR");
}
-
- snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
return 0;
}
@@ -935,9 +937,15 @@
return 0;
}
-static const char * const taiko_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
-static const struct soc_enum taiko_ear_pa_gain_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
+
+
+static const char *const taiko_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum taiko_anc_func_enum =
+ SOC_ENUM_SINGLE_EXT(2, taiko_anc_func_text);
+
+static const char *const tabla_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum tabla_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, tabla_ear_pa_gain_text),
};
/*cut of frequency for high pass filter*/
@@ -1009,26 +1017,6 @@
static const struct snd_kcontrol_new taiko_snd_controls[] = {
- SOC_ENUM_EXT("EAR PA Gain", taiko_ear_pa_gain_enum[0],
- taiko_pa_gain_get, taiko_pa_gain_put),
-
- SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 12, 1,
- line_gain),
- SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 12, 1,
- line_gain),
- SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 12, 1,
- line_gain),
- SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 12, 1,
- line_gain),
-
- SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 12, 1,
- line_gain),
- SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 12, 1,
- line_gain),
-
- SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
- line_gain),
-
SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
@@ -1064,6 +1052,7 @@
digital_gain),
SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
40, digital_gain),
+
SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
40, digital_gain),
SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
@@ -1072,15 +1061,12 @@
40, digital_gain),
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
- SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
taiko_put_anc_slot),
+ SOC_ENUM_EXT("ANC Function", taiko_anc_func_enum, taiko_get_anc_func,
+ taiko_put_anc_func),
+
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -1170,6 +1156,122 @@
};
+static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
+
+ ear_pa_gain = ear_pa_gain >> 5;
+
+ ucontrol->value.integer.value[0] = ear_pa_gain;
+
+ pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+ return 0;
+}
+
+static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+
+ ear_pa_gain = ucontrol->value.integer.value[0] << 5;
+
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
+ return 0;
+}
+
+static const char * const taiko_1_x_ear_pa_gain_text[] = {
+ "POS_6_DB", "UNDEFINED_1", "UNDEFINED_2", "UNDEFINED_3", "POS_2_DB",
+ "NEG_2P5_DB", "UNDEFINED_4", "NEG_12_DB"
+};
+
+static const struct soc_enum taiko_1_x_ear_pa_gain_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_1_x_ear_pa_gain_text),
+ taiko_1_x_ear_pa_gain_text);
+
+static const struct snd_kcontrol_new taiko_1_x_analog_gain_controls[] = {
+
+ SOC_ENUM_EXT("EAR PA Gain", taiko_1_x_ear_pa_gain_enum,
+ taiko_pa_gain_get, taiko_pa_gain_put),
+
+ SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 7, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+};
+
+static const char * const taiko_2_x_ear_pa_gain_text[] = {
+ "POS_6_DB", "POS_4P5_DB", "POS_3_DB", "POS_1P5_DB",
+ "POS_0_DB", "NEG_2P5_DB", "UNDEFINED", "NEG_12_DB"
+};
+
+static const struct soc_enum taiko_2_x_ear_pa_gain_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_2_x_ear_pa_gain_text),
+ taiko_2_x_ear_pa_gain_text);
+
+static const struct snd_kcontrol_new taiko_2_x_analog_gain_controls[] = {
+
+ SOC_ENUM_EXT("EAR PA Gain", taiko_2_x_ear_pa_gain_enum,
+ taiko_pa_gain_get, taiko_pa_gain_put),
+
+ SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 20, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 20, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 20, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("SPK DRV Volume", TAIKO_A_SPKR_DRV_GAIN, 3, 8, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_CDC_TX_1_GAIN, 2, 19, 0,
+ analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_CDC_TX_2_GAIN, 2, 19, 0,
+ analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_CDC_TX_3_GAIN, 2, 19, 0,
+ analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_CDC_TX_4_GAIN, 2, 19, 0,
+ analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_CDC_TX_5_GAIN, 2, 19, 0,
+ analog_gain),
+ SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_CDC_TX_6_GAIN, 2, 19, 0,
+ analog_gain),
+};
+
static const char * const rx_mix1_text[] = {
"ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
"RX5", "RX6", "RX7"
@@ -2209,101 +2311,6 @@
return 0;
}
-static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- const char *filename;
- const struct firmware *fw;
- int i;
- int ret;
- int num_anc_slots;
- struct anc_header *anc_head;
- struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
- u32 anc_writes_size = 0;
- int anc_size_remaining;
- u32 *anc_ptr;
- u16 reg;
- u8 mask, val;
-
- pr_debug("%s %d\n", __func__, event);
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
-
- filename = "wcd9320/wcd9320_anc.bin";
-
- ret = request_firmware(&fw, filename, codec->dev);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
- ret);
- return -ENODEV;
- }
-
- if (fw->size < sizeof(struct anc_header)) {
- dev_err(codec->dev, "Not enough data\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- /* First number is the number of register writes */
- anc_head = (struct anc_header *)(fw->data);
- anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
- anc_size_remaining = fw->size - sizeof(struct anc_header);
- num_anc_slots = anc_head->num_anc_slots;
-
- if (taiko->anc_slot >= num_anc_slots) {
- dev_err(codec->dev, "Invalid ANC slot selected\n");
- release_firmware(fw);
- return -EINVAL;
- }
-
- for (i = 0; i < num_anc_slots; i++) {
-
- if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -EINVAL;
- }
- anc_writes_size = (u32)(*anc_ptr);
- anc_size_remaining -= sizeof(u32);
- anc_ptr += 1;
-
- if (anc_writes_size * TAIKO_PACKED_REG_SIZE
- > anc_size_remaining) {
- dev_err(codec->dev, "Invalid register format\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- if (taiko->anc_slot == i)
- break;
-
- anc_size_remaining -= (anc_writes_size *
- TAIKO_PACKED_REG_SIZE);
- anc_ptr += anc_writes_size;
- }
- if (i == num_anc_slots) {
- dev_err(codec->dev, "Selected ANC slot not present\n");
- release_firmware(fw);
- return -ENOMEM;
- }
-
- for (i = 0; i < anc_writes_size; i++) {
- TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
- mask, val);
- snd_soc_write(codec, reg, val);
- }
- release_firmware(fw);
-
- break;
- case SND_SOC_DAPM_POST_PMD:
- snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
- snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
- break;
- }
- return 0;
-}
-
static int taiko_codec_config_mad(struct snd_soc_codec *codec)
{
int ret;
@@ -2805,6 +2812,106 @@
return 0;
}
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ const char *filename;
+ const struct firmware *fw;
+ int i;
+ int ret;
+ int num_anc_slots;
+ struct anc_header *anc_head;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u32 anc_writes_size = 0;
+ int anc_size_remaining;
+ u32 *anc_ptr;
+ u16 reg;
+ u8 mask, val, old_val;
+
+
+ if (taiko->anc_func == 0)
+ return 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ filename = "wcd9320/wcd9320_anc.bin";
+
+ ret = request_firmware(&fw, filename, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ if (fw->size < sizeof(struct anc_header)) {
+ dev_err(codec->dev, "Not enough data\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ /* First number is the number of register writes */
+ anc_head = (struct anc_header *)(fw->data);
+ anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+ anc_size_remaining = fw->size - sizeof(struct anc_header);
+ num_anc_slots = anc_head->num_anc_slots;
+
+ if (taiko->anc_slot >= num_anc_slots) {
+ dev_err(codec->dev, "Invalid ANC slot selected\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ for (i = 0; i < num_anc_slots; i++) {
+ if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ anc_writes_size = (u32)(*anc_ptr);
+ anc_size_remaining -= sizeof(u32);
+ anc_ptr += 1;
+
+ if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+ > anc_size_remaining) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ if (taiko->anc_slot == i)
+ break;
+
+ anc_size_remaining -= (anc_writes_size *
+ TAIKO_PACKED_REG_SIZE);
+ anc_ptr += anc_writes_size;
+ }
+ if (i == num_anc_slots) {
+ dev_err(codec->dev, "Selected ANC slot not present\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+ for (i = 0; i < anc_writes_size; i++) {
+ TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+ mask, val);
+ old_val = snd_soc_read(codec, reg);
+ snd_soc_write(codec, reg, (old_val & ~mask) |
+ (val & mask));
+ }
+ release_firmware(fw);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ msleep(40);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+ msleep(20);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+ break;
+ }
+ return 0;
+}
+
static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2860,6 +2967,46 @@
return 0;
}
+static int taiko_codec_enable_anc_hph(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ if (w->shift == 4) {
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->shift == 4) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x30);
+ msleep(30);
+ }
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ msleep(40);
+ }
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_TX_7_MBHC_EN, 0x80, 00);
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ }
+ case SND_SOC_DAPM_POST_PMD:
+ ret = taiko_hph_pa_event(w, kcontrol, event);
+ break;
+ }
+ return ret;
+}
+
static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
4, 0, NULL, 0),
@@ -3047,9 +3194,10 @@
{"EAR_PA_MIXER", NULL, "DAC1"},
{"DAC1", NULL, "RX_BIAS"},
+ {"ANC EAR", NULL, "ANC EAR PA"},
+ {"ANC EAR PA", NULL, "EAR_PA_MIXER"},
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
- {"ANC", NULL, "ANC1 FB MUX"},
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
@@ -3063,18 +3211,28 @@
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
{"HPHR DAC", NULL, "RX_BIAS"},
- {"ANC", NULL, "ANC1 MUX"},
- {"ANC", NULL, "ANC2 MUX"},
+ {"ANC HEADPHONE", NULL, "ANC HPHL"},
+ {"ANC HEADPHONE", NULL, "ANC HPHR"},
+
+ {"ANC HPHL", NULL, "HPHL_PA_MIXER"},
+ {"ANC HPHR", NULL, "HPHR_PA_MIXER"},
+
{"ANC1 MUX", "ADC1", "ADC1"},
{"ANC1 MUX", "ADC2", "ADC2"},
{"ANC1 MUX", "ADC3", "ADC3"},
{"ANC1 MUX", "ADC4", "ADC4"},
+ {"ANC1 MUX", "DMIC1", "DMIC1"},
+ {"ANC1 MUX", "DMIC2", "DMIC2"},
+ {"ANC1 MUX", "DMIC3", "DMIC3"},
+ {"ANC1 MUX", "DMIC4", "DMIC4"},
+ {"ANC1 MUX", "DMIC5", "DMIC5"},
+ {"ANC1 MUX", "DMIC6", "DMIC6"},
{"ANC2 MUX", "ADC1", "ADC1"},
{"ANC2 MUX", "ADC2", "ADC2"},
{"ANC2 MUX", "ADC3", "ADC3"},
{"ANC2 MUX", "ADC4", "ADC4"},
- {"ANC", NULL, "CDC_CONN"},
+ {"ANC HPHR", NULL, "CDC_CONN"},
{"DAC1", "Switch", "CLASS_H_DSM MUX"},
{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
@@ -3120,8 +3278,8 @@
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
- {"RX1 CHAIN", NULL, "ANC"},
- {"RX2 CHAIN", NULL, "ANC"},
+ {"RX1 MIX2", NULL, "ANC1 MUX"},
+ {"RX2 MIX2", NULL, "ANC2 MUX"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -3454,6 +3612,14 @@
(reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
return 1;
+ /* ANC filter registers are not cacheable */
+ if ((reg >= TAIKO_A_CDC_ANC1_IIR_B1_CTL) &&
+ (reg <= TAIKO_A_CDC_ANC1_LPF_B2_CTL))
+ return 1;
+ if ((reg >= TAIKO_A_CDC_ANC2_IIR_B1_CTL) &&
+ (reg <= TAIKO_A_CDC_ANC2_LPF_B2_CTL))
+ return 1;
+
/* Digital gain register is not cacheable so we have to write
* the setting even it is the same
*/
@@ -3768,7 +3934,7 @@
taiko->comp_fs[comp_rx_path[j]]
= compander_fs;
}
- if (j <= 2)
+ if (j < 2)
rx_mix_1_reg_1 += 3;
else
rx_mix_1_reg_1 += 2;
@@ -4482,6 +4648,32 @@
return 0;
}
+static int taiko_codec_enable_anc_ear(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = taiko_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x10);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_EN, 0x10, 0x00);
+ msleep(40);
+ ret |= taiko_codec_enable_anc(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = taiko_codec_enable_ear_pa(w, kcontrol, event);
+ break;
+ }
+ return ret;
+}
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
@@ -4779,10 +4971,20 @@
SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
- SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
- taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
+ SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+ taiko_codec_enable_anc_hph,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+ taiko_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUTPUT("ANC EAR"),
+ SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ taiko_codec_enable_anc_ear,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
SND_SOC_DAPM_INPUT("AMIC2"),
@@ -5283,6 +5485,12 @@
TAIKO_REG_VAL(TAIKO_A_CDC_TX9_MUX_CTL, 0x48),
TAIKO_REG_VAL(TAIKO_A_CDC_TX10_MUX_CTL, 0x48),
TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B4_CTL, 0x8),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B4_CTL, 0x8),
TAIKO_REG_VAL(TAIKO_A_CDC_VBAT_GAIN_UPD_MON, 0x0),
TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B1_CTL, 0x0),
TAIKO_REG_VAL(TAIKO_A_CDC_PA_RAMP_B2_CTL, 0x0),
@@ -5708,12 +5916,19 @@
taiko_init_slim_slave_cfg(codec);
}
- if (TAIKO_IS_1_0(control->version))
+ if (TAIKO_IS_1_0(control->version)) {
snd_soc_dapm_new_controls(dapm, taiko_1_dapm_widgets,
ARRAY_SIZE(taiko_1_dapm_widgets));
- else
+ snd_soc_add_codec_controls(codec,
+ taiko_1_x_analog_gain_controls,
+ ARRAY_SIZE(taiko_1_x_analog_gain_controls));
+ } else {
snd_soc_dapm_new_controls(dapm, taiko_2_dapm_widgets,
ARRAY_SIZE(taiko_2_dapm_widgets));
+ snd_soc_add_codec_controls(codec,
+ taiko_2_x_analog_gain_controls,
+ ARRAY_SIZE(taiko_2_x_analog_gain_controls));
+ }
control->num_rx_port = TAIKO_RX_MAX;
control->rx_chs = ptr;
@@ -5727,6 +5942,14 @@
(void) taiko_setup_irqs(taiko);
atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+ mutex_lock(&dapm->codec->mutex);
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHL");
+ snd_soc_dapm_disable_pin(dapm, "ANC HPHR");
+ snd_soc_dapm_disable_pin(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR PA");
+ snd_soc_dapm_disable_pin(dapm, "ANC EAR");
+ snd_soc_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
codec->ignore_pmdown_time = 1;
return ret;
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 5b54e1b..764f4c6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -3018,14 +3018,19 @@
switch (event) {
case WCD9XXX_EVENT_PRE_MICBIAS_1_ON:
ret = MBHC_MICBIAS1;
+ break;
case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
ret = MBHC_MICBIAS2;
+ break;
case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
ret = MBHC_MICBIAS3;
+ break;
case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
ret = MBHC_MICBIAS4;
+ break;
default:
ret = MBHC_MICBIAS_INVALID;
+ break;
}
return ret;
}
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index fb77c8d..cafc5c3 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,8 +41,9 @@
#define MSM_SLIM_0_RX_MAX_CHANNELS 2
#define MSM_SLIM_0_TX_MAX_CHANNELS 4
-#define BTSCO_RATE_8KHZ 8000
-#define BTSCO_RATE_16KHZ 16000
+#define SAMPLE_RATE_8KHZ 8000
+#define SAMPLE_RATE_16KHZ 16000
+#define SAMPLE_RATE_48KHZ 48000
#define BOTTOM_SPK_AMP_POS 0x1
#define BOTTOM_SPK_AMP_NEG 0x2
@@ -67,6 +68,7 @@
enum {
SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
+ SLIM_1_TX_2 = 147, /* USB RX */
SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
SLIM_3_TX_1 = 153, /* HDMI RX */
@@ -90,8 +92,11 @@
static int msm_slim_0_tx_ch = 1;
static int msm_slim_3_rx_ch = 1;
-static int msm_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm_slim_1_rate = SAMPLE_RATE_8KHZ;
static int msm_btsco_ch = 1;
+static int msm_slim_1_rx_ch = 1;
+static int msm_slim_1_tx_ch = 1;
+
static int hdmi_rate_variable;
static int rec_mode = INCALL_REC_MONO;
@@ -651,11 +656,14 @@
SOC_ENUM_SINGLE_EXT(2, hdmi_rate),
};
-static const char *btsco_rate_text[] = {"8000", "16000"};
-static const struct soc_enum msm_btsco_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, btsco_rate_text),
+static const char * const slim1_rate_text[] = {"8000", "16000", "48000"};
+static const struct soc_enum msm_slim_1_rate_enum[] = {
+ SOC_ENUM_SINGLE_EXT(3, slim1_rate_text),
};
-
+static const char * const slim1_tx_ch_text[] = {"One", "Two"};
+static const struct soc_enum msm_slim_1_tx_ch_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, slim1_tx_ch_text),
+};
static int msm_slim_0_rx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -671,7 +679,7 @@
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);
+ msm_slim_0_rx_ch);
return 1;
}
@@ -694,6 +702,27 @@
return 1;
}
+static int msm_slim_1_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_slim_1_tx_ch = %d\n", __func__,
+ msm_slim_1_tx_ch);
+
+ ucontrol->value.integer.value[0] = msm_slim_1_tx_ch - 1;
+ return 0;
+}
+
+static int msm_slim_1_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_slim_1_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm_slim_1_tx_ch = %d\n", __func__,
+ msm_slim_1_tx_ch);
+
+ return 1;
+}
+
static int msm_slim_3_rx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -713,31 +742,35 @@
return 1;
}
-static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
+static int msm_slim_1_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- pr_debug("%s: msm_btsco_rate = %d", __func__,
- msm_btsco_rate);
- ucontrol->value.integer.value[0] = msm_btsco_rate;
+ pr_debug("%s: msm_slim_1_rate = %d", __func__,
+ msm_slim_1_rate);
+
+ ucontrol->value.integer.value[0] = msm_slim_1_rate;
return 0;
}
-static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol,
+static int msm_slim_1_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
switch (ucontrol->value.integer.value[0]) {
case 8000:
- msm_btsco_rate = BTSCO_RATE_8KHZ;
+ msm_slim_1_rate = SAMPLE_RATE_8KHZ;
break;
case 16000:
- msm_btsco_rate = BTSCO_RATE_16KHZ;
+ msm_slim_1_rate = SAMPLE_RATE_16KHZ;
+ break;
+ case 48000:
+ msm_slim_1_rate = SAMPLE_RATE_48KHZ;
break;
default:
- msm_btsco_rate = BTSCO_RATE_8KHZ;
+ msm_slim_1_rate = SAMPLE_RATE_8KHZ;
break;
}
- pr_debug("%s: msm_btsco_rate = %d\n", __func__,
- msm_btsco_rate);
+ pr_debug("%s: msm_slim_1_rate = %d\n", __func__,
+ msm_slim_1_rate);
return 0;
}
@@ -780,8 +813,10 @@
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),
- SOC_ENUM_EXT("Internal BTSCO SampleRate", msm_btsco_enum[0],
- msm_btsco_rate_get, msm_btsco_rate_put),
+ SOC_ENUM_EXT("SLIM_1_TX Channels", msm_slim_1_tx_ch_enum[0],
+ msm_slim_1_tx_ch_get, msm_slim_1_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_1 SampleRate", msm_slim_1_rate_enum[0],
+ msm_slim_1_rate_get, msm_slim_1_rate_put),
SOC_SINGLE_EXT("Incall Rec Mode", SND_SOC_NOPM, 0, 1, 0,
msm_incall_rec_mode_get, msm_incall_rec_mode_put),
SOC_ENUM_EXT("SLIM_3_RX Channels", msm_enum[1],
@@ -1001,7 +1036,7 @@
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret = 0;
- unsigned int rx_ch = SLIM_1_RX_1, tx_ch = SLIM_1_TX_1;
+ unsigned int rx_ch = SLIM_1_RX_1, tx_ch[2] = {SLIM_1_TX_1, SLIM_1_TX_2};
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pr_debug("%s: APQ BT/USB TX -> SLIMBUS_1_RX -> MDM TX shared ch %d\n",
@@ -1015,10 +1050,11 @@
goto end;
}
} else {
- pr_debug("%s: MDM RX -> SLIMBUS_1_TX -> APQ BT/USB Rx shared ch %d\n",
- __func__, tx_ch);
+ pr_debug("%s: MDM RX ->SLIMBUS_1_TX ->APQ BT/USB Rx shared ch %d %d\n",
+ __func__, tx_ch[0], tx_ch[1]);
- ret = snd_soc_dai_set_channel_map(cpu_dai, 1, &tx_ch, 0, 0);
+ ret = snd_soc_dai_set_channel_map(cpu_dai, msm_slim_1_tx_ch,
+ tx_ch, 0, 0);
if (ret < 0) {
pr_err("%s: Erorr %d setting SLIM_1 TX channel map\n",
__func__, ret);
@@ -1358,16 +1394,46 @@
struct snd_pcm_hw_params *params)
{
struct snd_interval *rate = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_RATE);
+ SNDRV_PCM_HW_PARAM_RATE);
struct snd_interval *channels = hw_param_interval(params,
- SNDRV_PCM_HW_PARAM_CHANNELS);
+ SNDRV_PCM_HW_PARAM_CHANNELS);
- rate->min = rate->max = msm_btsco_rate;
+ rate->min = rate->max = msm_slim_1_rate;
channels->min = channels->max = msm_btsco_ch;
return 0;
}
+static int msm_slim_1_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);
+
+ rate->min = rate->max = msm_slim_1_rate;
+ channels->min = channels->max = msm_slim_1_rx_ch;
+
+ return 0;
+}
+
+static int msm_slim_1_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);
+
+ rate->min = rate->max = msm_slim_1_rate;
+ channels->min = channels->max = msm_slim_1_tx_ch;
+
+ return 0;
+}
+
static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1728,20 +1794,18 @@
.codec_name = "snd-soc-dummy",
},
{
- .name = "VoLTE",
- .stream_name = "VoLTE",
- .cpu_dai_name = "VoLTE",
- .platform_name = "msm-pcm-voice",
+ .name = "VoLTE Stub",
+ .stream_name = "VoLTE Stub",
+ .cpu_dai_name = "VOLTE_STUB",
+ .platform_name = "msm-pcm-hostless",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
- /* this dainlink has playback support */
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOLTE,
},
{
.name = "MSM8960 LowLatency",
@@ -1800,6 +1864,21 @@
.ignore_pmdown_time = 1, /* this dailink has playback support */
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
},
+ {
+ .name = "Voice2 Stub",
+ .stream_name = "Voice2 Stub",
+ .cpu_dai_name = "VOICE2_STUB",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ /* this dainlink has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1971,7 +2050,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
- .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_slim_1_rx_be_hw_params_fixup,
.ops = &msm_slimbus_1_be_ops,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1985,7 +2064,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
- .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_slim_1_tx_be_hw_params_fixup,
.ops = &msm_slimbus_1_be_ops,
},
/* Ultrasound TX Back End DAI Link */
diff --git a/sound/soc/msm/lpass-dma.c b/sound/soc/msm/lpass-dma.c
index 39a7f7f..50938df 100644
--- a/sound/soc/msm/lpass-dma.c
+++ b/sound/soc/msm/lpass-dma.c
@@ -16,7 +16,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
-#include <linux/android_pmem.h>
+
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 4e6cbaa..e54f8b7 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -29,7 +29,7 @@
#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <sound/timer.h>
#include <mach/qdsp6v2/q6core.h>
#include <sound/pcm.h>
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index e00e409..734bd39 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -550,8 +550,8 @@
},
{
.playback = {
- .stream_name = "SGLTE Playback",
- .aif_name = "SGLTE_DL",
+ .stream_name = "Voice2 Playback",
+ .aif_name = "VOICE2_DL",
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
@@ -560,8 +560,8 @@
.rate_max = 48000,
},
.capture = {
- .stream_name = "SGLTE Capture",
- .aif_name = "SGLTE_UL",
+ .stream_name = "Voice2 Capture",
+ .aif_name = "VOICE2_UL",
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
@@ -570,7 +570,7 @@
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
- .name = "SGLTE",
+ .name = "Voice2",
},
{
.playback = {
@@ -626,6 +626,54 @@
.ops = &msm_fe_dai_ops,
.name = "LSM",
},
+ {
+ .playback = {
+ .stream_name = "VoLTE Stub Playback",
+ .aif_name = "VOLTE_STUB_DL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "VoLTE Stub Capture",
+ .aif_name = "VOLTE_STUB_UL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "VOLTE_STUB",
+ },
+ {
+ .playback = {
+ .stream_name = "Voice2 Stub Playback",
+ .aif_name = "VOICE2_STUB_DL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "Voice2 Stub Capture",
+ .aif_name = "VOICE2_STUB_UL",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "VOICE2_STUB",
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-lowlatency-pcm-q6.c b/sound/soc/msm/msm-lowlatency-pcm-q6.c
index 6ad1410..d5281e4 100644
--- a/sound/soc/msm/msm-lowlatency-pcm-q6.c
+++ b/sound/soc/msm/msm-lowlatency-pcm-q6.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/soc.h>
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 10b7e30..26bf3d9 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/soc.h>
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index e01c759..a3bcf23 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 6f1a01d..ba054bd 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -26,7 +26,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index c326437..1d15c11 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -27,7 +27,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include "msm-pcm-q6.h"
#include "msm-pcm-routing.h"
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 6cf74d5..c5cb560 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -733,8 +733,8 @@
session_id = voc_get_session_id(VOICE_SESSION_NAME);
else if (val == MSM_FRONTEND_DAI_VOLTE)
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else if (val == MSM_FRONTEND_DAI_SGLTE)
- session_id = voc_get_session_id(SGLTE_SESSION_NAME);
+ else if (val == MSM_FRONTEND_DAI_VOICE2)
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
else
session_id = voc_get_session_id(VOIP_SESSION_NAME);
@@ -1768,12 +1768,18 @@
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_PRI_I2S_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1789,8 +1795,8 @@
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_I2S_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1807,8 +1813,8 @@
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1825,11 +1831,17 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1846,8 +1858,14 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_MI2S_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1864,11 +1882,17 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AFE_PCM_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1885,11 +1909,17 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_AUXPCM_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1906,8 +1936,8 @@
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1927,8 +1957,14 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("SGLTE", MSM_BACKEND_DAI_HDMI_RX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
@@ -1939,18 +1975,36 @@
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_EXTPROC_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_EXTPROC_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_EXTPROC_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
};
static const struct snd_kcontrol_new slimbus_1_rx_mixer_controls[] = {
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
};
static const struct snd_kcontrol_new slimbus_3_rx_mixer_controls[] = {
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SLIMBUS_3_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE Stub", MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
};
static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
@@ -2004,30 +2058,30 @@
msm_routing_put_voice_mixer),
};
-static const struct snd_kcontrol_new tx_sglte_mixer_controls[] = {
- SOC_SINGLE_EXT("PRI_TX_SGLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_TX_Voice2", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SEC_TX_SGLTE", MSM_BACKEND_DAI_SEC_I2S_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("SEC_TX_Voice2", MSM_BACKEND_DAI_SEC_I2S_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("MI2S_TX_SGLTE", MSM_BACKEND_DAI_MI2S_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("MI2S_TX_Voice2", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SLIM_0_TX_SGLTE", MSM_BACKEND_DAI_SLIMBUS_0_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("SLIM_0_TX_Voice2", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_SGLTE",
- MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_SGLTE, 1, 0,
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice2",
+ MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOICE2, 1, 0,
msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("AFE_PCM_TX_SGLTE", MSM_BACKEND_DAI_AFE_PCM_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("AFE_PCM_TX_Voice2", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("AUX_PCM_TX_SGLTE", MSM_BACKEND_DAI_AUXPCM_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
- SOC_SINGLE_EXT("SEC_AUX_PCM_TX_SGLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
- MSM_FRONTEND_DAI_SGLTE, 1, 0, msm_routing_get_voice_mixer,
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
@@ -2087,6 +2141,66 @@
msm_routing_put_voice_stub_mixer),
};
+static const struct snd_kcontrol_new tx_volte_stub_mixer_controls[] = {
+ SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("STUB_1_TX_HL", MSM_BACKEND_DAI_EXTPROC_EC_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("PRIMARY_I2S_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SECONDARY_I2S_TX", MSM_BACKEND_DAI_SEC_I2S_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+};
+
+static const struct snd_kcontrol_new tx_voice2_stub_mixer_controls[] = {
+ SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("STUB_1_TX_HL", MSM_BACKEND_DAI_EXTPROC_EC_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("PRIMARY_I2S_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SECONDARY_I2S_TX", MSM_BACKEND_DAI_SEC_I2S_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+};
+
static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2553,8 +2667,8 @@
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_IN("SGLTE_DL", "SGLTE Playback", 0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("SGLTE_UL", "SGLTE Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICE2_UL", "Voice2 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
0, 0, 0, 0),
@@ -2622,6 +2736,12 @@
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOLTE_STUB_DL", "VOLTE_STUB Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOLTE_STUB_UL", "VOLTE_STUB Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOICE2_STUB_DL",
+ "VOICE2_STUB Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICE2_STUB_UL",
+ "VOICE2_STUB Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
@@ -2712,9 +2832,9 @@
SND_SOC_DAPM_MIXER("VoLTE_Tx Mixer",
SND_SOC_NOPM, 0, 0, tx_volte_mixer_controls,
ARRAY_SIZE(tx_volte_mixer_controls)),
- SND_SOC_DAPM_MIXER("SGLTE_Tx Mixer",
- SND_SOC_NOPM, 0, 0, tx_sglte_mixer_controls,
- ARRAY_SIZE(tx_sglte_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Voice2_Tx Mixer",
+ SND_SOC_NOPM, 0, 0, tx_voice2_mixer_controls,
+ ARRAY_SIZE(tx_voice2_mixer_controls)),
SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -2758,7 +2878,12 @@
ARRAY_SIZE(sbus_3_rx_port_mixer_controls)),
SND_SOC_DAPM_MIXER("MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
mi2s_rx_port_mixer_controls, ARRAY_SIZE(mi2s_rx_port_mixer_controls)),
-
+ SND_SOC_DAPM_MIXER("VoLTE Stub Tx Mixer", SND_SOC_NOPM, 0, 0,
+ tx_volte_stub_mixer_controls,
+ ARRAY_SIZE(tx_volte_stub_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Voice2 Stub Tx Mixer", SND_SOC_NOPM, 0, 0,
+ tx_voice2_stub_mixer_controls,
+ ARRAY_SIZE(tx_voice2_stub_mixer_controls)),
/* Virtual Pins to force backends ON atm */
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_INPUT("BE_IN"),
@@ -2890,7 +3015,7 @@
{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"PRI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"PRI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"PRI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
@@ -2898,49 +3023,49 @@
{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"SEC_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"SEC_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"SLIM_0_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"SLIM_0_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"INTERNAL_BT_SCO_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"AFE_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"AFE_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"AUX_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
{"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"SEC_AUX_PCM_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
- {"HDMI_RX_Voice Mixer", "SGLTE", "SGLTE_DL"},
+ {"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
@@ -2963,15 +3088,15 @@
{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
{"VoLTE_Tx Mixer", "SEC_AUX_PCM_TX_VoLTE", "SEC_AUX_PCM_TX"},
{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
- {"SGLTE_Tx Mixer", "PRI_TX_SGLTE", "PRI_I2S_TX"},
- {"SGLTE_Tx Mixer", "SEC_TX_SGLTE", "SEC_I2S_TX"},
- {"SGLTE_Tx Mixer", "MI2S_TX_SGLTE", "MI2S_TX"},
- {"SGLTE_Tx Mixer", "SLIM_0_TX_SGLTE", "SLIMBUS_0_TX"},
- {"SGLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_SGLTE", "INT_BT_SCO_TX"},
- {"SGLTE_Tx Mixer", "AFE_PCM_TX_SGLTE", "PCM_TX"},
- {"SGLTE_Tx Mixer", "AUX_PCM_TX_SGLTE", "AUX_PCM_TX"},
- {"SGLTE_Tx Mixer", "SEC_AUX_PCM_TX_SGLTE", "SEC_AUX_PCM_TX"},
- {"SGLTE_UL", NULL, "SGLTE_Tx Mixer"},
+ {"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
+ {"Voice2_Tx Mixer", "SEC_TX_Voice2", "SEC_I2S_TX"},
+ {"Voice2_Tx Mixer", "MI2S_TX_Voice2", "MI2S_TX"},
+ {"Voice2_Tx Mixer", "SLIM_0_TX_Voice2", "SLIMBUS_0_TX"},
+ {"Voice2_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice2", "INT_BT_SCO_TX"},
+ {"Voice2_Tx Mixer", "AFE_PCM_TX_Voice2", "PCM_TX"},
+ {"Voice2_Tx Mixer", "AUX_PCM_TX_Voice2", "AUX_PCM_TX"},
+ {"Voice2_Tx Mixer", "SEC_AUX_PCM_TX_Voice2", "SEC_AUX_PCM_TX"},
+ {"VOICE2_UL", NULL, "Voice2_Tx Mixer"},
{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
{"Voip_Tx Mixer", "SEC_TX_Voip", "SEC_I2S_TX"},
{"Voip_Tx Mixer", "MI2S_TX_Voip", "MI2S_TX"},
@@ -3017,17 +3142,53 @@
{"Voice Stub Tx Mixer", "AFE_PCM_TX", "PCM_TX"},
{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
+ {"VoLTE Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
+ {"VoLTE Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
+ {"VoLTE Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"VoLTE Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
+ {"VoLTE Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
+ {"VoLTE Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
+ {"VoLTE Stub Tx Mixer", "PRIMARY_I2S_TX", "PRI_I2S_TX"},
+ {"VoLTE Stub Tx Mixer", "SECONDARY_I2S_TX", "SEC_I2S_TX"},
+ {"VoLTE Stub Tx Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"VOLTE_STUB_UL", NULL, "VoLTE Stub Tx Mixer"},
+
+ {"Voice2 Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
+ {"Voice2 Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
+ {"Voice2 Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"Voice2 Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
+ {"Voice2 Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
+ {"Voice2 Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
+ {"Voice2 Stub Tx Mixer", "PRIMARY_I2S_TX", "PRI_I2S_TX"},
+ {"Voice2 Stub Tx Mixer", "SECONDARY_I2S_TX", "SEC_I2S_TX"},
+ {"Voice2 Stub Tx Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"VOICE2_STUB_UL", NULL, "Voice2 Stub Tx Mixer"},
+
{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"STUB_RX Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"STUB_RX Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"STUB_RX", NULL, "STUB_RX Mixer"},
{"SLIMBUS_1_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"SLIMBUS_1_RX Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"SLIMBUS_1_RX Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Mixer"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"MI2S_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"MI2S_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
{"HDMI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"HDMI_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"HDMI_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"AFE_PCM_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"AFE_PCM_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"SLIMBUS_3_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"SLIMBUS_3_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
+ {"SLIMBUS_3_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX_Voice Mixer"},
{"SLIMBUS_1_RX Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index b571483..c42e155 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -69,8 +69,10 @@
MSM_FRONTEND_DAI_AFE_TX,
MSM_FRONTEND_DAI_VOICE_STUB,
MSM_FRONTEND_DAI_VOLTE,
- MSM_FRONTEND_DAI_SGLTE,
+ MSM_FRONTEND_DAI_VOICE2,
MSM_FRONTEND_DAI_DTMF_RX,
+ MSM_FRONTEND_DAI_VOLTE_STUB,
+ MSM_FRONTEND_DAI_VOICE2_STUB,
MSM_FRONTEND_DAI_MAX,
};
diff --git a/sound/soc/msm/msm-pcm-voice.c b/sound/soc/msm/msm-pcm-voice.c
index ac5bc34..26e6ae6 100644
--- a/sound/soc/msm/msm-pcm-voice.c
+++ b/sound/soc/msm/msm-pcm-voice.c
@@ -59,9 +59,10 @@
return false;
}
-static int is_sglte(struct msm_voice *psglte)
+static int is_voice2(struct msm_voice *pvoice2)
+
{
- if (psglte == &voice_info[SGLTE_SESSION_INDEX])
+ if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
return true;
else
return false;
@@ -100,15 +101,15 @@
if (!strncmp("VoLTE", substream->pcm->id, 5)) {
voice = &voice_info[VOLTE_SESSION_INDEX];
pr_debug("%s: Open VoLTE Substream Id=%s\n",
- __func__, substream->pcm->id);
- } else if (!strncmp("SGLTE", substream->pcm->id, 5)) {
- voice = &voice_info[SGLTE_SESSION_INDEX];
- pr_debug("%s: Open SGLTE Substream Id=%s\n",
- __func__, substream->pcm->id);
+ __func__, substream->pcm->id);
+ } else if (!strncmp("Voice2", substream->pcm->id, 6)) {
+ voice = &voice_info[VOICE2_SESSION_INDEX];
+ pr_debug("%s: Open Voice2 Substream Id=%s\n",
+ __func__, substream->pcm->id);
} else {
voice = &voice_info[VOICE_SESSION_INDEX];
pr_debug("%s: Open VOICE Substream Id=%s\n",
- __func__, substream->pcm->id);
+ __func__, substream->pcm->id);
}
mutex_lock(&voice->lock);
@@ -174,8 +175,8 @@
pr_debug("end voice call\n");
if (is_volte(prtd))
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else if (is_sglte(prtd))
- session_id = voc_get_session_id(SGLTE_SESSION_NAME);
+ else if (is_voice2(prtd))
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
else
session_id = voc_get_session_id(VOICE_SESSION_NAME);
voc_end_voice_call(session_id);
@@ -201,8 +202,8 @@
if (prtd->playback_start && prtd->capture_start) {
if (is_volte(prtd))
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else if (is_sglte(prtd))
- session_id = voc_get_session_id(SGLTE_SESSION_NAME);
+ else if (is_voice2(prtd))
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
else
session_id = voc_get_session_id(VOICE_SESSION_NAME);
voc_start_voice_call(session_id);
@@ -233,8 +234,8 @@
pr_debug("%s: cmd = %d\n", __func__, cmd);
if (is_volte(prtd))
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else if (is_sglte(prtd))
- session_id = voc_get_session_id(SGLTE_SESSION_NAME);
+ else if (is_voice2(prtd))
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
else
session_id = voc_get_session_id(VOICE_SESSION_NAME);
@@ -308,19 +309,20 @@
return 0;
}
-static int msm_sglte_volume_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = 0;
return 0;
}
-static int msm_sglte_volume_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int volume = ucontrol->value.integer.value[0];
pr_debug("%s: volume: %d\n", __func__, volume);
- voc_set_rx_vol_index(voc_get_session_id(SGLTE_SESSION_NAME),
+
+ voc_set_rx_vol_index(voc_get_session_id(VOICE2_SESSION_NAME),
RX_PATH, volume);
return 0;
}
@@ -401,21 +403,21 @@
return 0;
}
-static int msm_sglte_mute_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = 0;
return 0;
}
-static int msm_sglte_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int mute = ucontrol->value.integer.value[0];
pr_debug("%s: mute=%d\n", __func__, mute);
- voc_set_tx_mute(voc_get_session_id(SGLTE_SESSION_NAME), TX_PATH, mute);
+ voc_set_tx_mute(voc_get_session_id(VOICE2_SESSION_NAME), TX_PATH, mute);
return 0;
}
@@ -460,22 +462,22 @@
return 0;
}
-static int msm_sglte_rx_device_mute_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] =
- voc_get_rx_device_mute(voc_get_session_id(SGLTE_SESSION_NAME));
+ voc_get_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME));
return 0;
}
-static int msm_sglte_rx_device_mute_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int msm_voice2_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
int mute = ucontrol->value.integer.value[0];
pr_debug("%s: mute=%d\n", __func__, mute);
- voc_set_rx_device_mute(voc_get_session_id(SGLTE_SESSION_NAME), mute);
+ voc_set_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME), mute);
return 0;
}
@@ -502,7 +504,7 @@
voc_set_tty_mode(voc_get_session_id(VOICE_SESSION_NAME), tty_mode);
- voc_set_tty_mode(voc_get_session_id(SGLTE_SESSION_NAME), tty_mode);
+ voc_set_tty_mode(voc_get_session_id(VOICE2_SESSION_NAME), tty_mode);
return 0;
}
static int msm_voice_widevoice_put(struct snd_kcontrol *kcontrol,
@@ -514,7 +516,7 @@
voc_set_widevoice_enable(voc_get_session_id(VOICE_SESSION_NAME),
wv_enable);
- voc_set_widevoice_enable(voc_get_session_id(SGLTE_SESSION_NAME),
+ voc_set_widevoice_enable(voc_get_session_id(VOICE2_SESSION_NAME),
wv_enable);
return 0;
}
@@ -536,9 +538,9 @@
pr_debug("%s: st enable=%d\n", __func__, st_enable);
voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_ST, st_enable);
- voc_set_pp_enable(voc_get_session_id(SGLTE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_ST, st_enable);
+ MODULE_ID_VOICE_MODULE_ST, st_enable);
+ voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+ MODULE_ID_VOICE_MODULE_ST, st_enable);
return 0;
}
@@ -560,9 +562,9 @@
pr_debug("%s: fens enable=%d\n", __func__, fens_enable);
voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_FENS, fens_enable);
- voc_set_pp_enable(voc_get_session_id(SGLTE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+ MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+ voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+ MODULE_ID_VOICE_MODULE_FENS, fens_enable);
return 0;
}
@@ -605,13 +607,13 @@
SOC_SINGLE_EXT("VoLTE Topology Disable", SND_SOC_NOPM, 0, 1, 0,
msm_volte_topology_disable_get,
msm_volte_topology_disable_put),
- SOC_SINGLE_EXT("SGLTE Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
- msm_sglte_rx_device_mute_get,
- msm_sglte_rx_device_mute_put),
- SOC_SINGLE_EXT("SGLTE Tx Mute", SND_SOC_NOPM, 0, 1, 0,
- msm_sglte_mute_get, msm_sglte_mute_put),
- SOC_SINGLE_EXT("SGLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
- msm_sglte_volume_get, msm_sglte_volume_put),
+ SOC_SINGLE_EXT("Voice2 Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice2_rx_device_mute_get,
+ msm_voice2_rx_device_mute_put),
+ SOC_SINGLE_EXT("Voice2 Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice2_mute_get, msm_voice2_mute_put),
+ SOC_SINGLE_EXT("Voice2 Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+ msm_voice2_volume_get, msm_voice2_volume_put),
};
static struct snd_pcm_ops msm_pcm_ops = {
@@ -674,7 +676,7 @@
memset(&voice_info, 0, sizeof(voice_info));
mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
- mutex_init(&voice_info[SGLTE_SESSION_INDEX].lock);
+ mutex_init(&voice_info[VOICE2_SESSION_INDEX].lock);
return platform_driver_register(&msm_pcm_driver);
}
diff --git a/sound/soc/msm/msm-pcm-voice.h b/sound/soc/msm/msm-pcm-voice.h
index 6eb2060..207e7a7 100644
--- a/sound/soc/msm/msm-pcm-voice.h
+++ b/sound/soc/msm/msm-pcm-voice.h
@@ -16,7 +16,7 @@
enum {
VOICE_SESSION_INDEX,
VOLTE_SESSION_INDEX,
- SGLTE_SESSION_INDEX,
+ VOICE2_SESSION_INDEX,
VOICE_SESSION_INDEX_MAX,
};
diff --git a/sound/soc/msm/msm7kv2-pcm.c b/sound/soc/msm/msm7kv2-pcm.c
index 2b7a438..ed23521 100644
--- a/sound/soc/msm/msm7kv2-pcm.c
+++ b/sound/soc/msm/msm7kv2-pcm.c
@@ -32,7 +32,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <linux/slab.h>
#include "msm7kv2-pcm.h"
#include <mach/qdsp5v2/audio_dev_ctl.h>
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 328e287..b97d9dc 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -86,6 +86,7 @@
static struct mutex cdc_mclk_mutex;
static struct clk *codec_clk;
static int clk_users;
+static int vdd_spkr_gpio = -1;
static int msm_snd_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
bool dapm)
@@ -149,6 +150,30 @@
return 0;
}
+static int msm8226_vdd_spkr_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:
+ if (vdd_spkr_gpio >= 0) {
+ gpio_direction_output(vdd_spkr_gpio, 1);
+ pr_debug("%s: Enabled 5V external supply for speaker\n",
+ __func__);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (vdd_spkr_gpio >= 0) {
+ gpio_direction_output(vdd_spkr_gpio, 0);
+ pr_debug("%s: Disabled 5V external supply for speaker\n",
+ __func__);
+ }
+ break;
+ }
+ return 0;
+}
+
static const struct snd_soc_dapm_widget msm8226_dapm_widgets[] = {
SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0,
@@ -165,6 +190,9 @@
SND_SOC_DAPM_MIC("Digital Mic4", NULL),
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+
+ SND_SOC_DAPM_SUPPLY("EXT_VDD_SPKR", SND_SOC_NOPM, 0, 0,
+ msm8226_vdd_spkr_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
};
static const char *const slim0_rx_ch_text[] = {"One", "Two"};
@@ -744,20 +772,19 @@
.codec_name = "snd-soc-dummy",
},
{
- .name = "VoLTE",
- .stream_name = "VoLTE",
- .cpu_dai_name = "VoLTE",
+ .name = "Voice2",
+ .stream_name = "Voice2",
+ .cpu_dai_name = "Voice2",
.platform_name = "msm-pcm-voice",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOLTE,
},
{
.name = "MSM8226 LowLatency",
@@ -1104,19 +1131,44 @@
goto err;
}
+ vdd_spkr_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,cdc-vdd-spkr-gpios", 0);
+ if (vdd_spkr_gpio < 0) {
+ dev_err(&pdev->dev,
+ "Looking up %s property in node %s failed %d\n",
+ "qcom, cdc-vdd-spkr-gpios",
+ pdev->dev.of_node->full_name, vdd_spkr_gpio);
+ } else {
+ ret = gpio_request(vdd_spkr_gpio, "TAPAN_CODEC_VDD_SPKR");
+ if (ret) {
+ /* GPIO to enable EXT VDD exists, but failed request */
+ dev_err(card->dev,
+ "%s: Failed to request tapan vdd spkr gpio %d\n",
+ __func__, vdd_spkr_gpio);
+ goto err;
+ }
+ }
+
ret = msm8226_prepare_codec_mclk(card);
if (ret)
- goto err;
+ goto err_vdd_spkr;
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- goto err;
+ goto err_vdd_spkr;
}
mutex_init(&cdc_mclk_mutex);
return 0;
+
+err_vdd_spkr:
+ if (vdd_spkr_gpio >= 0) {
+ gpio_free(vdd_spkr_gpio);
+ vdd_spkr_gpio = -1;
+ }
+
err:
if (pdata->mclk_gpio > 0) {
dev_dbg(&pdev->dev, "%s free gpio %d\n",
@@ -1134,6 +1186,8 @@
struct msm8226_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
gpio_free(pdata->mclk_gpio);
+ gpio_free(vdd_spkr_gpio);
+ vdd_spkr_gpio = -1;
snd_soc_unregister_card(card);
return 0;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index ae9468f..2bd5c88 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -1105,9 +1105,9 @@
.be_id = MSM_FRONTEND_DAI_VOLTE,
},
{
- .name = "SGLTE",
- .stream_name = "SGLTE",
- .cpu_dai_name = "SGLTE",
+ .name = "Voice2",
+ .stream_name = "Voice2",
+ .cpu_dai_name = "Voice2",
.platform_name = "msm-pcm-voice",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
@@ -1118,7 +1118,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_SGLTE,
+ .be_id = MSM_FRONTEND_DAI_VOICE2,
},
{
.name = "MSM8960 LowLatency",
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index f987eb4..8c0d1a9 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1361,9 +1361,9 @@
.be_id = MSM_FRONTEND_DAI_VOLTE,
},
{
- .name = "SGLTE",
- .stream_name = "SGLTE",
- .cpu_dai_name = "SGLTE",
+ .name = "Voice2",
+ .stream_name = "Voice2",
+ .cpu_dai_name = "Voice2",
.platform_name = "msm-pcm-voice",
.dynamic = 1,
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
@@ -1373,7 +1373,7 @@
.ignore_pmdown_time = 1,/* this dainlink has playback support */
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_SGLTE,
+ .be_id = MSM_FRONTEND_DAI_VOICE2,
},
{
.name = "MSM8960 LowLatency",
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 0dbe3f7..30e9629 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -44,6 +44,7 @@
#define BTSCO_RATE_16KHZ 16000
static int slim0_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
+static int hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
#define SAMPLING_RATE_48KHZ 48000
#define SAMPLING_RATE_96KHZ 96000
@@ -733,6 +734,46 @@
return 0;
}
+static int hdmi_rx_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ switch (hdmi_rx_bit_format) {
+ case SNDRV_PCM_FORMAT_S24_LE:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+
+ pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
+ __func__, hdmi_rx_bit_format,
+ ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static int hdmi_rx_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 0:
+ default:
+ hdmi_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ pr_debug("%s: hdmi_rx_bit_format = %d, ucontrol value = %ld\n",
+ __func__, hdmi_rx_bit_format,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
static int msm_hdmi_rx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -840,6 +881,8 @@
pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
channels->min, channels->max);
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ hdmi_rx_bit_format);
if (channels->max < 2)
channels->min = channels->max = 2;
rate->min = rate->max = 48000;
@@ -1067,6 +1110,8 @@
slim0_rx_bit_format_get, slim0_rx_bit_format_put),
SOC_ENUM_EXT("SLIM_0_RX SampleRate", msm_snd_enum[5],
slim0_rx_sample_rate_get, slim0_rx_sample_rate_put),
+ SOC_ENUM_EXT("HDMI_RX Bit Format", msm_snd_enum[4],
+ hdmi_rx_bit_format_get, hdmi_rx_bit_format_put),
};
static bool msm8974_swap_gnd_mic(struct snd_soc_codec *codec)
@@ -1154,6 +1199,14 @@
return err;
}
+ config_data = taiko_get_afe_config(codec, AFE_AANC_VERSION);
+ err = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (err) {
+ pr_err("%s: Failed to set aanc version %d\n",
+ __func__, err);
+ return err;
+ }
+
/* start mbhc */
mbhc_cfg.calibration = def_taiko_mbhc_cal();
if (mbhc_cfg.calibration)
@@ -2104,8 +2157,7 @@
sizeof(struct msm8974_asoc_mach_data), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "Can't allocate msm8974_asoc_mach_data\n");
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
ret = msm8974_dtparse_auxpcm(pdev, &pdata);
diff --git a/sound/soc/msm/msm8x60-pcm.c b/sound/soc/msm/msm8x60-pcm.c
index 7993435..f8b43cf 100644
--- a/sound/soc/msm/msm8x60-pcm.c
+++ b/sound/soc/msm/msm8x60-pcm.c
@@ -27,7 +27,7 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/android_pmem.h>
+
#include <mach/qdsp6v2/audio_dev_ctl.h>
#include "msm8x60-pcm.h"
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index a55700c..f15f4d1 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -25,7 +25,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
+
#include <linux/memory_alloc.h>
#include <linux/debugfs.h>
#include <linux/time.h>
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index f04947c..17f2d03 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -31,11 +31,6 @@
#define CMD_STATUS_SUCCESS 0
#define CMD_STATUS_FAIL 1
-#define VOC_PATH_PASSIVE 0
-#define VOC_PATH_FULL 1
-#define VOC_PATH_VOLTE_PASSIVE 2
-#define VOC_PATH_SGLTE_PASSIVE 3
-
#define CAL_BUFFER_SIZE 4096
#define NUM_CVP_CAL_BLOCKS 75
#define NUM_CVS_CAL_BLOCKS 15
@@ -173,9 +168,9 @@
else if (!strncmp(name, "VoLTE session", 13))
session_id =
common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
- else if (!strncmp(name, "SGLTE session", 13))
+ else if (!strncmp(name, "Voice2 session", 14))
session_id =
- common.voice[VOC_PATH_SGLTE_PASSIVE].session_id;
+ common.voice[VOC_PATH_VOICE2_PASSIVE].session_id;
else
session_id = common.voice[VOC_PATH_FULL].session_id;
@@ -216,9 +211,9 @@
return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
}
-static bool is_sglte_session(u16 session_id)
+static bool is_voice2_session(u16 session_id)
{
- return (session_id == common.voice[VOC_PATH_SGLTE_PASSIVE].session_id);
+ return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
}
/* Only for memory allocated in the voice driver */
@@ -373,9 +368,9 @@
pr_err("%s: apr_mvm is NULL.\n", __func__);
return -EINVAL;
}
- pr_debug("%s: VoLTE/SGLTE command to MVM\n", __func__);
+ pr_debug("%s: VoLTE/Voice2 command to MVM\n", __func__);
if (is_volte_session(v->session_id) ||
- is_sglte_session(v->session_id)) {
+ is_voice2_session(v->session_id)) {
mvm_handle = voice_get_mvm_handle(v);
mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
@@ -451,7 +446,7 @@
if (!mvm_handle) {
if (is_voice_session(v->session_id) ||
is_volte_session(v->session_id) ||
- is_sglte_session(v->session_id)) {
+ is_voice2_session(v->session_id)) {
mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -471,7 +466,7 @@
strlcpy(mvm_session_cmd.mvm_session.name,
"default volte voice",
sizeof(mvm_session_cmd.mvm_session.name) - 1);
- } else if (is_sglte_session(v->session_id)) {
+ } else if (is_voice2_session(v->session_id)) {
strlcpy(mvm_session_cmd.mvm_session.name,
"default modem voice2",
sizeof(mvm_session_cmd.mvm_session.name));
@@ -538,7 +533,7 @@
if (!cvs_handle) {
if (is_voice_session(v->session_id) ||
is_volte_session(v->session_id) ||
- is_sglte_session(v->session_id)) {
+ is_voice2_session(v->session_id)) {
pr_debug("%s: creating CVS passive session\n",
__func__);
@@ -559,7 +554,7 @@
strlcpy(cvs_session_cmd.cvs_session.name,
"default volte voice",
sizeof(cvs_session_cmd.cvs_session.name) - 1);
- } else if (is_sglte_session(v->session_id)) {
+ } else if (is_voice2_session(v->session_id)) {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice2",
sizeof(cvs_session_cmd.cvs_session.name));
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 8df6c38..0bae384 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -1314,12 +1314,12 @@
#define VOICE_SESSION_NAME "Voice session"
#define VOIP_SESSION_NAME "VoIP session"
#define VOLTE_SESSION_NAME "VoLTE session"
-#define SGLTE_SESSION_NAME "SGLTE session"
+#define VOICE2_SESSION_NAME "Voice2 session"
#define VOC_PATH_PASSIVE 0
#define VOC_PATH_FULL 1
#define VOC_PATH_VOLTE_PASSIVE 2
-#define VOC_PATH_SGLTE_PASSIVE 3
+#define VOC_PATH_VOICE2_PASSIVE 3
uint16_t voc_get_session_id(char *name);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index f6e571b8..5dc5f96 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -29,7 +29,7 @@
#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <sound/timer.h>
#include "msm-compr-q6-v2.h"
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 329d293..16df886 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -23,6 +23,7 @@
#include <sound/apr_audio-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/msm-dai-q6-v2.h>
+#include <sound/pcm_params.h>
#define HDMI_RX_CA_MAX 0x32
@@ -119,7 +120,14 @@
dai_data->port_config.hdmi_multi_ch.reserved = 0;
dai_data->port_config.hdmi_multi_ch.hdmi_cfg_minor_version = 1;
dai_data->port_config.hdmi_multi_ch.sample_rate = dai_data->rate;
- dai_data->port_config.hdmi_multi_ch.bit_width = 16;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ dai_data->port_config.hdmi_multi_ch.bit_width = 16;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ dai_data->port_config.hdmi_multi_ch.bit_width = 24;
+ break;
+ }
switch (dai_data->channels) {
case 2:
@@ -257,7 +265,7 @@
static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
.channels_min = 2,
.channels_max = 8,
.rate_max = 48000,
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 916be0b..5b18311 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -485,7 +485,7 @@
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FMTBIT_SPECIAL:
+ case SNDRV_PCM_FORMAT_SPECIAL:
dai_data->port_config.i2s.bit_width = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
@@ -561,7 +561,7 @@
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FMTBIT_SPECIAL:
+ case SNDRV_PCM_FORMAT_SPECIAL:
dai_data->port_config.slim_sch.bit_width = 16;
break;
case SNDRV_PCM_FORMAT_S24_LE:
@@ -1351,7 +1351,7 @@
ctrl = &mi2s_config_controls[3];
}
- if (!ctrl) {
+ if (ctrl) {
kcontrol = snd_ctl_new1(ctrl,
&mi2s_dai_data->rx_dai.mi2s_dai_data);
rc = snd_ctl_add(dai->card->snd_card, kcontrol);
@@ -1371,7 +1371,7 @@
ctrl = &mi2s_config_controls[4];
}
- if (!ctrl) {
+ if (ctrl) {
rc = snd_ctl_add(dai->card->snd_card,
snd_ctl_new1(ctrl,
&mi2s_dai_data->tx_dai.mi2s_dai_data));
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index ea6f390..363fb15 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -18,7 +18,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
#include <linux/of.h>
#include <sound/core.h>
#include <sound/soc.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
index d0d573c..a078042 100644
--- a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/soc.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 91bb09b..e4f3f94 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <sound/core.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 3a4a674..64f19ad 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -26,7 +26,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <linux/of_device.h>
#include <sound/compress_params.h>
#include <sound/compress_offload.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 4ca96d7..ca91fe5 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -27,7 +27,7 @@
#include <sound/control.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
-#include <linux/android_pmem.h>
+
#include <linux/of_device.h>
#include <sound/pcm_params.h>
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 594d753..d8f2759 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -566,6 +566,8 @@
session_id = voc_get_session_id(VOICE_SESSION_NAME);
else if (val == MSM_FRONTEND_DAI_VOLTE)
session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+ else if (val == MSM_FRONTEND_DAI_VOICE2)
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
else
session_id = voc_get_session_id(VOIP_SESSION_NAME);
@@ -1587,6 +1589,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1602,6 +1607,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1617,6 +1625,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1632,6 +1643,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1650,6 +1664,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1668,6 +1685,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1686,6 +1706,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AUXPCM_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1704,6 +1727,9 @@
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice2", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1757,6 +1783,27 @@
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
+ SOC_SINGLE_EXT("PRI_TX_Voice2", MSM_BACKEND_DAI_PRI_I2S_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("MI2S_TX_Voice2", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SLIM_0_TX_Voice2", MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice2",
+ MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_VOICE2, 1, 0,
+ msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX_Voice2", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("AUX_PCM_TX_Voice2", MSM_BACKEND_DAI_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOICE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new tx_volte_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_TX_VoLTE", MSM_BACKEND_DAI_PRI_I2S_TX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
@@ -2287,6 +2334,8 @@
SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("VOICE2_DL", "Voice2 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("VOICE2_UL", "Voice2 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VoLTE_DL", "VoLTE Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VoLTE_UL", "VoLTE Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
@@ -2473,6 +2522,9 @@
SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
ARRAY_SIZE(tx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("Voice2_Tx Mixer",
+ SND_SOC_NOPM, 0, 0, tx_voice2_mixer_controls,
+ ARRAY_SIZE(tx_voice2_mixer_controls)),
SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
ARRAY_SIZE(tx_voip_mixer_controls)),
@@ -2649,48 +2701,56 @@
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
{"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"PRI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"PRI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"PRI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
{"SEC_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SEC_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"SEC_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SEC_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SEC_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SEC_I2S_RX", NULL, "SEC_RX_Voice Mixer"},
{"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SLIM_0_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"SLIM_0_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"SLIM_0_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"AFE_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"AFE_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AFE_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
{"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"AUX_PCM_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"HDMI_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
@@ -2698,6 +2758,7 @@
{"HDMI", NULL, "HDMI_DL_HL"},
{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"MI2S_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -2710,6 +2771,15 @@
{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
+
+ {"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
+ {"Voice2_Tx Mixer", "MI2S_TX_Voice2", "MI2S_TX"},
+ {"Voice2_Tx Mixer", "SLIM_0_TX_Voice2", "SLIMBUS_0_TX"},
+ {"Voice2_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice2", "INT_BT_SCO_TX"},
+ {"Voice2_Tx Mixer", "AFE_PCM_TX_Voice2", "PCM_TX"},
+ {"Voice2_Tx Mixer", "AUX_PCM_TX_Voice2", "AUX_PCM_TX"},
+ {"VOICE2_UL", NULL, "Voice2_Tx Mixer"},
+
{"VoLTE_Tx Mixer", "PRI_TX_VoLTE", "PRI_I2S_TX"},
{"VoLTE_Tx Mixer", "SLIM_0_TX_VoLTE", "SLIMBUS_0_TX"},
{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 798f676..1c1029c 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -73,6 +73,7 @@
MSM_FRONTEND_DAI_VOLTE,
MSM_FRONTEND_DAI_DTMF_RX,
MSM_FRONTEND_DAI_LSM1,
+ MSM_FRONTEND_DAI_VOICE2,
MSM_FRONTEND_DAI_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 333ee48..4df66d0 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -59,6 +59,29 @@
return false;
}
+static int is_voice2(struct msm_voice *pvoice2)
+{
+ if (pvoice2 == &voice_info[VOICE2_SESSION_INDEX])
+ return true;
+ else
+ return false;
+}
+
+static uint16_t get_session_id(struct msm_voice *pvoc)
+{
+ uint16_t session_id = 0;
+
+ if (is_volte(pvoc))
+ session_id = voc_get_session_id(VOLTE_SESSION_NAME);
+ else if (is_voice2(pvoc))
+ session_id = voc_get_session_id(VOICE2_SESSION_NAME);
+ else
+ session_id = voc_get_session_id(VOICE_SESSION_NAME);
+
+ return session_id;
+}
+
+
static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -92,11 +115,15 @@
if (!strncmp("VoLTE", substream->pcm->id, 5)) {
voice = &voice_info[VOLTE_SESSION_INDEX];
pr_debug("%s: Open VoLTE Substream Id=%s\n",
- __func__, substream->pcm->id);
+ __func__, substream->pcm->id);
+ } else if (!strncmp("Voice2", substream->pcm->id, 6)) {
+ voice = &voice_info[VOICE2_SESSION_INDEX];
+ pr_debug("%s: Open Voice2 Substream Id=%s\n",
+ __func__, substream->pcm->id);
} else {
voice = &voice_info[VOICE_SESSION_INDEX];
pr_debug("%s: Open VOICE Substream Id=%s\n",
- __func__, substream->pcm->id);
+ __func__, substream->pcm->id);
}
mutex_lock(&voice->lock);
@@ -160,11 +187,10 @@
prtd->instance--;
if (!prtd->playback_start && !prtd->capture_start) {
pr_debug("end voice call\n");
- if (is_volte(prtd))
- session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else
- session_id = voc_get_session_id(VOICE_SESSION_NAME);
- voc_end_voice_call(session_id);
+
+ session_id = get_session_id(prtd);
+ if (session_id)
+ voc_end_voice_call(session_id);
}
mutex_unlock(&prtd->lock);
@@ -185,11 +211,9 @@
ret = msm_pcm_capture_prepare(substream);
if (prtd->playback_start && prtd->capture_start) {
- if (is_volte(prtd))
- session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else
- session_id = voc_get_session_id(VOICE_SESSION_NAME);
- voc_start_voice_call(session_id);
+ session_id = get_session_id(prtd);
+ if (session_id)
+ voc_start_voice_call(session_id);
}
mutex_unlock(&prtd->lock);
@@ -215,10 +239,8 @@
uint16_t session_id = 0;
pr_debug("%s: cmd = %d\n", __func__, cmd);
- if (is_volte(prtd))
- session_id = voc_get_session_id(VOLTE_SESSION_NAME);
- else
- session_id = voc_get_session_id(VOICE_SESSION_NAME);
+
+ session_id = get_session_id(prtd);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -233,8 +255,10 @@
ret = msm_pcm_playback_prepare(substream);
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
ret = msm_pcm_capture_prepare(substream);
- if (prtd->playback_start && prtd->capture_start)
- voc_resume_voice_call(session_id);
+ if (prtd->playback_start && prtd->capture_start) {
+ if (session_id)
+ voc_resume_voice_call(session_id);
+ }
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -247,7 +271,8 @@
if (prtd->capture_start)
prtd->capture_start = 0;
}
- voc_standby_voice_call(session_id);
+ if (session_id)
+ voc_standby_voice_call(session_id);
break;
default:
ret = -EINVAL;
@@ -290,6 +315,24 @@
return 0;
}
+static int msm_voice2_volume_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
+}
+
+static int msm_voice2_volume_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int volume = ucontrol->value.integer.value[0];
+ pr_debug("%s: volume: %d\n", __func__, volume);
+
+ voc_set_rx_vol_index(voc_get_session_id(VOICE2_SESSION_NAME),
+ RX_PATH, volume);
+ return 0;
+}
+
static int msm_voice_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -328,6 +371,25 @@
return 0;
}
+static int msm_voice2_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+ return 0;
+}
+
+static int msm_voice2_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_tx_mute(voc_get_session_id(VOICE2_SESSION_NAME), TX_PATH, mute);
+
+ return 0;
+}
+
static int msm_voice_rx_device_mute_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -368,6 +430,26 @@
return 0;
}
+static int msm_voice2_rx_device_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ voc_get_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME));
+ return 0;
+}
+
+static int msm_voice2_rx_device_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int mute = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: mute=%d\n", __func__, mute);
+
+ voc_set_rx_device_mute(voc_get_session_id(VOICE2_SESSION_NAME), mute);
+
+ return 0;
+}
+
static const char const *tty_mode[] = {"OFF", "HCO", "VCO", "FULL"};
static const struct soc_enum msm_tty_mode_enum[] = {
SOC_ENUM_SINGLE_EXT(4, tty_mode),
@@ -389,6 +471,7 @@
pr_debug("%s: tty_mode=%d\n", __func__, tty_mode);
voc_set_tty_mode(voc_get_session_id(VOICE_SESSION_NAME), tty_mode);
+ voc_set_tty_mode(voc_get_session_id(VOICE2_SESSION_NAME), tty_mode);
return 0;
}
@@ -401,6 +484,8 @@
voc_set_widevoice_enable(voc_get_session_id(VOICE_SESSION_NAME),
wv_enable);
+ voc_set_widevoice_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+ wv_enable);
return 0;
}
@@ -422,7 +507,9 @@
pr_debug("%s: st enable=%d\n", __func__, st_enable);
voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_ST, st_enable);
+ MODULE_ID_VOICE_MODULE_ST, st_enable);
+ voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+ MODULE_ID_VOICE_MODULE_ST, st_enable);
return 0;
}
@@ -444,7 +531,9 @@
pr_debug("%s: fens enable=%d\n", __func__, fens_enable);
voc_set_pp_enable(voc_get_session_id(VOICE_SESSION_NAME),
- MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+ MODULE_ID_VOICE_MODULE_FENS, fens_enable);
+ voc_set_pp_enable(voc_get_session_id(VOICE2_SESSION_NAME),
+ MODULE_ID_VOICE_MODULE_FENS, fens_enable);
return 0;
}
@@ -481,6 +570,13 @@
msm_volte_mute_get, msm_volte_mute_put),
SOC_SINGLE_EXT("VoLTE Rx Volume", SND_SOC_NOPM, 0, 5, 0,
msm_volte_volume_get, msm_volte_volume_put),
+ SOC_SINGLE_EXT("Voice2 Rx Device Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice2_rx_device_mute_get,
+ msm_voice2_rx_device_mute_put),
+ SOC_SINGLE_EXT("Voice2 Tx Mute", SND_SOC_NOPM, 0, 1, 0,
+ msm_voice2_mute_get, msm_voice2_mute_put),
+ SOC_SINGLE_EXT("Voice2 Rx Volume", SND_SOC_NOPM, 0, 5, 0,
+ msm_voice2_volume_get, msm_voice2_volume_put),
};
static struct snd_pcm_ops msm_pcm_ops = {
@@ -550,9 +646,12 @@
static int __init msm_soc_platform_init(void)
{
+ int i = 0;
+
memset(&voice_info, 0, sizeof(voice_info));
- mutex_init(&voice_info[VOICE_SESSION_INDEX].lock);
- mutex_init(&voice_info[VOLTE_SESSION_INDEX].lock);
+
+ for (i = 0; i < VOICE_SESSION_INDEX_MAX; i++)
+ mutex_init(&voice_info[i].lock);
return platform_driver_register(&msm_pcm_driver);
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
index a25fb2a..5425c46 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.h
@@ -16,6 +16,7 @@
enum {
VOICE_SESSION_INDEX,
VOLTE_SESSION_INDEX,
+ VOICE2_SESSION_INDEX,
VOICE_SESSION_INDEX_MAX,
};
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b32daaa..b1db277 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -992,6 +992,8 @@
if (tmp >= 0 && tmp < AFE_MAX_PORTS)
copps_list[i] =
atomic_read(&this_adm.copp_id[tmp]);
+ else
+ continue;
pr_debug("%s: port_id[%#x]: %d, index: %d act coppid[0x%x]\n",
__func__, i, port_id[i], tmp,
atomic_read(&this_adm.copp_id[tmp]));
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 7bb5401..3b1727c 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -425,6 +425,7 @@
int index = 0;
struct afe_spkr_prot_config_command config;
+ memset(&config, 0 , sizeof(config));
if (!prot_config) {
pr_err("%s Invalid params\n", __func__);
goto fail_cmd;
@@ -433,7 +434,6 @@
pr_err("%s invalid port %d", __func__, port);
goto fail_cmd;
}
- memset(&config, 0 , sizeof(config));
index = q6audio_get_port_index(port);
switch (param_id) {
case AFE_PARAM_ID_FBSP_MODE_RX_CFG:
@@ -486,7 +486,7 @@
}
ret = 0;
fail_cmd:
- pr_err("%s config.pdata.param_id %x status %d\n",
+ pr_debug("%s config.pdata.param_id %x status %d\n",
__func__, config.pdata.param_id, ret);
return ret;
}
@@ -926,7 +926,7 @@
int i;
i = port_id - SLIMBUS_0_RX;
- if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
+ if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
pr_err("%s: Invalid port_id 0x%x\n", __func__, port_id);
return -EINVAL;
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0549671..ea2b5c6 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -24,7 +24,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>
-#include <linux/android_pmem.h>
+
#include <linux/memory_alloc.h>
#include <linux/debugfs.h>
#include <linux/time.h>
@@ -1651,6 +1651,9 @@
case FORMAT_AMRWB:
open.dec_fmt_id = ASM_MEDIA_FMT_AMRWB_FS;
break;
+ case FORMAT_AMR_WB_PLUS:
+ open.dec_fmt_id = ASM_MEDIA_FMT_AMR_WB_PLUS_V2;
+ break;
case FORMAT_V13K:
open.dec_fmt_id = ASM_MEDIA_FMT_V13K_FS;
break;
@@ -2532,6 +2535,42 @@
return -EINVAL;
}
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg)
+{
+ struct asm_amrwbplus_fmt_blk_v2 fmt;
+ int rc = 0;
+
+ pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
+ __func__,
+ ac->session,
+ cfg->amr_band_mode,
+ cfg->amr_frame_fmt,
+ cfg->num_channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2;
+ fmt.fmtblk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
+ sizeof(fmt.fmtblk);
+ fmt.amr_frame_fmt = cfg->amr_frame_fmt;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd media format update failed..\n", __func__);
+ 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 FORMAT_UPDATE\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
uint32_t bufsz, uint32_t bufcnt)
{
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 12e83b0..754a4fa 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -35,10 +35,6 @@
#define CMD_STATUS_SUCCESS 0
#define CMD_STATUS_FAIL 1
-#define VOC_PATH_PASSIVE 0
-#define VOC_PATH_FULL 1
-#define VOC_PATH_VOLTE_PASSIVE 2
-
/* CVP CAL Size: 245760 = 240 * 1024 */
#define CVP_CAL_SIZE 245760
/* CVS CAL Size: 49152 = 48 * 1024 */
@@ -180,6 +176,9 @@
if (name != NULL) {
if (!strncmp(name, "Voice session", 13))
session_id = common.voice[VOC_PATH_PASSIVE].session_id;
+ else if (!strncmp(name, "Voice2 session", 14))
+ session_id =
+ common.voice[VOC_PATH_VOICE2_PASSIVE].session_id;
else if (!strncmp(name, "VoLTE session", 13))
session_id =
common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
@@ -223,6 +222,11 @@
return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
}
+static bool is_voice2_session(u16 session_id)
+{
+ return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
+}
+
static int voice_apr_register(void)
{
void *modem_mvm, *modem_cvs, *modem_cvp;
@@ -347,7 +351,8 @@
}
pr_debug("%s: VoLTE command to MVM\n", __func__);
if (is_volte_session(v->session_id) ||
- is_voice_session(v->session_id)) {
+ is_voice_session(v->session_id) ||
+ is_voice2_session(v->session_id)) {
mvm_handle = voice_get_mvm_handle(v);
mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
@@ -421,7 +426,8 @@
if (!mvm_handle) {
if (is_voice_session(v->session_id) ||
- is_volte_session(v->session_id)) {
+ is_volte_session(v->session_id) ||
+ is_voice2_session(v->session_id)) {
mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE),
@@ -441,8 +447,12 @@
strlcpy(mvm_session_cmd.mvm_session.name,
"default volte voice",
sizeof(mvm_session_cmd.mvm_session.name));
+ } else if (is_voice2_session(v->session_id)) {
+ strlcpy(mvm_session_cmd.mvm_session.name,
+ VOICE2_SESSION_VSID,
+ sizeof(mvm_session_cmd.mvm_session.name));
} else {
- strlcpy(mvm_session_cmd.mvm_session.name,
+ strlcpy(mvm_session_cmd.mvm_session.name,
"default modem voice",
sizeof(mvm_session_cmd.mvm_session.name));
}
@@ -503,7 +513,8 @@
/* send cmd to create cvs session */
if (!cvs_handle) {
if (is_voice_session(v->session_id) ||
- is_volte_session(v->session_id)) {
+ is_volte_session(v->session_id) ||
+ is_voice2_session(v->session_id)) {
pr_debug("%s: creating CVS passive session\n",
__func__);
@@ -524,6 +535,10 @@
strlcpy(cvs_session_cmd.cvs_session.name,
"default volte voice",
sizeof(cvs_session_cmd.cvs_session.name));
+ } else if (is_voice2_session(v->session_id)) {
+ strlcpy(cvs_session_cmd.cvs_session.name,
+ VOICE2_SESSION_VSID,
+ sizeof(cvs_session_cmd.cvs_session.name));
} else {
strlcpy(cvs_session_cmd.cvs_session.name,
"default modem voice",
@@ -4167,6 +4182,7 @@
case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
case VSS_IMVM_CMD_SET_CAL_NETWORK:
case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
+ case VSS_IMEMORY_CMD_MAP_PHYSICAL:
case VSS_IMEMORY_CMD_UNMAP:
case VSS_IMVM_CMD_STANDBY_VOICE:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 98bd002..babfddc 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1275,7 +1275,7 @@
void *buf;
};
-#define MAX_VOC_SESSIONS 3
+#define MAX_VOC_SESSIONS 4
#define SESSION_ID_BASE 0xFFF0
struct common_data {
@@ -1327,6 +1327,20 @@
TX_PATH,
};
+
+#define VOC_PATH_PASSIVE 0
+#define VOC_PATH_FULL 1
+#define VOC_PATH_VOLTE_PASSIVE 2
+#define VOC_PATH_VOICE2_PASSIVE 3
+
+#define MAX_SESSION_NAME_LEN 32
+#define VOICE_SESSION_NAME "Voice session"
+#define VOIP_SESSION_NAME "VoIP session"
+#define VOLTE_SESSION_NAME "VoLTE session"
+#define VOICE2_SESSION_NAME "Voice2 session"
+
+#define VOICE2_SESSION_VSID "10dc1000"
+
/* called by alsa driver */
int voc_set_pp_enable(uint16_t session_id, uint32_t module_id,
uint32_t enable);
@@ -1353,10 +1367,6 @@
int voc_enable_dtmf_rx_detection(uint16_t session_id, uint32_t enable);
void voc_disable_dtmf_det_on_active_sessions(void);
-#define MAX_SESSION_NAME_LEN 32
-#define VOICE_SESSION_NAME "Voice session"
-#define VOIP_SESSION_NAME "VoIP session"
-#define VOLTE_SESSION_NAME "VoLTE session"
uint16_t voc_get_session_id(char *name);
int voc_start_playback(uint32_t set);