Merge "usb: msm_otg: Allow support to use 2nd HSPHY with USB2 Core"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index 4d441ba..6b2f962 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -87,6 +87,10 @@
(In Bytes).
qcom,prio-rd: Read priority for a BIMC bus master (Can be 0/1/2)
qcom,prio-wr: Write priority for a BIMC bus master (Can be 0/1/2)
+qcom,prio0: Priority low signal for a NoC bus master
+ (Can be 0/1/2).
+qcom,prio1: Priority high signal for a NoC bus master
+ (Can be 0/1/2)
Example:
@@ -149,7 +153,7 @@
- qcom,msm-bus,name: String representing the client-name
- qcom,msm-bus,num-cases: Total number of usecases
-- qcom,msm-bus,active-only: Context flag for requests in active or
+- qcom,msm-bus,active-only: Boolean context flag for requests in active or
dual (active & sleep) contex
- qcom,msm-bus,num-paths: Total number of master-slave pairs
- qcom,msm-bus,vectors-KBps: Arrays of unsigned integers representing:
@@ -160,7 +164,7 @@
qcom,msm-bus,name = "client-name";
qcom,msm-bus,num-cases = <3>;
- qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,active-only;
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors =
<22 512 0 0>, <26 512 0 0>,
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
index 5d1fafb..31600ca 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -19,9 +19,55 @@
Typically the sensor closest to CPU0.
- qcom,poll-ms: Sampling interval to read sensor, in ms.
- qcom,limit-temp: Threshold temperature to start stepping CPU down, in degC.
-- qcom,temp-hysteresis: Degrees below threshold temperature to step CPU up.
+- qcom,temp-hysteresis: Degrees C below threshold temperature to step CPU up.
- qcom,freq-step: Number of frequency steps to take on each CPU mitigation.
+Optional properties
+
+- qcom,core-limit-temp: Threshold temperature to start shutting down cores
+ in degC
+- qcom,core-temp-hysterisis: Degrees C below which the cores will be brought
+ online in sequence.
+- qcom,core-control-mask: The cpu mask that will be used to determine if a
+ core can be controlled or not. A mask of 0 indicates
+ the feature is disabled.
+- qcom,vdd-restriction-temp: When temperature is below this threshold, will
+ enable vdd restriction which will set higher voltage on
+ key voltage rails, in degC.
+- qcom,vdd-restriction-temp-hysteresis: When temperature is above this threshold
+ will disable vdd restriction on key rails, in degC.
+- qcom,pmic-sw-mode-temp: Threshold temperature to disable auto mode on the
+ rail, in degC. If this property exists,
+ qcom,pmic-sw-mode-temp-hysteresis and
+ qcom,pmic-sw-mode-regs need to exist, otherwise return error.
+- qcom,pmic-sw-mode-temp-hysteresis: Degree below threshold temperature to
+ enable auto mode on the rail, in degC. If this property exists,
+ qcom,pmic-sw-mode-temp and qcom,pmic-sw-mode-regs need to
+ exist, otherwise return error.
+- qcom,pmic-sw-mode-regs: Array of the regulator names that will want to
+ disable/enable automode based on the threshold. If this
+ property exists, qcom,pmic-sw-mode-temp and
+ qcom,pmic-sw-mode-temp-hysteresis need to exist, otherwise
+ return error. Also, if this property is defined, will have to
+ define <consumer_supply_name>-supply = <&phandle_of_regulator>
+- <consumer_supply_name>-supply = <&phandle_of_regulator>: consumer_supply_name
+ is the name that's defined in thermal driver.
+ phandle_of_regulator is defined by reuglator device tree.
+
+Optional child nodes
+- qcom,<vdd restriction child node name>: Define the name of the child node.
+ If this property exisits, qcom,vdd-rstr-reg, qcom,levels,
+ qcom,min-level and qcom,freq-req need to exist, otherwise
+ we return an error.
+- qcom,vdd-rstr-reg: Name of the rail
+- qcom,levels: Array of the level values. Unit is corner voltage for voltage request
+ or kHz for frequency request.
+- qcom,min-level: Request this level as minimum level when disabling voltage
+ restriction. Unit is corner voltage for voltage request
+ or kHz for frequency request.
+- qcom,freq-req: Flag to determine if we should restrict frequency on this rail
+ instead of voltage.
+
Example:
qcom,msm-thermal {
@@ -31,4 +77,20 @@
qcom,limit-temp = <60>;
qcom,temp-hysteresis = <10>;
qcom,freq-step = <2>;
+ qcom,core-limit-temp = <90>;
+ qcom,core-temp-hysterisis = <10>;
+ qcom,core-control-mask = <7>;
+ qcom,pmic-sw-mode-temp = <90>;
+ qcom,pmic-sw-mode-temp-hysteresis = <80>;
+ qcom,pmic-sw-mode-regs = "vdd_dig";
+ qcom,vdd-restriction-temp = <5>;
+ qcom,vdd-restriction-temp-hysteresis = <10>;
+ vdd_dig-supply=<&pm8841_s2_floor_corner>
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
};
+
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
index b9a71f6..7eb65d2 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -9,7 +9,7 @@
- qcom,ce-hw-instance : should contain crypto HW instance.
- qcom,msm_bus,name: Should be "qcedev-noc"
- qcom,msm_bus,num_cases: Depends on the use cases for bus scaling
- - qcom,msm_bus,active-only: Default vector index
+ - qcom,msm_bus,active-only: Boolean flag for context of request (actve/dual)
- qcom,msm_bus,num_paths: The paths for source and destination ports
- qcom,msm_bus,vectors: Vectors for bus topology.
@@ -31,7 +31,6 @@
qcom,ce-hw-shared;
qcom,msm-bus,name = "qcedev-noc";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<56 512 0 0>,
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index 59f9879..79dc287 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -9,7 +9,7 @@
- qcom,ce-hw-instance : should contain crypto HW instance.
- qcom,msm_bus,name: Should be "qcrypto-noc"
- qcom,msm_bus,num_cases: Depends on the use cases for bus scaling
- - qcom,msm_bus,active-only: Default vector index
+ - qcom,msm_bus,active-only: Boolean flag for context of request (actve/dual)
- qcom,msm_bus,num_paths: The paths for source and destination ports
- qcom,msm_bus,vectors: Vectors for bus topology.
@@ -30,7 +30,6 @@
qcom,ce-hw-shared;
qcom,msm-bus,name = "qcrypto-noc";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<56 512 0 0>,
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 0004302..436dfc7 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -97,7 +97,6 @@
/* Bus Scale Settings */
qcom,msm-bus,name = "grp3d";
qcom,msm-bus,num-cases = <6>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 2caa959..ac60e38 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -6,6 +6,8 @@
- qcom,hfi : supported Host-Firmware Interface, one of:
- "venus"
- "q6"
+- qcom,max-hw-load: The maximum load the hardware can support expressed in units
+ of macroblocks per second.
Optional properties:
- reg : offset and length of the register set for the device.
@@ -40,8 +42,6 @@
(enum hal_buffer) to its corresponding TZ usage. The TZ usages are defined
as "enum cp_mem_usage" in include/linux/msm_ion.h
- qcom,has-ocmem: indicate the target has ocmem if this property exists
-- qcom,max-hw-load: The maximum load the hardware can support expressed in units
- of macroblocks per second.
Example:
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index b99b716..caead84 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -92,7 +92,6 @@
qcom,msm-bus,name = "sdcc2";
qcom,msm-bus,num-cases = <7>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
<81 512 6656 13312>, /* 13 MB/s*/
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 87281f7..013d56e 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -155,7 +155,6 @@
qcom,cpu-dma-latency-us = <200>;
qcom,msm-bus,name = "sdhc2";
qcom,msm-bus,num-cases = <7>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
<81 512 6656 13312>, /* 13 MB/s*/
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index ad35985..199862f 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -14,6 +14,8 @@
- vdd_pronto_pll-supply: regulator to supply pronto pll.
- qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
- qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
+- qcom,gpio-proxy-unvote: GPIO used by the wcnss to trigger proxy unvoting in
+ the Apps
- qcom,gpio-force-stop: GPIO used by the Apps to force the wcnss to shutdown.
Example:
@@ -30,6 +32,7 @@
/* GPIO input from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 30d34f6..eb62ea1 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -11,6 +11,9 @@
Optional properties:
- parent-supply: phandle to the parent supply/regulator node
+ - qcom,retain-mems: For Oxili GDSCs only: Presence currently denotes a hardware
+ requirement to assert the forced memory retention signals
+ in the core's clock branch control register.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index aaa731e..6a02e86 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -13,6 +13,8 @@
register base
- reg-names: "apcs_gcc" -string to identify the area where
the APCS GCC registers reside.
+- qcom,pfm-threshold The power coeff threshold in abstract power units below which
+ pmic will be made to operate in PFM mode.
Optional properties:
- qcom,use-phase-switching indicates whether the driver should add/shed phases on the PMIC
@@ -51,6 +53,7 @@
reg-names = "apcs_gcc";
compatible = "qcom,krait-pdn";
qcom,use-phase-switching;
+ qcom,pfm-threshold = <376975>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
index 5861eea..9754c2e 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial.txt
@@ -77,7 +77,6 @@
qcom,msm-bus,name = "serial_uart0";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<84 512 0 0>,
diff --git a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
index c597536..96c9486 100644
--- a/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
+++ b/Documentation/devicetree/bindings/tty/serial/msm_serial_hs.txt
@@ -93,7 +93,6 @@
qcom,msm-bus,name = "uart7";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<84 512 0 0>,
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 6ea9e62..8ce31d9 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -74,7 +74,6 @@
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>,
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
new file mode 100644
index 0000000..f853285
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -0,0 +1,67 @@
+/* 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_dsi_sharp_qhd_video {
+ compatible = "qcom,mdss-dsi-panel";
+ label = "sharp QHD LS043T1LE01 video mode dsi panel";
+ status = "disable";
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+ qcom,enable-gpio = <&msmgpio 58 0>;
+ qcom,rst-gpio = <&pm8941_gpios 19 0>;
+ qcom,mdss-pan-res = <540 960>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-dest = "display_1";
+ qcom,mdss-pan-porch-values = <80 32 48 15 10 3>; /* HBP, HPW, HFP, VBP, VPW, VFP */
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-bl-levels = <1 4095>;
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <1>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <0>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <2>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+ qcom,mdss-pan-dsi-dlane-swap = <0>;
+ qcom,mdss-pan-dsi-t-clk = <0x1c 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x04>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regulator settings */
+ 20 00 01];
+ qcom,panel-phy-timingSettings = [46 1d 20 00 39 3a
+ 21 21 32 03 04 00];
+ qcom,panel-phy-strengthCtrl = [ff 06];
+ qcom,panel-phy-bistCtrl = [00 00 b1 ff /* BIST Ctrl settings */
+ 00 00];
+ qcom,panel-phy-laneConfig = [00 00 00 00 00 00 00 01 97 /* lane0 config */
+ 00 00 00 00 05 00 00 01 97 /* lane1 config */
+ 00 00 00 00 0a 00 00 01 97 /* lane2 config */
+ 00 00 00 00 0f 00 00 01 97 /* lane3 config */
+ 00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
+ qcom,panel-on-cmds = [05 01 00 00 32 02 01 00 /* sw reset */
+ 05 01 00 00 0a 02 11 00 /* exit sleep */
+ 15 01 00 00 0a 02 53 2c /* backlight on */
+ 15 01 00 00 0a 02 51 ff /* brightness max */
+ 05 01 00 00 0a 02 29 00 /* display on */
+ 15 01 00 00 0a 02 ae 03 /* set num of lanes */
+ 15 01 00 00 0a 02 3a 77 /* rgb_888 */];
+ qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,panel-off-cmds = [05 01 00 00 0a 02 28 00 /* display off */
+ 05 01 00 00 78 02 10 00 /* enter sleep */];
+ qcom,off-cmds-dsi-state = "DSI_HS_MODE";
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index ec42cfc..28766cf 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -88,6 +88,24 @@
qcom,fast-avg-setup = <0>;
};
};
+
+ qcom,pm8110_rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8110_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+
+ qcom,pm8110_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
};
qcom,pm8110@1 {
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d712e5f..1881311 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -768,6 +768,17 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@39 {
+ label = "usb_id_nopull";
+ reg = <0x39>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
};
iadc@3600 {
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 0186e54..bf2ab4f 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -99,9 +99,9 @@
"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", "ANCRight Headset Mic",
+ "AMIC5", "MIC BIAS2 External",
"MIC BIAS2 External", "ANCLeft Headset Mic",
"DMIC1", "MIC BIAS1 External",
"MIC BIAS1 External", "Digital Mic1",
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index 6a8ba3a..bb2f0d4 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -33,7 +33,6 @@
/* Bus Scale Settings */
qcom,msm-bus,name = "grp3d";
qcom,msm-bus,num-cases = <4>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index a51d4b8..16a7177 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -176,7 +176,6 @@
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<87 512 0 0>,
@@ -642,8 +641,9 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
@@ -798,6 +798,24 @@
reg = <0xfd484000 0x400>;
qcom,num-locks = <8>;
};
+
+ qcom,qseecom@d980000 {
+ compatible = "qcom,qseecom";
+ reg = <0xd980000 0x256000>;
+ reg-names = "secapp-region";
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 3936000 393600>,
+ <55 512 3936000 393600>,
+ <55 512 3936000 393600>;
+ };
};
&gdsc_venus {
@@ -917,6 +935,16 @@
qcom,fast-avg-setup = <0>;
};
+ chan@39 {
+ label = "usb_id_nopull";
+ reg = <0x39>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
};
&pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index c762405..08da115 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -19,7 +19,7 @@
compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
qcom,msm-id = <147 1 0>, <165 1 0>;
- serial@f991f000 {
+ serial@f991e000 {
status = "ok";
};
};
@@ -38,7 +38,7 @@
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 */
- qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+ qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
@@ -61,7 +61,7 @@
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 */
- qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
+ qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
index f3a8259..5e57430 100644
--- a/arch/arm/boot/dts/msm8610-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -33,7 +33,6 @@
/* Bus Scale Settings */
qcom,msm-bus,name = "grp3d";
qcom,msm-bus,num-cases = <4>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>,
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
index 9690d12..91029e2 100644
--- a/arch/arm/boot/dts/msm8610-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8610-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/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index eaf89ee..2013bb8 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -74,6 +74,13 @@
status = "disabled";
};
+ serial@f991e000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991e000 0x1000>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ };
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
qcom,vidc-ns-map = <0x40000000 0x40000000>;
@@ -85,6 +92,35 @@
qcom,max-hw-load = <97200>; /* FWVGA @ 30 * 2 */
};
+ qcom,usbbam@f9a44000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0xf9a44000 0x11000>;
+ reg-names = "hsusb";
+ interrupts = <0 135 0>;
+ interrupt-names = "hsusb";
+ qcom,usb-bam-num-pipes = <16>;
+ qcom,usb-bam-fifo-baseaddr = <0xfe803000>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+
+ qcom,pipe0 {
+ label = "hsusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <3>;
+ qcom,bam-type = <1>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <1>;
+ qcom,src-bam-physical-address = <0xfc37c000>;
+ qcom,src-bam-pipe-index = <0>;
+ qcom,dst-bam-physical-address = <0xf9a44000>;
+ qcom,dst-bam-pipe-index = <2>;
+ qcom,data-fifo-offset = <0x0>;
+ qcom,data-fifo-size = <0x600>;
+ qcom,descriptor-fifo-offset = <0x600>;
+ qcom,descriptor-fifo-size = <0x200>;
+ };
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
@@ -371,13 +407,18 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
+ qcom,iris-fm {
+ compatible = "qcom,iris_fm";
+ };
+
sound {
compatible = "qcom,msm8x10-audio-codec";
qcom,model = "msm8x10-snd-card";
@@ -483,6 +524,25 @@
compatible = "qcom,msm-pcm-hostless";
};
+ 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 = <&pm8110_l3>;
+ qcom,pronto-vddcx-supply = <&pm8110_s1>;
+ qcom,pronto-vddpx-supply = <&pm8110_l6>;
+ qcom,iris-vddxo-supply = <&pm8110_l10>;
+ qcom,iris-vddrfa-supply = <&pm8110_l5>;
+ qcom,iris-vddpa-supply = <&pm8110_l16>;
+ qcom,iris-vdddig-supply = <&pm8110_l5>;
+
+ gpios = <&msmgpio 23 0>, <&msmgpio 24 0>, <&msmgpio 25 0>, <&msmgpio 26 0>, <&msmgpio 27 0>;
+ qcom,has_pronto_hw;
+ };
+
qcom,mss@fc880000 {
compatible = "qcom,pil-q6v5-mss";
reg = <0xfc880000 0x100>,
@@ -543,6 +603,18 @@
qcom,temp-hysteresis = <10>;
qcom,freq-step = <2>;
};
+
+ qcom,ipc-spinlock@fd484000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0xfd484000 0x400>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,bam_dmux@fc834000 {
+ compatible = "qcom,bam_dmux";
+ reg = <0xfc834000 0x7000>;
+ interrupts = <0 29 1>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index cebb907..bb4b48e 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -284,8 +284,8 @@
qcom,qport = <0>;
qcom,mas-hw-id = <18>;
qcom,mode = "Fixed";
- qcom,prio-rd = <2>;
- qcom,prio-wr = <2>;
+ qcom,prio1 = <2>;
+ qcom,prio0 = <2>;
};
mas-qdss-bam {
@@ -296,8 +296,8 @@
qcom,mode = "Fixed";
qcom,qport = <1>;
qcom,mas-hw-id = <19>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
qcom,hw-sel = "NoC";
};
@@ -342,8 +342,8 @@
qcom,mas-hw-id = <29>;
qcom,slv-hw-id = <28>;
qcom,mode = "Fixed";
- qcom,prio-rd = <2>;
- qcom,prio-wr = <2>;
+ qcom,prio1 = <2>;
+ qcom,prio0 = <2>;
};
fab-ovnoc {
@@ -364,8 +364,8 @@
qcom,qport = <2>;
qcom,mas-hw-id = <23>;
qcom,hw-sel = "NoC";
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
};
mas-crypto-core1 {
@@ -377,8 +377,8 @@
qcom,qport = <3>;
qcom,mas-hw-id = <24>;
qcom,hw-sel = "NoC";
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
};
mas-lpass-proc {
@@ -389,8 +389,8 @@
qcom,qport = <4>;
qcom,mas-hw-id = <25>;
qcom,mode = "Fixed";
- qcom,prio-rd = <2>;
- qcom,prio-wr = <2>;
+ qcom,prio1 = <2>;
+ qcom,prio0 = <2>;
};
mas-mss {
@@ -435,8 +435,8 @@
qcom,qport = <10>;
qcom,mode = "Fixed";
qcom,mas-hw-id = <31>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
qcom,hw-sel = "NoC";
};
@@ -448,8 +448,8 @@
qcom,mode = "Fixed";
qcom,qport = <11>;
qcom,mas-hw-id = <32>;
- qcom,prio-rd = <1>;
- qcom,prio-wr = <1>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
qcom,hw-sel = "NoC";
qcom,iface-clk-node = "msm_usb3";
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 41e3783..91d3bc0 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -229,7 +229,6 @@
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>,
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index ec8a459..de370e7 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -276,7 +276,6 @@
};
&sdcc1 {
- qcom,bus-width = <4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index 28d1d61..3779dbd 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -33,7 +33,6 @@
/* Bus Scale Settings */
qcom,msm-bus,name = "grp3d";
qcom,msm-bus,num-cases = <6>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 0f38e44..0ae20a0 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -382,7 +382,6 @@
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>,
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 5c42b2c..88641f9 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -49,7 +49,7 @@
<0x017C 0x0FFF0FFF>,
<0x0160 0x22222222>,
<0x0164 0x00002222>;
- qcom,mdp-settings = <0x02E0 0x000000AA>,
+ qcom,mdp-settings = <0x02E0 0x000000E9>,
<0x02E4 0x00000055>,
<0x03AC 0xC0000CCC>,
<0x03B4 0xC0000CCC>,
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 5970e6b..a81fc20 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -369,57 +369,99 @@
&pm8941_gpios {
gpio@c000 { /* GPIO 1 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c100 { /* GPIO 2 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c200 { /* GPIO 3 */
- qcom,mode = <0>;
- qcom,pull = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c300 { /* GPIO 4 */
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c400 { /* GPIO 5 */
- qcom,mode = <0>;
- qcom,pull = <0>;
- qcom,vin-sel = <2>;
- qcom,src-sel = <0>;
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
+ qcom,master-en = <1>;
};
gpio@c500 { /* GPIO 6 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c600 { /* GPIO 7 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c700 { /* GPIO 8 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <0>; /* QPNP_PIN_PULL_UP_30 */
+ qcom,master-en = <1>;
};
gpio@c800 { /* GPIO 9 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@c900 { /* GPIO 10 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@ca00 { /* GPIO 11 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cb00 { /* GPIO 12 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cc00 { /* GPIO 13 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@cd00 { /* GPIO 14 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@ce00 { /* GPIO 15 */
@@ -438,7 +480,7 @@
qcom,pull = <5>;
qcom,vin-sel = <2>;
qcom,out-strength = <3>;
- qcom,src-sel = <2>;
+ qcom,src-sel = <3>; /* QPNP_PIN_SEL_FUNC_2 */
qcom,master-en = <1>;
};
@@ -453,60 +495,102 @@
qcom,output-type = <0>; /* QPNP_PIN_OUT_BUF_CMOS */
qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
- qcom,out-strength = <2>; /* QPNP_PIN_OUT_STRENGTH_MED */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,src-sel = <0>; /* QPNP_PIN_SEL_FUNC_CONSTANT */
qcom,master-en = <1>;
};
gpio@d300 { /* GPIO 20 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d400 { /* GPIO 21 */
};
gpio@d500 { /* GPIO 22 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@d600 { /* GPIO 23 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d700 { /* GPIO 24 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d800 { /* GPIO 25 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@d900 { /* GPIO 26 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@da00 { /* GPIO 27 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@db00 { /* GPIO 28 */
};
gpio@dc00 { /* GPIO 29 */
- qcom,pull = <0>; /* set to default pull */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
qcom,master-en = <1>;
- qcom,vin-sel = <2>; /* select 1.8 V source */
};
gpio@dd00 { /* GPIO 30 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@de00 { /* GPIO 31 */
};
gpio@df00 { /* GPIO 32 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e000 { /* GPIO 33 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e100 { /* GPIO 34 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e200 { /* GPIO 35 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <4>; /* QPNP_PIN_PULL_DN */
+ qcom,master-en = <1>;
};
gpio@e300 { /* GPIO 36 */
@@ -520,6 +604,9 @@
};
mpp@a100 { /* MPP 2 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
mpp@a200 { /* MPP 3 */
@@ -534,6 +621,7 @@
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
qcom,src-sel = <0>; /* CONSTANT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,master-en = <1>; /* ENABLE MPP */
};
@@ -543,13 +631,20 @@
qcom,output-type = <0>; /* CMOS */
qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
qcom,src-sel = <0>; /* CONSTANT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
qcom,master-en = <1>; /* ENABLE MPP */
};
mpp@a600 { /* MPP 7 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
mpp@a700 { /* MPP 8 */
+ qcom,mode = <1>; /* QPNP_PIN_MODE_DIG_OUT */
+ qcom,out-strength = <1>; /* QPNP_PIN_OUT_STRENGTH_LOW */
+ qcom,master-en = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 05451671..49450f3 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -448,6 +448,7 @@
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ qcom,pfm-threshold = <376975>;
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 0f762a8..8f2ef31 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -25,3 +25,7 @@
&pm8941_chg {
qcom,chg-charging-disabled;
};
+
+&sdcc1 {
+ qcom,bus-width = <4>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index a0b9be6..ec6b14a 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -188,7 +188,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -205,7 +205,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <75>;
qcom,ss-power = <735>;
qcom,energy-overhead = <77341>;
@@ -223,7 +223,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <95>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
@@ -240,7 +240,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <2000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
@@ -257,7 +257,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <3000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
@@ -446,9 +446,9 @@
qcom,offset-page-indices = <56>;
};
- qcom,rpm-stats@0xfc19dbd0{
+ qcom,rpm-stats@fc19dba0 {
compatible = "qcom,rpm-stats";
- reg = <0xfc19dbd0 0x1000>;
+ reg = <0xfc19dba0 0x1000>;
reg-names = "phys_addr_base";
qcom,sleep-stats-version = <2>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index 24b68b5..41837c1 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -188,7 +188,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -205,7 +205,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <75>;
qcom,ss-power = <735>;
qcom,energy-overhead = <77341>;
@@ -223,7 +223,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <95>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
@@ -240,7 +240,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <2000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
@@ -257,7 +257,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <3000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
@@ -446,9 +446,9 @@
qcom,offset-page-indices = <56>;
};
- qcom,rpm-stats@0xfc19dbd0{
+ qcom,rpm-stats@fc19dba0 {
compatible = "qcom,rpm-stats";
- reg = <0xfc19dbd0 0x1000>;
+ reg = <0xfc19dba0 0x1000>;
reg-names = "phys_addr_base";
qcom,sleep-stats-version = <2>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 50fb380..777d26c 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -57,8 +57,6 @@
&mdss_mdp {
qcom,vbif-settings = <0x0004 0x00000001>;
- qcom,mdp-settings = <0x02E0 0x000000A9>,
- <0x02E4 0x00000055>;
qcom,mdss-wb-off = <0x00011100 0x00011500
0x00011900 0x00011D00 0x00012100>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 56234a1..273c677 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -102,6 +102,7 @@
qcom,vidc {
compatible = "qcom,msm-vidc";
qcom,hfi = "q6";
+ qcom,max-hw-load = <108000>; /* 720p @ 30 */
};
qcom,wfd {
@@ -130,7 +131,6 @@
qcom,msm-bus,name = "serial_uart2";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<84 512 0 0>,
@@ -157,7 +157,6 @@
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<87 512 0 0>,
@@ -198,7 +197,6 @@
qcom,msm-bus,name = "sdcc1";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
<78 512 1600 3200>, /* 400 KB/s*/
@@ -245,7 +243,6 @@
qcom,msm-bus,name = "sdcc2";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
<81 512 1600 3200>, /* 400 KB/s*/
@@ -292,7 +289,6 @@
qcom,msm-bus,name = "sdcc3";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
<79 512 1600 3200>, /* 400 KB/s*/
@@ -338,7 +334,6 @@
qcom,msm-bus,name = "sdcc4";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <80 512 0 0>, /* No vote */
<80 512 1600 3200>, /* 400 KB/s*/
@@ -365,7 +360,6 @@
qcom,msm-bus,name = "sdhc1";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
<78 512 1600 3200>, /* 400 KB/s*/
@@ -392,7 +386,6 @@
qcom,msm-bus,name = "sdhc2";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
<81 512 1600 3200>, /* 400 KB/s*/
@@ -426,7 +419,6 @@
qcom,msm-bus,name = "sdhc3";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
<79 512 1600 3200>, /* 400 KB/s*/
@@ -460,7 +452,6 @@
qcom,msm-bus,name = "sdhc4";
qcom,msm-bus,num-cases = <8>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps = <80 512 0 0>, /* No vote */
<80 512 1600 3200>, /* 400 KB/s*/
@@ -734,7 +725,6 @@
qcom,msm-bus,name = "usb3";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<61 512 0 0>,
@@ -1002,7 +992,6 @@
compatible = "qcom,msm-ocmem-audio";
qcom,msm-bus,name = "audio-ocmem";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<11 604 0 0>,
@@ -1055,8 +1044,9 @@
qcom,firmware-name = "wcnss";
- /* GPIO input from wcnss */
+ /* GPIO inputs from wcnss */
qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
/* GPIO output to wcnss */
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
@@ -1142,7 +1132,6 @@
qcom,qsee-ce-hw-instance = <0>;
qcom,msm-bus,name = "qseecom-noc";
qcom,msm-bus,num-cases = <4>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<55 512 0 0>,
@@ -1223,7 +1212,6 @@
qcom,ce-hw-instance = <1>;
qcom,msm-bus,name = "qcedev-noc";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<56 512 0 0>,
@@ -1240,7 +1228,6 @@
qcom,ce-hw-instance = <1>;
qcom,msm-bus,name = "qcrypto-noc";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<56 512 0 0>,
@@ -1303,6 +1290,29 @@
qcom,limit-temp = <60>;
qcom,temp-hysteresis = <10>;
qcom,freq-step = <2>;
+ qcom,core-limit-temp = <80>;
+ qcom,core-temp-hysteresis = <10>;
+ qcom,core-control-mask = <0xe>;
+ qcom,vdd-restriction-temp = <5>;
+ qcom,vdd-restriction-temp-hysteresis = <10>;
+ qcom,pmic-sw-mode-temp = <90>;
+ qcom,pmic-sw-mode-temp-hysteresis = <70>;
+ qcom,pmic-sw-mode-regs = "vdd_dig";
+ vdd_dig-supply = <&pm8841_s2_floor_corner>;
+ vdd_gfx-supply = <&pm8841_s4_floor_corner>;
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd_dig";
+ qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
+
+ qcom,vdd-gfx-rstr{
+ qcom,vdd-rstr-reg = "vdd_gfx";
+ qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
+
};
qcom,bam_dmux@fc834000 {
@@ -1330,7 +1340,6 @@
qcom,bam-rx-ep-pipe-index = <1>;
qcom,msm-bus,name = "uart7";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<84 512 0 0>,
@@ -1455,6 +1464,7 @@
};
&gdsc_oxili_gx {
+ qcom,retain-mems;
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm9625-pm.dtsi b/arch/arm/boot/dts/msm9625-pm.dtsi
index 51a3faa..3e421a8 100644
--- a/arch/arm/boot/dts/msm9625-pm.dtsi
+++ b/arch/arm/boot/dts/msm9625-pm.dtsi
@@ -80,7 +80,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <100>;
qcom,ss-power = <8000>;
qcom,energy-overhead = <100000>;
@@ -97,7 +97,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <2000>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60100000>;
@@ -114,7 +114,7 @@
qcom,vdd-dig-upper-bound = <6>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <4>; /* NORMAL */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <3500>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60350000>;
@@ -131,7 +131,7 @@
qcom,vdd-dig-upper-bound = <4>; /* NORMAL */
qcom,vdd-dig-lower-bound = <3>; /* SVS SOC */
qcom,irqs-detectable;
- qcom.gpios-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <4500>;
qcom,ss-power = <5000>;
qcom,energy-overhead = <60350000>;
@@ -289,9 +289,9 @@
qcom,offset-page-indices = <56>;
};
- qcom,rpm-stats@fc19dbd0 {
+ qcom,rpm-stats@fc19dba0 {
compatible = "qcom,rpm-stats";
- reg = <0xfc19dbd0 0x1000>;
+ reg = <0xfc19dba0 0x1000>;
reg-names = "phys_addr_base";
qcom,sleep-stats-version = <2>;
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index ee61dc3..0e98aa8 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -101,7 +101,6 @@
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<87 512 0 0>,
@@ -118,7 +117,6 @@
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>,
diff --git a/arch/arm/boot/dts/msmkrypton-sim.dts b/arch/arm/boot/dts/msmkrypton-sim.dts
new file mode 100644
index 0000000..1872a36
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton-sim.dts
@@ -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.
+ */
+
+/dts-v1/;
+
+/include/ "msmkrypton.dtsi"
+
+/ {
+ model = "Qualcomm MSM KRYPTON SIM";
+ compatible = "qcom,msmkrypton-sim", "qcom,msmkrypton", "qcom,sim";
+ qcom,msm-id = <187 16 0>;
+};
+
+&uartdm3{
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
new file mode 100644
index 0000000..db61dab
--- /dev/null
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -0,0 +1,54 @@
+/* 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/ "skeleton.dtsi"
+
+/ {
+ model = "Qualcomm MSM KRYPTON";
+ compatible = "qcom,msmkrypton";
+ interrupt-parent = <&intc>;
+
+ intc: interrupt-controller@f9000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0xf9000000 0x1000>,
+ <0xf9002000 0x1000>;
+ };
+
+ msmgpio: gpio@fd510000 {
+ compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0xfd510000 0x4000>;
+ ngpio = <89>;
+ interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
+ };
+
+ timer: msm-qtimer@f9021000 {
+ compatible = "arm,armv7-timer";
+ reg = <0xf9021000 0x1000>;
+ interrupts = <0 7 0>;
+ irq-is-not-percpu;
+ clock-frequency = <19200000>;
+ };
+
+ uartdm3: serial@f991f000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991f000 0x1000>;
+ interrupts = <0 109 0>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 45f0868..7e835f6 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -267,6 +267,8 @@
CONFIG_MSMB_CAMERA=y
CONFIG_OV9724=y
CONFIG_MSMB_JPEG=y
+CONFIG_SWITCH=y
+CONFIG_MSM_WFD=y
CONFIG_MSM_VIDC_V4L2=y
CONFIG_VIDEOBUF2_MSM_MEM=y
CONFIG_V4L_PLATFORM_DRIVERS=y
@@ -375,3 +377,4 @@
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
CONFIG_QPNP_VIBRATOR=y
+CONFIG_QSEECOM=y
diff --git a/arch/arm/configs/msmkrypton_defconfig b/arch/arm/configs/msmkrypton_defconfig
new file mode 100644
index 0000000..69bc36e
--- /dev/null
+++ b/arch/arm/configs/msmkrypton_defconfig
@@ -0,0 +1,116 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO 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_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSMKRYPTON=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_WATCHDOG_V2=y
+CONFIG_MSM_UARTDM_Core_v14=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_USE_OF=y
+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_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_RUNTIME=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_MTD_MSM_NAND is not set
+CONFIG_MTD_MSM_QPIC_NAND=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_ANDROID_PMEM is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+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_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_MSM=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_EXT3_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 601fcfa..c510889 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -391,6 +391,21 @@
select MEMORY_HOLE_CARVEOUT
select MSM_RPM_LOG
+config ARCH_MSMKRYPTON
+ bool "MSMKRYPTON"
+ select ARM_GIC
+ select CPU_V7
+ select MSM_GPIOMUX
+ select MSM_RPM_SMD
+ select MSM_NATIVE_RESTART
+ select MSM_RESTART_V2
+ select MSM_SPM_V2
+ select MSM_PM8X60 if PM
+ select MULTI_IRQ_HANDLER
+ select GPIO_MSM_V3
+ select MAY_HAVE_SPARSE_IRQ
+ select SPARSE_IRQ
+
config ARCH_MSM8610
bool "MSM8610"
select ARM_GIC
@@ -1074,6 +1089,7 @@
default "0x00000000" if ARCH_MSM8610
default "0x10000000" if ARCH_FSM9XXX
default "0x00200000" if ARCH_MSM9625
+ default "0x00200000" if ARCH_MSMKRYPTON
default "0x00200000" if !MSM_STACKED_MEMORY
default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
default "0x20000000" if ARCH_QSD8X50
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 1c14ac6..7c78395 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
ifndef CONFIG_ARCH_MPQ8092
ifndef CONFIG_ARCH_MSM8610
ifndef CONFIG_ARCH_MSMZINC
+ifndef CONFIG_ARCH_MSMKRYPTON
obj-y += nand_partitions.o
endif
endif
@@ -131,6 +132,7 @@
endif
endif
endif
+endif
obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -304,6 +306,7 @@
obj-$(CONFIG_ARCH_MSM8226) += gdsc.o
obj-$(CONFIG_ARCH_MSM8610) += gdsc.o
obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += board-krypton.o board-krypton-gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o acpuclock-9625.o acpuclock-cortex.o
obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
@@ -368,6 +371,7 @@
obj-$(CONFIG_ARCH_MSM9615) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8974) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSMKRYPTON) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MPQ8092) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index e3b8d73..f20f6ae 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -62,6 +62,9 @@
zreladdr-$(CONFIG_ARCH_MSMZINC) := 0x00008000
dtb-$(CONFIG_ARCH_MSMZINC) += msmzinc-sim.dtb
+# MSMKRYPTON
+ zreladdr-$(CONFIG_ARCH_MSMKRYPTON) := 0x00208000
+ dtb-$(CONFIG_ARCH_MSMKRYPTON) += msmkrypton-sim.dtb
# MSM9615
zreladdr-$(CONFIG_ARCH_MSM9615) := 0x40808000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c60e89a..a61f5ca 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -128,122 +128,122 @@
};
static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 229 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 298 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 321 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 346 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 397 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 423 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 506 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 835000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 845000, 229 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 905000, 298 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 920000, 321 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 940000, 346 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 980000, 397 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 995000, 423 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1015000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1030000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1050000, 506 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 298 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 321 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 346 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 397 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 423 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 506 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 298 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 321 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 346 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 930000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 945000, 397 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 423 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 975000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 990000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1000000, 506 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 825000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 825000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 835000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 855000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 885000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 925000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 940000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 950000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 825000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(3), 825000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(6), 825000, 124 },
+ { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(7), 825000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(10), 825000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 229 },
+ { 0, { 960000, HFPLL, 1, 50 }, L2(10), 825000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 825000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 835000, 298 },
+ { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 855000, 321 },
+ { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 346 },
+ { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 885000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 397 },
+ { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 423 },
+ { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 925000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 940000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 950000, 506 },
{ 0, { 0 } }
};
@@ -284,618 +284,618 @@
};
static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 815000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 835000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 845000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 855000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 865000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 875000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 890000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 900000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 915000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 925000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 940000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 950000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 965000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 980000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 995000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 1010000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1025000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1040000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1055000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1070000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1085000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 815000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 825000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 835000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 845000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 855000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 865000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 875000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 890000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 900000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 915000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 925000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 940000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 950000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 965000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 980000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 995000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 1010000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1025000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1040000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1055000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1070000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1085000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 810000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 820000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 830000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 840000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 850000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 860000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 875000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 885000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 895000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 910000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 920000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 930000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 945000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 960000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 975000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1005000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1020000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1030000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1045000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1060000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 810000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 820000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 830000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 840000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 850000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 860000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 875000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 885000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 895000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 910000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 920000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 930000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 945000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 960000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 975000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1005000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1020000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1030000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1045000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1060000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 785000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 795000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 910000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 955000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1005000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1020000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1035000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 785000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 795000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 910000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 955000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1005000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1020000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1035000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 780000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 790000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 935000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 970000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 985000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 995000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1010000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 780000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 790000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 935000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 970000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 985000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 995000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1010000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 780000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 790000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 950000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 960000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 975000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 985000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 780000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 790000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 950000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 960000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 975000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 985000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 760000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 770000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 860000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 870000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 880000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 930000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 940000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 955000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 965000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 975000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 760000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 770000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 860000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 870000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 880000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 930000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 940000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 955000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 965000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 975000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 760000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 770000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 905000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 73 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 760000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 770000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 252 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 275 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 298 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 321 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 346 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 371 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 397 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 423 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 905000, 450 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 477 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 506 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 536 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 567 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 598 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 915000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 950000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 965000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1010000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1025000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1040000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 915000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 950000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 965000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1010000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1025000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1040000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 920000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 930000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 945000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 975000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 990000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1005000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1020000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 920000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 930000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 945000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 975000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 990000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1005000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1020000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 785000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 795000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 805000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 815000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 825000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 835000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 845000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 910000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 980000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 995000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 785000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 795000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 805000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 815000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 825000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 835000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 845000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 910000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 980000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 995000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 960000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 970000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 985000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 995000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 960000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 970000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 985000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 995000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 870000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 880000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 920000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 940000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 950000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 975000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 985000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 870000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 880000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 920000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 940000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 950000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 975000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 985000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 890000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 920000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 940000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 955000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 965000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 975000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 890000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 920000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 940000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 955000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 965000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 975000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 875000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 920000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 930000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 3200000 },
- { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 950000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 102 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 121 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 141 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 161 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 181 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 202 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 223 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 245 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 267 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 289 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 313 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 336 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 360 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 383 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 409 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 875000, 435 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 461 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 488 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 516 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 543 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 920000, 573 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 930000, 604 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 636 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 950000, 656 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 805000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 815000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 835000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 845000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 855000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 865000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 915000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 940000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 805000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 815000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 825000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 835000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 845000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 855000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 865000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 915000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 940000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 875000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 885000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 945000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 960000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 975000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 990000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1005000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 875000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 885000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 945000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 960000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 975000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 990000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1005000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 785000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 795000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 805000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 815000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 825000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 835000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 845000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 855000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 865000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 940000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 955000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 970000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 785000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 795000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 805000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 815000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 825000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 835000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 845000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 855000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 865000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 940000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 955000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 970000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 925000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 935000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 950000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 960000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 925000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 935000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 950000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 960000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 895000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 910000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 895000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 910000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 880000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 890000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 910000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 920000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 965000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 880000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 890000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 910000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 920000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 965000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 691 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 760000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 770000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 780000, 3200000 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 790000, 3200000 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 810000, 3200000 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 820000, 3200000 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 830000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 840000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 850000, 3200000 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 3200000 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 875000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 885000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 905000, 3200000 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 3200000 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 3200000 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 3200000 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 3200000 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 159 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 760000, 180 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 770000, 200 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 780000, 221 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 790000, 242 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 264 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 810000, 287 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 820000, 308 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 830000, 333 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 840000, 356 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 850000, 380 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 404 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 430 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 875000, 456 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 885000, 482 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 510 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 905000, 538 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 565 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 596 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 627 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 659 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 691 },
{ 0, { 0 } }
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 707abef..0fe94d5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -186,7 +186,7 @@
#endif
}
-static int apq8064_paddr_to_memtype(unsigned int paddr)
+static int apq8064_paddr_to_memtype(phys_addr_t paddr)
{
return MEMTYPE_EBI1;
}
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 6371b9d..3582914 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -25,6 +25,7 @@
#include <linux/of_irq.h>
#include <linux/memory.h>
#include <linux/regulator/qpnp-regulator.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
@@ -112,7 +113,7 @@
msm_clock_init(&msm8226_rumi_clock_init_data);
else
msm_clock_init(&msm8226_clock_init_data);
-
+ tsens_tm_init_driver();
msm_thermal_device_init();
}
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 15d7679..4b435de 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -35,6 +35,48 @@
.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 lcd_en_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_HIGH,
+};
+
+static struct gpiomux_setting lcd_en_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
+ {
+ .gpio = 41,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &lcd_en_act_cfg,
+ [GPIOMUX_SUSPENDED] = &lcd_en_sus_cfg,
+ },
+ },
+ {
+ .gpio = 7,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &lcd_en_act_cfg,
+ [GPIOMUX_SUSPENDED] = &lcd_en_sus_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
.gpio = 10, /* BLSP1 QUP3 I2C_SDA */
@@ -74,6 +116,44 @@
},
};
+static struct msm_gpiomux_config wcnss_5wire_interface[] = {
+ {
+ .gpio = 23,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 24,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 25,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 26,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 27,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &wcnss_5wire_active_cfg,
+ [GPIOMUX_SUSPENDED] = &wcnss_5wire_suspend_cfg,
+ },
+ },
+};
+
void __init msm8610_init_gpiomux(void)
{
int rc;
@@ -85,4 +165,7 @@
}
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(msm_lcd_configs, ARRAY_SIZE(msm_lcd_configs));
}
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 99db345..67334d5 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -24,6 +24,7 @@
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/memory.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/arch_timer.h>
#include <asm/hardware/gic.h>
@@ -105,6 +106,7 @@
msm_lpmrs_module_init();
msm_spm_device_init();
qpnp_regulator_init();
+ tsens_tm_init_driver();
msm_thermal_device_init();
if (of_board_is_rumi())
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 771e678..8be128c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -226,7 +226,7 @@
#endif
}
-static int msm8930_paddr_to_memtype(unsigned int paddr)
+static int msm8930_paddr_to_memtype(phys_addr_t paddr)
{
return MEMTYPE_EBI1;
}
@@ -957,7 +957,7 @@
},
{
ARRAY_SIZE(qseecom_enable_dfab_vectors),
- qseecom_enable_sfpb_vectors,
+ qseecom_enable_dfab_vectors,
},
{
ARRAY_SIZE(qseecom_enable_sfpb_vectors),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index f3d8a2f..c5fc418 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -236,7 +236,7 @@
#endif
}
-static int msm8960_paddr_to_memtype(unsigned int paddr)
+static int msm8960_paddr_to_memtype(phys_addr_t paddr)
{
return MEMTYPE_EBI1;
}
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index e30d0ba..3b92171 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -743,7 +743,8 @@
.pull = GPIOMUX_PULL_DOWN,
};
-static struct msm_gpiomux_config msm8974_pri_auxpcm_configs[] __initdata = {
+/* Primary AUXPCM port sharing GPIO lines with Primary MI2S */
+static struct msm_gpiomux_config msm8974_pri_pri_auxpcm_configs[] __initdata = {
{
.gpio = 65,
.settings = {
@@ -774,6 +775,38 @@
},
};
+/* Primary AUXPCM port sharing GPIO lines with Tertiary MI2S */
+static struct msm_gpiomux_config msm8974_pri_ter_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 74,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 75,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 76,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 77,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm8974_sec_auxpcm_configs[] __initdata = {
{
.gpio = 79,
@@ -1090,8 +1123,13 @@
msm_gpiomux_install(msm_mhl_configs,
ARRAY_SIZE(msm_mhl_configs));
- msm_gpiomux_install(msm8974_pri_auxpcm_configs,
- ARRAY_SIZE(msm8974_pri_auxpcm_configs));
+ if (of_board_is_liquid())
+ msm_gpiomux_install(msm8974_pri_ter_auxpcm_configs,
+ ARRAY_SIZE(msm8974_pri_ter_auxpcm_configs));
+ else
+ msm_gpiomux_install(msm8974_pri_pri_auxpcm_configs,
+ ARRAY_SIZE(msm8974_pri_pri_auxpcm_configs));
+
msm_gpiomux_install(msm8974_sec_auxpcm_configs,
ARRAY_SIZE(msm8974_sec_auxpcm_configs));
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 9b69c8f..cfa1628 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -22,6 +22,7 @@
#include <linux/memory.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/krait-regulator.h>
+#include <linux/msm_tsens.h>
#include <linux/msm_thermal.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
@@ -59,7 +60,7 @@
},
};
-static int msm8974_paddr_to_memtype(unsigned int paddr)
+static int msm8974_paddr_to_memtype(phys_addr_t paddr)
{
return MEMTYPE_EBI1;
}
@@ -101,6 +102,7 @@
msm_clock_init(&msm8974_rumi_clock_init_data);
else
msm_clock_init(&msm8974_clock_init_data);
+ tsens_tm_init_driver();
msm_thermal_device_init();
}
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 923dc2a..3bb00bb 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/of_irq.h>
#include <linux/memory.h>
+#include <linux/msm_tsens.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <asm/mach/arch.h>
@@ -237,6 +238,7 @@
msm_spm_device_init();
msm_clock_init(&msm9625_clock_init_data);
msm9625_init_buses();
+ tsens_tm_init_driver();
}
void __init msm9625_init(void)
diff --git a/arch/arm/mach-msm/board-krypton-gpiomux.c b/arch/arm/mach-msm/board-krypton-gpiomux.c
new file mode 100644
index 0000000..3d86ba7
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton-gpiomux.c
@@ -0,0 +1,52 @@
+/* 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/ioport.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+
+static struct gpiomux_setting gpio_uart_config = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
+ {
+ .gpio = 8, /* BLSP1 UART TX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_uart_config,
+ },
+ },
+ {
+ .gpio = 9, /* BLSP1 UART RX */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_uart_config,
+ },
+ },
+};
+
+void __init msmkrypton_init_gpiomux(void)
+{
+ int rc;
+
+ rc = msm_gpiomux_init_dt();
+ if (rc) {
+ pr_err("%s failed %d\n", __func__, rc);
+ return;
+ }
+
+ msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
+}
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
new file mode 100644
index 0000000..aada3b0
--- /dev/null
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -0,0 +1,84 @@
+/* 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/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memtypes.h>
+#include <mach/msm_smd.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+
+static struct clk_lookup msm_clocks_dummy[] = {
+ CLK_DUMMY("core_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+ .table = msm_clocks_dummy,
+ .size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msmkrypton_add_drivers(void)
+{
+ msm_smd_init();
+ msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init msmkrypton_map_io(void)
+{
+ msm_map_msmkrypton_io();
+}
+
+void __init msmkrypton_init(void)
+{
+ if (socinfo_init() < 0)
+ pr_err("%s: socinfo_init() failed\n", __func__);
+
+ msmkrypton_init_gpiomux();
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ msmkrypton_add_drivers();
+}
+
+static const char *msmkrypton_dt_match[] __initconst = {
+ "qcom,msmkrypton",
+ NULL
+};
+
+DT_MACHINE_START(MSMKRYPTON_DT, "Qualcomm MSM Krypton (Flattened Device Tree)")
+ .map_io = msmkrypton_map_io,
+ .init_irq = msm_dt_init_irq,
+ .init_machine = msmkrypton_init,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_dt_timer,
+ .dt_compat = msmkrypton_dt_match,
+ .restart = msm_restart,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 6b98393..0e1c03e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -5558,7 +5558,7 @@
reserve_rtb_memory();
}
-static int msm8x60_paddr_to_memtype(unsigned int paddr)
+static int msm8x60_paddr_to_memtype(phys_addr_t paddr)
{
if (paddr >= 0x40000000 && paddr < 0x60000000)
return MEMTYPE_EBI1;
diff --git a/arch/arm/mach-msm/board-zinc.c b/arch/arm/mach-msm/board-zinc.c
index fa19e39..444444f 100644
--- a/arch/arm/mach-msm/board-zinc.c
+++ b/arch/arm/mach-msm/board-zinc.c
@@ -43,7 +43,7 @@
},
};
-static int msmzinc_paddr_to_memtype(unsigned int paddr)
+static int msmzinc_paddr_to_memtype(phys_addr_t paddr)
{
return MEMTYPE_EBI1;
}
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 80907c8..5f9eafd 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2776,6 +2776,7 @@
},
.base = &virt_bases[APCS_PLL_BASE],
.c = {
+ .parent = &xo_a_clk.c,
.dbg_name = "a7sspll",
.ops = &clk_ops_sr2_pll,
.vdd_class = &vdd_sr2_pll,
@@ -3529,17 +3530,6 @@
panic("clock-8226: Unable to get the vdd_sr2_dig regulator!");
/*
- * These regulators are used at boot. Ensure they stay on
- * while the clock framework comes online.
- */
- vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
- regulator_enable(vdd_sr2_pll.regulator[0]);
- regulator_enable(vdd_sr2_pll.regulator[1]);
-
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig.regulator[0]);
-
- /*
* Hold an active set vote at a rate of 40MHz for the MMSS NOC AHB
* source. Sleep set vote is 0.
* RPM will also turn on gcc_mmss_noc_cfg_ahb_clk, which is needed to
@@ -3561,17 +3551,9 @@
mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
}
-static int __init msm8226_clock_late_init(void)
-{
- unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
- unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- return 0;
-}
-
struct clock_init_data msm8226_clock_init_data __initdata = {
.table = msm_clocks_8226,
.size = ARRAY_SIZE(msm_clocks_8226),
.pre_init = msm8226_clock_pre_init,
.post_init = msm8226_clock_post_init,
- .late_init = msm8226_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 768efe7..4a716fc 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -564,6 +564,7 @@
},
.base = &virt_bases[APCS_PLL_BASE],
.c = {
+ .parent = &gcc_xo_a_clk_src.c,
.dbg_name = "a7sspll",
.ops = &clk_ops_sr2_pll,
.vdd_class = &vdd_sr2_pll,
@@ -2782,12 +2783,16 @@
CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
CLK_LOOKUP("measure_clk", l2_m_clk, ""),
+ CLK_LOOKUP("xo", gcc_xo_clk_src.c, "fb000000.qcom,wcnss-wlan"),
+ CLK_LOOKUP("rf_clk", cxo_a2.c, "fb000000.qcom,wcnss-wlan"),
+
CLK_LOOKUP("iface_clk", mdp_ahb_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("core_clk", mdp_axi_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("lcdc_clk", mdp_lcdc_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("vsync_clk", mdp_vsync_clk.c, "fd900000.qcom,mdss_mdp"),
+ CLK_LOOKUP("dsi_clk", mdp_dsi_clk.c, "fd900000.qcom,mdss_mdp"),
CLK_LOOKUP("iface_clk", dsi_ahb_clk.c, "fdd00000.qcom,mdss_dsi"),
- CLK_LOOKUP("core_clk", dsi_clk.c, "fdd00000.qcom,mdss_dsi"),
+ CLK_LOOKUP("dsi_clk", dsi_clk.c, "fdd00000.qcom,mdss_dsi"),
CLK_LOOKUP("byte_clk", dsi_byte_clk.c, "fdd00000.qcom,mdss_dsi"),
CLK_LOOKUP("esc_clk", dsi_esc_clk.c, "fdd00000.qcom,mdss_dsi"),
CLK_LOOKUP("pixel_clk", dsi_pclk_clk.c, "fdd00000.qcom,mdss_dsi"),
@@ -2966,19 +2971,6 @@
if (IS_ERR(vdd_sr2_pll.regulator[1]))
panic("clock-8610: Unable to get the vdd_sr2_dig regulator!");
- vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
- regulator_enable(vdd_sr2_pll.regulator[0]);
- regulator_enable(vdd_sr2_pll.regulator[1]);
-
- /*
- * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
- * until late_init. This may not be necessary with clock handoff;
- * Investigate this code on a real non-simulator target to determine
- * its necessity.
- */
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig.regulator[0]);
-
enable_rpm_scaling();
/* Enable a clock to allow access to MMSS clock registers */
@@ -2995,17 +2987,9 @@
clk_prepare_enable(&mmss_s0_axi_clk.c);
}
-static int __init msm8610_clock_late_init(void)
-{
- unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
- return 0;
-}
-
struct clock_init_data msm8610_clock_init_data __initdata = {
.table = msm_clocks_8610,
.size = ARRAY_SIZE(msm_clocks_8610),
.pre_init = msm8610_clock_pre_init,
.post_init = msm8610_clock_post_init,
- .late_init = msm8610_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index aefaa5c..509443d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -6740,8 +6740,6 @@
if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
prng_clk.freq_tbl = clk_tbl_prng_64;
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
clk_ops_local_pll.enable = sr_pll_clk_enable;
}
@@ -6852,7 +6850,7 @@
if (WARN(rc, "cfpb_a_clk not enabled (%d)\n", rc))
return rc;
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ return 0;
}
struct clock_init_data msm8960_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e6874b7..c42da92 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -1405,7 +1405,14 @@
};
static struct clk_freq_tbl ftbl_gcc_gp_clk[] = {
- F(19200000, cxo, 1, 0, 0),
+ F( 4800000, cxo, 4, 0, 0),
+ F( 6000000, gpll0, 10, 1, 10),
+ F( 6750000, gpll0, 1, 1, 89),
+ F( 8000000, gpll0, 15, 1, 5),
+ F( 9600000, cxo, 2, 0, 0),
+ F(16000000, gpll0, 1, 2, 75),
+ F(19200000, cxo, 1, 0, 0),
+ F(24000000, gpll0, 5, 1, 5),
F_END
};
@@ -5107,6 +5114,7 @@
CLK_LOOKUP("bus_clk", venus0_axi_clk.c, "fdc00000.qcom,vidc"),
CLK_LOOKUP("mem_clk", venus0_ocmemnoc_clk.c, "fdc00000.qcom,vidc"),
+ CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fd8c4024.qcom,gdsc"),
/* LPASS clocks */
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "fc880000.qcom,mss"),
@@ -5487,15 +5495,6 @@
if (IS_ERR(vdd_dig.regulator[0]))
panic("clock-8974: Unable to get the vdd_dig regulator!");
- /*
- * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
- * until late_init. This may not be necessary with clock handoff;
- * Investigate this code on a real non-simulator target to determine
- * its necessity.
- */
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig.regulator[0]);
-
enable_rpm_scaling();
reg_init();
@@ -5532,11 +5531,6 @@
mdss_clk_ctrl_pre_init(&mdss_ahb_clk.c);
}
-static int __init msm8974_clock_late_init(void)
-{
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
static void __init msm8974_rumi_clock_pre_init(void)
{
virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5552,15 +5546,6 @@
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!");
-
- /*
- * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
- * until late_init. This may not be necessary with clock handoff;
- * Investigate this code on a real non-simulator target to determine
- * its necessity.
- */
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
- regulator_enable(vdd_dig.regulator[0]);
}
struct clock_init_data msm8974_clock_init_data __initdata = {
@@ -5568,7 +5553,6 @@
.size = ARRAY_SIZE(msm_clocks_8974),
.pre_init = msm8974_clock_pre_init,
.post_init = msm8974_clock_post_init,
- .late_init = msm8974_clock_late_init,
};
struct clock_init_data msm8974_rumi_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index d0b4a32..5d55966 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3777,8 +3777,6 @@
static void __init msm8660_clock_pre_init(void)
{
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
/* Setup MM_PLL2 (PLL3), but turn it off. Rate set by set_rate_tv(). */
rmwreg(0, MM_PLL2_MODE_REG, BIT(0)); /* Disable output */
/* Set ref, bypass, assert reset, disable output, disable test mode */
@@ -3900,7 +3898,7 @@
if (WARN(rc, "mmfpb_a_clk not enabled (%d)\n", rc))
return rc;
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ return 0;
}
struct clock_init_data msm8x60_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index d6ae4335..6b218a1 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1754,8 +1754,6 @@
{
u32 regval, is_pll_enabled, pll9_lval;
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-
clk_ops_local_pll.enable = sr_pll_clk_enable;
/* Enable PDM CXO source. */
@@ -1831,15 +1829,9 @@
clk_disable_unprepare(&pdm_clk.c);
}
-static int __init msm9615_clock_late_init(void)
-{
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
struct clock_init_data msm9615_clock_init_data __initdata = {
.table = msm_clocks_9615,
.size = ARRAY_SIZE(msm_clocks_9615),
.pre_init = msm9615_clock_pre_init,
.post_init = msm9615_clock_post_init,
- .late_init = msm9615_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 6817c6c..0d97401 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -411,6 +411,7 @@
},
.base = &virt_bases[APCS_PLL_BASE],
.c = {
+ .parent = &cxo_a_clk_src.c,
.dbg_name = "apcspll_clk_src",
.ops = &clk_ops_local_pll,
CLK_INIT(apcspll_clk_src.c),
@@ -2089,9 +2090,6 @@
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.regulator[0]);
-
enable_rpm_scaling();
reg_init();
@@ -2107,15 +2105,9 @@
measure_mux_common, sizeof(measure_mux_common));
}
-static int __init msm9625_clock_late_init(void)
-{
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
-}
-
struct clock_init_data msm9625_clock_init_data __initdata = {
.table = msm_clocks_9625,
.size = ARRAY_SIZE(msm_clocks_9625),
.pre_init = msm9625_clock_pre_init,
.post_init = msm9625_clock_post_init,
- .late_init = msm9625_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 5da1663..0b8240c 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -756,10 +756,10 @@
spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
reg_val = readl_relaxed(b->retain_reg);
switch (flags) {
- case CLKFLAG_RETAIN:
+ case CLKFLAG_RETAIN_MEM:
reg_val |= b->retain_mask;
break;
- case CLKFLAG_NORETAIN:
+ case CLKFLAG_NORETAIN_MEM:
reg_val &= ~b->retain_mask;
break;
default:
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 8bdc496..8c2121f 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -570,6 +570,40 @@
return __branch_clk_reset(BCR_REG(branch), action);
}
+static int branch_clk_set_flags(struct clk *c, unsigned flags)
+{
+ u32 cbcr_val;
+ unsigned long irq_flags;
+ struct branch_clk *branch = to_branch_clk(c);
+ int ret = 0;
+
+ spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
+ cbcr_val = readl_relaxed(CBCR_REG(branch));
+ switch (flags) {
+ case CLKFLAG_RETAIN_PERIPH:
+ cbcr_val |= BIT(13);
+ break;
+ case CLKFLAG_NORETAIN_PERIPH:
+ cbcr_val &= ~BIT(13);
+ break;
+ case CLKFLAG_RETAIN_MEM:
+ cbcr_val |= BIT(14);
+ break;
+ case CLKFLAG_NORETAIN_MEM:
+ cbcr_val &= ~BIT(14);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ writel_relaxed(cbcr_val, CBCR_REG(branch));
+ spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
+
+ /* Make sure write is issued before returning. */
+ mb();
+
+ return ret;
+}
+
/*
* Voteable clock functions
*/
@@ -824,6 +858,7 @@
.list_rate = branch_clk_list_rate,
.round_rate = branch_clk_round_rate,
.reset = branch_clk_reset,
+ .set_flags = branch_clk_set_flags,
.handoff = branch_clk_handoff,
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 9b34465..044fc2c 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -33,6 +33,12 @@
};
static LIST_HEAD(handoff_list);
+struct handoff_vdd {
+ struct list_head list;
+ struct clk_vdd_class *vdd_class;
+};
+static LIST_HEAD(handoff_vdd_list);
+
/* Find the voltage level required for a given rate. */
int find_vdd_level(struct clk *clk, unsigned long rate)
{
@@ -159,7 +165,7 @@
unvote_vdd_level(clk->vdd_class, level);
}
-/* Returns true if the rate is valid without voting for it */
+/* Check if the rate is within the voltage limits of the clock. */
static bool is_rate_valid(struct clk *clk, unsigned long rate)
{
int level;
@@ -171,6 +177,92 @@
return level >= 0;
}
+/**
+ * __clk_pre_reparent() - Set up the new parent before switching to it and
+ * prevent the enable state of the child clock from changing.
+ * @c: The child clock that's going to switch parents
+ * @new: The new parent that the child clock is going to switch to
+ * @flags: Pointer to scratch space to save spinlock flags
+ *
+ * Cannot be called from atomic context.
+ *
+ * Use this API to set up the @new parent clock to be able to support the
+ * current prepare and enable state of the child clock @c. Once the parent is
+ * set up, the child clock can safely switch to it.
+ *
+ * The caller shall grab the prepare_lock of clock @c before calling this API
+ * and only release it after calling __clk_post_reparent() for clock @c (or
+ * if this API fails). This is necessary to prevent the prepare state of the
+ * child clock @c from changing while the reparenting is in progress. Since
+ * this API takes care of grabbing the enable lock of @c, only atomic
+ * operation are allowed between calls to __clk_pre_reparent and
+ * __clk_post_reparent()
+ *
+ * The scratch space pointed to by @flags should not be altered before
+ * calling __clk_post_reparent() for clock @c.
+ *
+ * See also: __clk_post_reparent()
+ */
+int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags)
+{
+ int rc;
+
+ if (c->prepare_count) {
+ rc = clk_prepare(new);
+ if (rc)
+ return rc;
+ }
+
+ spin_lock_irqsave(&c->lock, *flags);
+ if (c->count) {
+ rc = clk_enable(new);
+ if (rc) {
+ spin_unlock_irqrestore(&c->lock, *flags);
+ clk_unprepare(new);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+/**
+ * __clk_post_reparent() - Release requirements on old parent after switching
+ * away from it and allow changes to the child clock's enable state.
+ * @c: The child clock that switched parents
+ * @old: The old parent that the child clock switched away from or the new
+ * parent of a failed reparent attempt.
+ * @flags: Pointer to scratch space where spinlock flags were saved
+ *
+ * Cannot be called from atomic context.
+ *
+ * This API works in tandem with __clk_pre_reparent. Use this API to
+ * - Remove prepare and enable requirements from the @old parent after
+ * switching away from it
+ * - Or, undo the effects of __clk_pre_reparent() after a failed attempt to
+ * change parents
+ *
+ * The caller shall release the prepare_lock of @c that was grabbed before
+ * calling __clk_pre_reparent() only after this API is called (or if
+ * __clk_pre_reparent() fails). This is necessary to prevent the prepare
+ * state of the child clock @c from changing while the reparenting is in
+ * progress. Since this API releases the enable lock of @c, the limit to
+ * atomic operations set by __clk_pre_reparent() is no longer present.
+ *
+ * The scratch space pointed to by @flags shall not be altered since the call
+ * to __clk_pre_reparent() for clock @c.
+ *
+ * See also: __clk_pre_reparent()
+ */
+void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags)
+{
+ if (c->count)
+ clk_disable(old);
+ spin_unlock_irqrestore(&c->lock, *flags);
+
+ if (c->prepare_count)
+ clk_unprepare(old);
+}
+
int clk_prepare(struct clk *clk)
{
int ret = 0;
@@ -357,6 +449,9 @@
if (!clk->ops->set_rate)
return -ENOSYS;
+ if (!is_rate_valid(clk, rate))
+ return -EINVAL;
+
mutex_lock(&clk->prepare_lock);
/* Return early if the rate isn't going to change */
@@ -364,31 +459,32 @@
goto out;
trace_clock_set_rate(name, rate, raw_smp_processor_id());
+
+ start_rate = clk->rate;
+
+ /* Enforce vdd requirements for target frequency. */
if (clk->prepare_count) {
- start_rate = clk->rate;
- /* Enforce vdd requirements for target frequency. */
rc = vote_rate_vdd(clk, rate);
if (rc)
goto out;
- rc = clk->ops->set_rate(clk, rate);
- if (rc)
- goto err_set_rate;
- /* Release vdd requirements for starting frequency. */
- unvote_rate_vdd(clk, start_rate);
- } else if (is_rate_valid(clk, rate)) {
- rc = clk->ops->set_rate(clk, rate);
- } else {
- rc = -EINVAL;
}
- if (!rc)
- clk->rate = rate;
+ rc = clk->ops->set_rate(clk, rate);
+ if (rc)
+ goto err_set_rate;
+ clk->rate = rate;
+
+ /* Release vdd requirements for starting frequency. */
+ if (clk->prepare_count)
+ unvote_rate_vdd(clk, start_rate);
+
out:
mutex_unlock(&clk->prepare_lock);
return rc;
err_set_rate:
- unvote_rate_vdd(clk, rate);
+ if (clk->prepare_count)
+ unvote_rate_vdd(clk, rate);
goto out;
}
EXPORT_SYMBOL(clk_set_rate);
@@ -498,6 +594,38 @@
}
EXPORT_SYMBOL(msm_clock_register);
+
+static void vdd_class_init(struct clk_vdd_class *vdd)
+{
+ struct handoff_vdd *v;
+ int i;
+
+ if (!vdd)
+ return;
+
+ list_for_each_entry(v, &handoff_vdd_list, list) {
+ if (v->vdd_class == vdd)
+ return;
+ }
+
+ pr_debug("voting for vdd_class %s\n", vdd->class_name);
+ if (vote_vdd_level(vdd, vdd->num_levels - 1))
+ pr_err("failed to vote for %s\n", vdd->class_name);
+
+ for (i = 0; i < vdd->num_regulators; i++)
+ regulator_enable(vdd->regulator[i]);
+
+ v = kmalloc(sizeof(*v), GFP_KERNEL);
+ if (!v) {
+ pr_err("Unable to kmalloc. %s will be stuck at max.\n",
+ vdd->class_name);
+ return;
+ }
+
+ v->vdd_class = vdd;
+ list_add_tail(&v->list, &handoff_vdd_list);
+}
+
static int __init __handoff_clk(struct clk *clk)
{
enum handoff state = HANDOFF_DISABLED_CLK;
@@ -603,6 +731,16 @@
init_sibling_lists(clock_tbl, num_clocks);
/*
+ * Enable regulators and temporarily set them up at maximum voltage.
+ * Once all the clocks have made their respective vote, remove this
+ * temporary vote. The removing of the temporary vote is done at
+ * late_init, by which time we assume all the clocks would have been
+ * handed off.
+ */
+ for (n = 0; n < num_clocks; n++)
+ vdd_class_init(clock_tbl[n].clk->vdd_class);
+
+ /*
* Detect and preserve initial clock state until clock_late_init() or
* a driver explicitly changes it, whichever is first.
*/
@@ -623,8 +761,12 @@
static int __init clock_late_init(void)
{
struct handoff_clk *h, *h_temp;
+ struct handoff_vdd *v, *v_temp;
int ret = 0;
+ if (clk_init_data->late_init)
+ ret = clk_init_data->late_init();
+
pr_info("%s: Removing enables held for handed-off clocks\n", __func__);
list_for_each_entry_safe(h, h_temp, &handoff_list, list) {
clk_disable_unprepare(h->clk);
@@ -632,8 +774,12 @@
kfree(h);
}
- if (clk_init_data->late_init)
- ret = clk_init_data->late_init();
+ list_for_each_entry_safe(v, v_temp, &handoff_vdd_list, list) {
+ unvote_vdd_level(v->vdd_class, v->vdd_class->num_levels - 1);
+ list_del(&v->list);
+ kfree(v);
+ }
+
return ret;
}
late_initcall(clock_late_init);
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index d5fe866..76ad9b8 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -206,7 +206,7 @@
}
/* Prevent core memory from collapsing when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
/* Return clocks to their state before this function. */
restore_clocks(fs);
@@ -238,7 +238,7 @@
return rc;
/* Allow core memory to collapse when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN_MEM);
/* Halt all bus ports in the power domain. */
if (fs->bus_port0) {
@@ -292,7 +292,7 @@
err_port2_halt:
msm_bus_axi_portunhalt(fs->bus_port0);
err:
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
restore_clocks(fs);
return rc;
}
@@ -360,7 +360,7 @@
clk_prepare_enable(fs->core_clk);
/* Prevent core memory from collapsing when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
/* Return clocks to their state before this function. */
restore_clocks(fs);
@@ -390,7 +390,7 @@
return rc;
/* Allow core memory to collapse when its clock is gated. */
- clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_NORETAIN_MEM);
/* Halt all bus ports in the power domain. */
if (fs->bus_port0) {
@@ -436,7 +436,7 @@
return 0;
err:
- clk_set_flags(fs->core_clk, CLKFLAG_RETAIN);
+ clk_set_flags(fs->core_clk, CLKFLAG_RETAIN_MEM);
restore_clocks(fs);
return rc;
}
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index e5b9d93..6665d66 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.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
@@ -22,6 +22,8 @@
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
+#include <linux/clk.h>
+#include <mach/clk.h>
#define PWR_ON_MASK BIT(31)
#define EN_REST_WAIT_MASK (0xF << 20)
@@ -42,6 +44,7 @@
struct regulator_dev *rdev;
struct regulator_desc rdesc;
void __iomem *gdscr;
+ struct clk *core_clk;
};
static int gdsc_is_enabled(struct regulator_dev *rdev)
@@ -108,6 +111,7 @@
struct resource *res;
struct gdsc *sc;
uint32_t regval;
+ bool retain_mems;
int ret;
sc = devm_kzalloc(&pdev->dev, sizeof(struct gdsc), GFP_KERNEL);
@@ -151,6 +155,16 @@
regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
writel_relaxed(regval, sc->gdscr);
+ retain_mems = of_property_read_bool(pdev->dev.of_node,
+ "qcom,retain-mems");
+ if (retain_mems) {
+ sc->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(sc->core_clk))
+ return PTR_ERR(sc->core_clk);
+ clk_set_flags(sc->core_clk, CLKFLAG_RETAIN_MEM);
+ clk_set_flags(sc->core_clk, CLKFLAG_RETAIN_PERIPH);
+ }
+
sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
pdev->dev.of_node);
if (IS_ERR(sc->rdev)) {
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 35257b2..72f5051 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -601,6 +601,7 @@
void msm_map_fsm9xxx_io(void);
void msm_map_8974_io(void);
void msm_map_zinc_io(void);
+void msm_map_msmkrypton_io(void);
void msm_map_msm8625_io(void);
void msm_map_msm9625_io(void);
void msm_init_irq(void);
@@ -611,6 +612,7 @@
void msm_8974_init_gpiomux(void);
void msmzinc_init_gpiomux(void);
void msm9625_init_gpiomux(void);
+void msmkrypton_init_gpiomux(void);
void msm_map_mpq8092_io(void);
void mpq8092_init_gpiomux(void);
void msm_map_msm8226_io(void);
diff --git a/arch/arm/mach-msm/include/mach/clk-provider.h b/arch/arm/mach-msm/include/mach/clk-provider.h
index 528e9d5..2a33228 100644
--- a/arch/arm/mach-msm/include/mach/clk-provider.h
+++ b/arch/arm/mach-msm/include/mach/clk-provider.h
@@ -156,6 +156,8 @@
int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
int unvote_vdd_level(struct clk_vdd_class *vdd_class, int level);
+int __clk_pre_reparent(struct clk *c, struct clk *new, unsigned long *flags);
+void __clk_post_reparent(struct clk *c, struct clk *old, unsigned long *flags);
/* Register clocks with the MSM clock driver */
int msm_clock_register(struct clk_lookup *table, size_t size);
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index 1191bb7..1809456 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -16,8 +16,10 @@
#define CLKFLAG_NOINVERT 0x00000002
#define CLKFLAG_NONEST 0x00000004
#define CLKFLAG_NORESET 0x00000008
-#define CLKFLAG_RETAIN 0x00000040
-#define CLKFLAG_NORETAIN 0x00000080
+#define CLKFLAG_RETAIN_PERIPH 0x00000010
+#define CLKFLAG_NORETAIN_PERIPH 0x00000020
+#define CLKFLAG_RETAIN_MEM 0x00000040
+#define CLKFLAG_NORETAIN_MEM 0x00000080
#define CLKFLAG_SKIP_HANDOFF 0x00000100
#define CLKFLAG_MIN 0x00000400
#define CLKFLAG_MAX 0x00000800
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
new file mode 100644
index 0000000..a8b9da5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-krypton.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+#define __ASM_ARCH_MSM_IOMAP_MSMKRYPTON_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSMKRYPTON_SHARED_RAM_PHYS 0x00000000
+
+#define MSMKRYPTON_TLMM_PHYS 0xFD510000
+#define MSMKRYPTON_TLMM_SIZE SZ_16K
+
+#define MSMKRYPTON_MPM2_PSHOLD_PHYS 0xFC4AB000
+#define MSMKRYPTON_MPM2_PSHOLD_SIZE SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index d3706cd..f27eb36 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -134,6 +134,7 @@
#include "msm_iomap-8092.h"
#include "msm_iomap-8226.h"
#include "msm_iomap-8610.h"
+#include "msm_iomap-krypton.h"
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 264dad5..3bf05e6 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -45,9 +45,9 @@
#define MEMTYPE_FLAGS_1M_ALIGN 0x2
struct memtype_reserve {
- unsigned long start;
- unsigned long size;
- unsigned long limit;
+ phys_addr_t start;
+ phys_addr_t size;
+ phys_addr_t limit;
int flags;
};
@@ -55,7 +55,7 @@
struct memtype_reserve *memtype_reserve_table;
void (*calculate_reserve_sizes)(void);
void (*reserve_fixed_area)(unsigned long);
- int (*paddr_to_memtype)(unsigned int);
+ int (*paddr_to_memtype)(phys_addr_t);
unsigned long low_unstable_address;
unsigned long max_unstable_size;
unsigned long bank_size;
diff --git a/arch/arm/mach-msm/ramdump.h b/arch/arm/mach-msm/include/mach/ramdump.h
similarity index 100%
rename from arch/arm/mach-msm/ramdump.h
rename to arch/arm/mach-msm/include/mach/ramdump.h
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index b898fe8..7c9882e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -48,6 +48,8 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
#define early_machine_is_msmzinc() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
+#define early_machine_is_msmkrypton() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmkrypton")
#else
#define of_board_is_sim() 0
#define of_board_is_rumi() 0
@@ -62,6 +64,7 @@
#define early_machine_is_msm8610() 0
#define early_machine_is_mpq8092() 0
#define early_machine_is_msmzinc() 0
+#define early_machine_is_msmkrypton() 0
#endif
#define PLATFORM_SUBTYPE_SGLTE 6
@@ -100,6 +103,7 @@
MSM_CPU_8610,
MSM_CPU_8625Q,
MSM_CPU_ZINC,
+ MSM_CPU_KRYPTON,
};
enum pmic_model {
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 25cbc87..c5ad35d 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -258,6 +258,7 @@
enum sps_callback_case {
SPS_CALLBACK_BAM_ERROR_IRQ = 1, /* BAM ERROR IRQ */
SPS_CALLBACK_BAM_HRESP_ERR_IRQ, /* Erroneous HResponse */
+ SPS_CALLBACK_BAM_TIMER_IRQ, /* Inactivity timer */
};
/*
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 19c7acd..ecac4a5 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -507,6 +507,25 @@
}
#endif /* CONFIG_ARCH_MSM9625 */
+#ifdef CONFIG_ARCH_MSMKRYPTON
+static struct map_desc msmkrypton_io_desc[] __initdata = {
+ MSM_CHIP_DEVICE(TLMM, MSMKRYPTON),
+ MSM_CHIP_DEVICE(MPM2_PSHOLD, MSMKRYPTON),
+ {
+ .virtual = (unsigned long) MSM_SHARED_RAM_BASE,
+ .length = MSM_SHARED_RAM_SIZE,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init msm_map_msmkrypton_io(void)
+{
+ msm_shared_ram_phys = MSMKRYPTON_SHARED_RAM_PHYS;
+ msm_map_io(msmkrypton_io_desc, ARRAY_SIZE(msmkrypton_io_desc));
+ of_scan_flat_dt(msm_scan_dt_map_imem, NULL);
+}
+#endif /* CONFIG_ARCH_MSMKRYPTON */
+
#ifdef CONFIG_ARCH_MPQ8092
static struct map_desc mpq8092_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 953f941d..b931ee6 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -61,9 +61,7 @@
#define PMIC_VOLTAGE_MAX 1355000
#define LV_RANGE_STEP 5000
-#define LOAD_PER_PHASE 3200000
-
-#define CORE_VOLTAGE_MIN 900000
+#define CORE_VOLTAGE_BOOTUP 900000
#define KRAIT_LDO_VOLTAGE_MIN 465000
#define KRAIT_LDO_VOLTAGE_OFFSET 465000
@@ -146,7 +144,10 @@
* regulator's callback functions to prevent
* simultaneous updates to the pmic's phase
* voltage.
- * @apcs_gcc_base virtual address of the APCS GCC registers
+ * @apcs_gcc_base: virtual address of the APCS GCC registers
+ * @manage_phases: begin phase control
+ * @pfm_threshold: the sum of coefficients below which PFM can be
+ * enabled
*/
struct pmic_gang_vreg {
const char *name;
@@ -159,6 +160,8 @@
bool retention_enabled;
bool use_phase_switching;
void __iomem *apcs_gcc_base;
+ bool manage_phases;
+ int pfm_threshold;
};
static struct pmic_gang_vreg *the_gang;
@@ -168,6 +171,9 @@
LDO_MODE = REGULATOR_MODE_IDLE,
};
+#define WAIT_FOR_LOAD 0x2
+#define WAIT_FOR_VOLTAGE 0x1
+
struct krait_power_vreg {
struct list_head link;
struct regulator_desc desc;
@@ -175,7 +181,7 @@
const char *name;
struct pmic_gang_vreg *pvreg;
int uV;
- int load_uA;
+ int load;
enum krait_supply_mode mode;
void __iomem *reg_base;
void __iomem *mdd_base;
@@ -185,7 +191,10 @@
int ldo_threshold_uV;
int ldo_delta_uV;
int cpu_num;
+ int coeff1;
+ int coeff2;
bool online;
+ int online_at_probe;
};
DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -293,6 +302,229 @@
return 0;
}
+#define COEFF2_UV_THRESHOLD 850000
+static int get_coeff2(int krait_uV)
+{
+ int coeff2 = 0;
+ int krait_mV = krait_uV / 1000;
+
+ if (krait_uV <= COEFF2_UV_THRESHOLD)
+ coeff2 = (612229 * krait_mV) / 1000 - 211258;
+ else
+ coeff2 = (892564 * krait_mV) / 1000 - 449543;
+
+ return coeff2;
+}
+
+static int get_coeff1(int actual_uV, int requested_uV, int load)
+{
+ int ratio = actual_uV * 1000 / requested_uV;
+ int coeff1 = 330 * load + (load * 673 * ratio / 1000);
+
+ return coeff1;
+}
+
+static int get_coeff_total(struct krait_power_vreg *from)
+{
+ int coeff_total = 0;
+ struct krait_power_vreg *kvreg;
+ struct pmic_gang_vreg *pvreg = from->pvreg;
+
+ list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+ if (!kvreg->online)
+ continue;
+
+ if (kvreg->mode == LDO_MODE) {
+ kvreg->coeff1 =
+ get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
+ kvreg->uV, kvreg->load);
+ kvreg->coeff2 =
+ get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
+ } else {
+ kvreg->coeff1 =
+ get_coeff1(pvreg->pmic_vmax_uV,
+ kvreg->uV, kvreg->load);
+ kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
+ }
+ coeff_total += kvreg->coeff1 + kvreg->coeff2;
+ }
+
+ return coeff_total;
+}
+
+static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
+{
+ pr_debug("programming phase_count = %d\n", phase_count);
+ if (pvreg->use_phase_switching)
+ /*
+ * note the PMIC sets the phase count to one more than
+ * the value in the register - hence subtract 1 from it
+ */
+ return msm_spm_apcs_set_phase(phase_count - 1);
+ else
+ return 0;
+}
+
+static int num_online(struct pmic_gang_vreg *pvreg)
+{
+ int online_total = 0;
+ struct krait_power_vreg *kvreg;
+
+ list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+ if (kvreg->online)
+ online_total++;
+ }
+ return online_total;
+}
+
+static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
+{
+ struct krait_power_vreg *kvreg;
+
+ list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+ pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
+ kvreg->online_at_probe);
+ if (kvreg->online_at_probe)
+ return false;
+ }
+ return true;
+}
+
+#define PMIC_FTS_MODE_PFM 0x00
+#define PMIC_FTS_MODE_PWM 0x80
+#define ONE_PHASE_COEFF 1000000
+#define TWO_PHASE_COEFF 2000000
+
+#define PHASE_SETTLING_TIME_US 10
+static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
+ int coeff_total)
+{
+ struct pmic_gang_vreg *pvreg = from->pvreg;
+ int phase_count;
+ int rc = 0;
+ int n_online = num_online(pvreg);
+
+ if (pvreg->manage_phases == false) {
+ if (enable_phase_management(pvreg))
+ pvreg->manage_phases = true;
+ else
+ return 0;
+ }
+
+ /* First check if the coeff is low for PFM mode */
+ if (coeff_total < pvreg->pfm_threshold && n_online == 1) {
+ if (!pvreg->pfm_mode) {
+ rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
+ if (rc) {
+ pr_err("%s PFM en failed coeff_t %d rc = %d\n",
+ from->name, coeff_total, rc);
+ return rc;
+ } else {
+ pvreg->pfm_mode = true;
+ }
+ }
+ return rc;
+ }
+
+ /* coeff is high switch to PWM mode before changing phases */
+ if (pvreg->pfm_mode) {
+ rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
+ if (rc) {
+ pr_err("%s PFM exit failed load %d rc = %d\n",
+ from->name, coeff_total, rc);
+ return rc;
+ } else {
+ pvreg->pfm_mode = false;
+ }
+ }
+
+ /* calculate phases */
+ if (coeff_total < ONE_PHASE_COEFF)
+ phase_count = 1;
+ else if (coeff_total < TWO_PHASE_COEFF)
+ phase_count = 2;
+ else
+ phase_count = 4;
+
+ /* don't increase the phase count higher than number of online cpus */
+ if (phase_count > n_online)
+ phase_count = n_online;
+
+ if (phase_count != pvreg->pmic_phase_count) {
+ rc = set_pmic_gang_phases(pvreg, phase_count);
+ if (rc < 0) {
+ pr_err("%s failed set phase %d rc = %d\n",
+ from->name, phase_count, rc);
+ return rc;
+ }
+
+ /* complete the writes before the delay */
+ mb();
+
+ /*
+ * delay until the phases are settled when
+ * the count is raised
+ */
+ if (phase_count > pvreg->pmic_phase_count)
+ udelay(PHASE_SETTLING_TIME_US);
+
+ pvreg->pmic_phase_count = phase_count;
+ }
+
+ return rc;
+}
+
+static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load)
+{
+ struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+ int coeff_total;
+ int rc;
+
+ kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
+ coeff_total = get_coeff_total(kvreg);
+
+ rc = pmic_gang_set_phases(kvreg, coeff_total);
+ if (rc < 0) {
+ dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
+ kvreg->name, coeff_total, rc);
+ }
+
+ return kvreg->mode;
+}
+
+static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
+{
+ struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+ struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+ int rc;
+
+ mutex_lock(&pvreg->krait_power_vregs_lock);
+ kvreg->load = load_uA;
+ if (!kvreg->online) {
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+ return kvreg->mode;
+ }
+
+ rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
+ mutex_unlock(&pvreg->krait_power_vregs_lock);
+
+ return rc;
+}
+
+static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+ return 0;
+}
+
+static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
+{
+ struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+
+ return kvreg->mode;
+}
+
static int switch_to_using_hs(struct krait_power_vreg *kvreg)
{
if (kvreg->mode == HS_MODE)
@@ -368,19 +600,6 @@
return 0;
}
-static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
-{
- pr_debug("programming phase_count = %d\n", phase_count);
- if (pvreg->use_phase_switching)
- /*
- * note the PMIC sets the phase count to one more than
- * the value in the register - hence subtract 1 from it
- */
- return msm_spm_apcs_set_phase(phase_count - 1);
- else
- return 0;
-}
-
static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
{
int setpoint;
@@ -524,46 +743,6 @@
return rc;
}
-#define PHASE_SETTLING_TIME_US 10
-static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
- int load_uA)
-{
- struct pmic_gang_vreg *pvreg = from->pvreg;
- int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE);
- int rc = 0;
-
- if (phase_count <= 0)
- phase_count = 1;
-
- /* Increase phases if it is less than the number of cpus online */
- if (phase_count < num_online_cpus()) {
- phase_count = num_online_cpus();
- }
-
- if (phase_count != pvreg->pmic_phase_count) {
- rc = set_pmic_gang_phases(pvreg, phase_count);
- if (rc < 0) {
- dev_err(&from->rdev->dev,
- "%s failed set phase %d rc = %d\n",
- pvreg->name, phase_count, rc);
- return rc;
- }
-
- /* complete the writes before the delay */
- mb();
-
- /*
- * delay until the phases are settled when
- * the count is raised
- */
- if (phase_count > pvreg->pmic_phase_count)
- udelay(PHASE_SETTLING_TIME_US);
-
- pvreg->pmic_phase_count = phase_count;
- }
- return rc;
-}
-
static int krait_power_get_voltage(struct regulator_dev *rdev)
{
struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -590,21 +769,6 @@
return vmax;
}
-static int get_total_load(struct krait_power_vreg *from)
-{
- int load_total = 0;
- struct krait_power_vreg *kvreg;
- struct pmic_gang_vreg *pvreg = from->pvreg;
-
- list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
- if (!kvreg->online)
- continue;
- load_total += kvreg->load_uA;
- }
-
- return load_total;
-}
-
#define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
static int _set_voltage(struct regulator_dev *rdev,
int orig_krait_uV, int requested_uV)
@@ -613,6 +777,7 @@
struct pmic_gang_vreg *pvreg = kvreg->pvreg;
int rc;
int vmax;
+ int coeff_total;
pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
/*
@@ -636,6 +801,11 @@
kvreg->name, requested_uV, orig_krait_uV, rc);
}
+ kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
+ coeff_total = get_coeff_total(kvreg);
+ /* adjust the phases since coeff2 would have changed */
+ rc = pmic_gang_set_phases(kvreg, coeff_total);
+
return rc;
}
@@ -670,89 +840,6 @@
return rc;
}
-#define PMIC_FTS_MODE_PFM 0x00
-#define PMIC_FTS_MODE_PWM 0x80
-#define PFM_LOAD_UA 500000
-static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
- int input_uV, int output_uV, int load_uA)
-{
- struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
- struct pmic_gang_vreg *pvreg = kvreg->pvreg;
- int rc;
- int load_total_uA;
-
- load_total_uA = get_total_load(kvreg);
-
- if (load_total_uA < PFM_LOAD_UA) {
- if (!pvreg->pfm_mode) {
- rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
- if (rc) {
- dev_err(&rdev->dev,
- "%s enter PFM failed load %d rc = %d\n",
- kvreg->name, load_total_uA, rc);
- goto out;
- } else {
- pvreg->pfm_mode = true;
- }
- }
- return kvreg->mode;
- }
-
- if (pvreg->pfm_mode) {
- rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
- if (rc) {
- dev_err(&rdev->dev,
- "%s exit PFM failed load %d rc = %d\n",
- kvreg->name, load_total_uA, rc);
- goto out;
- } else {
- pvreg->pfm_mode = false;
- }
- }
-
- rc = pmic_gang_set_phases(kvreg, load_total_uA);
- if (rc < 0) {
- dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
- kvreg->name, load_total_uA, rc);
- goto out;
- }
-
-out:
- return kvreg->mode;
-}
-
-static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
- int input_uV, int output_uV, int load_uA)
-{
- struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
- struct pmic_gang_vreg *pvreg = kvreg->pvreg;
- int rc;
-
- mutex_lock(&pvreg->krait_power_vregs_lock);
- kvreg->load_uA = load_uA;
- if (!kvreg->online) {
- mutex_unlock(&pvreg->krait_power_vregs_lock);
- return kvreg->mode;
- }
-
- rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
- mutex_unlock(&pvreg->krait_power_vregs_lock);
-
- return rc;
-}
-
-static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
- return 0;
-}
-
-static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
-{
- struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-
- return kvreg->mode;
-}
-
static int krait_power_is_enabled(struct regulator_dev *rdev)
{
struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -769,7 +856,7 @@
mutex_lock(&pvreg->krait_power_vregs_lock);
__krait_power_mdd_enable(kvreg, true);
kvreg->online = true;
- rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
+ rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
if (rc < 0)
goto en_err;
/*
@@ -791,8 +878,7 @@
mutex_lock(&pvreg->krait_power_vregs_lock);
kvreg->online = false;
- rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
- kvreg->load_uA);
+ rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
if (rc < 0)
goto dis_err;
@@ -851,8 +937,10 @@
DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
+#define CPU_PWR_CTL_ONLINE_MASK 0x80
static void kvreg_hw_init(struct krait_power_vreg *kvreg)
{
+ int online;
/*
* bhs_cnt value sets the ramp-up time from power collapse,
* initialize the ramp up time
@@ -865,6 +953,10 @@
/* Enable MDD */
writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
mb();
+ online = CPU_PWR_CTL_ONLINE_MASK
+ & readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
+ kvreg->online_at_probe
+ = online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
}
static void glb_init(void __iomem *apcs_gcc_base)
@@ -1012,7 +1104,7 @@
kvreg->desc.ops = &krait_power_ops;
kvreg->desc.type = REGULATOR_VOLTAGE;
kvreg->desc.owner = THIS_MODULE;
- kvreg->uV = CORE_VOLTAGE_MIN;
+ kvreg->uV = CORE_VOLTAGE_BOOTUP;
kvreg->mode = HS_MODE;
kvreg->desc.ops = &krait_power_ops;
kvreg->headroom_uV = headroom_uV;
@@ -1111,6 +1203,7 @@
{
int rc;
bool use_phase_switching = false;
+ int pfm_threshold;
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
struct pmic_gang_vreg *pvreg;
@@ -1123,6 +1216,13 @@
use_phase_switching = of_property_read_bool(node,
"qcom,use-phase-switching");
+
+ rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
+ if (rc < 0) {
+ dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
+ return -EINVAL;
+ }
+
pvreg = devm_kzalloc(&pdev->dev,
sizeof(struct pmic_gang_vreg), GFP_KERNEL);
if (!pvreg) {
@@ -1148,6 +1248,7 @@
pvreg->retention_enabled = true;
pvreg->pmic_min_uV_for_retention = INT_MAX;
pvreg->use_phase_switching = use_phase_switching;
+ pvreg->pfm_threshold = pfm_threshold;
mutex_init(&pvreg->krait_power_vregs_lock);
INIT_LIST_HEAD(&pvreg->krait_power_vregs);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index d71787c..5f85ee9 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -152,8 +152,8 @@
if (mt->flags & MEMTYPE_FLAGS_1M_ALIGN)
mt->size = (mt->size + SECTION_SIZE - 1) & SECTION_MASK;
if (mt->size > mt->limit) {
- pr_warning("%lx size for %s too large, setting to %lx\n",
- mt->size, memtype_name[i], mt->limit);
+ pr_warning("%pa size for %s too large, setting to %pa\n",
+ &mt->size, memtype_name[i], &mt->limit);
mt->size = mt->limit;
}
}
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index 09f784d..fcd7cef 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -70,9 +70,6 @@
#define MSM_MPM_IRQ_INDEX(irq) (irq / 32)
#define MSM_MPM_IRQ_MASK(irq) BIT(irq % 32)
-#define MSM_MPM_DETECT_CTL_INDEX(irq) (irq / 16)
-#define MSM_MPM_DETECT_CTL_SHIFT(irq) ((irq % 16) * 2)
-
#define hashfn(val) (val % MSM_MPM_NR_MPM_IRQS)
#define SCLK_HZ (32768)
#define ARCH_TIMER_HZ (19200000)
@@ -81,8 +78,8 @@
enum mpm_reg_offsets {
MSM_MPM_REG_WAKEUP,
MSM_MPM_REG_ENABLE,
- MSM_MPM_REG_DETECT_CTL,
- MSM_MPM_REG_DETECT_CTL1,
+ MSM_MPM_REG_FALLING_EDGE,
+ MSM_MPM_REG_RISING_EDGE,
MSM_MPM_REG_POLARITY,
MSM_MPM_REG_STATUS,
};
@@ -91,7 +88,8 @@
static uint32_t msm_mpm_enabled_irq[MSM_MPM_REG_WIDTH];
static uint32_t msm_mpm_wake_irq[MSM_MPM_REG_WIDTH];
-static uint32_t msm_mpm_detect_ctl[MSM_MPM_REG_WIDTH * 2];
+static uint32_t msm_mpm_falling_edge[MSM_MPM_REG_WIDTH];
+static uint32_t msm_mpm_rising_edge[MSM_MPM_REG_WIDTH];
static uint32_t msm_mpm_polarity[MSM_MPM_REG_WIDTH];
enum {
@@ -174,11 +172,11 @@
reg = MSM_MPM_REG_ENABLE;
msm_mpm_write(reg, i, irqs[i]);
- reg = MSM_MPM_REG_DETECT_CTL;
- msm_mpm_write(reg, i, msm_mpm_detect_ctl[i]);
+ reg = MSM_MPM_REG_FALLING_EDGE;
+ msm_mpm_write(reg, i, msm_mpm_falling_edge[i]);
- reg = MSM_MPM_REG_DETECT_CTL1;
- msm_mpm_write(reg, i, msm_mpm_detect_ctl[2+i]);
+ reg = MSM_MPM_REG_RISING_EDGE;
+ msm_mpm_write(reg, i, msm_mpm_rising_edge[i]);
reg = MSM_MPM_REG_POLARITY;
msm_mpm_write(reg, i, msm_mpm_polarity[i]);
@@ -264,23 +262,24 @@
return 0;
}
-static void msm_mpm_set_detect_ctl(int pin, unsigned int flow_type)
+static void msm_mpm_set_edge_ctl(int pin, unsigned int flow_type)
{
uint32_t index;
- uint32_t val = 0;
- uint32_t shift;
+ uint32_t mask;
- index = MSM_MPM_DETECT_CTL_INDEX(pin);
- shift = MSM_MPM_DETECT_CTL_SHIFT(pin);
-
- if (flow_type & IRQ_TYPE_EDGE_RISING)
- val |= 0x02;
+ index = MSM_MPM_IRQ_INDEX(pin);
+ mask = MSM_MPM_IRQ_MASK(pin);
if (flow_type & IRQ_TYPE_EDGE_FALLING)
- val |= 0x01;
+ msm_mpm_falling_edge[index] |= mask;
+ else
+ msm_mpm_falling_edge[index] &= ~mask;
- msm_mpm_detect_ctl[index] &= ~(0x3 << shift);
- msm_mpm_detect_ctl[index] |= (val & 0x03) << shift;
+ if (flow_type & IRQ_TYPE_EDGE_RISING)
+ msm_mpm_rising_edge[index] |= mask;
+ else
+ msm_mpm_rising_edge[index] &= ~mask;
+
}
static int msm_mpm_set_irq_type_exclusive(
@@ -300,7 +299,7 @@
if (index >= MSM_MPM_REG_WIDTH)
return -EFAULT;
- msm_mpm_set_detect_ctl(mpm_irq, flow_type);
+ msm_mpm_set_edge_ctl(mpm_irq, flow_type);
if (flow_type & IRQ_TYPE_LEVEL_HIGH)
msm_mpm_polarity[index] |= mask;
@@ -429,7 +428,7 @@
spin_lock_irqsave(&msm_mpm_lock, flags);
- msm_mpm_set_detect_ctl(pin, flow_type);
+ msm_mpm_set_edge_ctl(pin, flow_type);
if (flow_type & IRQ_TYPE_LEVEL_HIGH)
msm_mpm_polarity[index] |= mask;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index b9a553a..af3537c 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -79,9 +79,10 @@
}
pdata->num_usecases = num_usecases;
- ret = of_property_read_u32(of_node, "qcom,msm-bus,active-only",
- &pdata->active_only);
- if (ret) {
+
+ if (of_property_read_bool(of_node, "qcom,msm-bus,active-only"))
+ pdata->active_only = 1;
+ else {
pr_debug("active_only flag absent.\n");
pr_debug("Using dual context by default\n");
}
diff --git a/arch/arm/mach-msm/msm_dsps.c b/arch/arm/mach-msm/msm_dsps.c
index db67f7d..0ada902 100644
--- a/arch/arm/mach-msm/msm_dsps.c
+++ b/arch/arm/mach-msm/msm_dsps.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
@@ -36,8 +36,8 @@
#include <mach/msm_smsm.h>
#include <mach/msm_dsps.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
-#include "ramdump.h"
#include "timer.h"
#define DRV_NAME "msm_dsps"
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 4e8674c..056da7d 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -36,9 +36,9 @@
#include <asm-generic/io-64-nonatomic-lo-hi.h>
#include <mach/msm_iomap.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
-#include "ramdump.h"
#define pil_err(desc, fmt, ...) \
dev_err(desc->dev, "%s: " fmt, desc->name, ##__VA_ARGS__)
@@ -335,6 +335,14 @@
unsigned int mask;
size_t size = max_addr - min_addr;
+ /* Don't reallocate due to fragmentation concerns, just sanity check */
+ if (priv->region) {
+ if (WARN(priv->region_end - priv->region_start < size,
+ "Can't reuse PIL memory, too small\n"))
+ return -ENOMEM;
+ return 0;
+ }
+
if (!ion) {
WARN_ON_ONCE("No ION client, can't support relocation\n");
return -ENOMEM;
@@ -471,9 +479,6 @@
writeq(0, &priv->info->start);
writel_relaxed(0, &priv->info->size);
- if (priv->region)
- ion_free(ion, priv->region);
- priv->region = NULL;
list_for_each_entry_safe(p, tmp, &priv->segs, list) {
list_del(&p->list);
kfree(p);
@@ -661,8 +666,13 @@
release_firmware(fw);
out:
up_read(&pil_pm_rwsem);
- if (ret)
+ if (ret) {
+ if (priv->region) {
+ ion_free(ion, priv->region);
+ priv->region = NULL;
+ }
pil_release_mmap(desc);
+ }
return ret;
}
EXPORT_SYMBOL(pil_boot);
diff --git a/arch/arm/mach-msm/pil-dsps.c b/arch/arm/mach-msm/pil-dsps.c
index 65d60d6..df5ea35 100644
--- a/arch/arm/mach-msm/pil-dsps.c
+++ b/arch/arm/mach-msm/pil-dsps.c
@@ -21,10 +21,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define PPSS_RESET 0x2594
#define PPSS_RESET_PROC_RESET 0x2
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index c9e2e0d..d44add6 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.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
@@ -29,11 +29,11 @@
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
#include "smd_private.h"
-#include "ramdump.h"
#define GSS_CSR_AHB_CLK_SEL 0x0
#define GSS_CSR_RESET 0x4
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index e95fae8..30f480a 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.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
@@ -24,11 +24,11 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "modem_notifier.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define MARM_BOOT_CONTROL 0x0010
#define MARM_RESET 0x2BD4
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index edaa60c..0df8739 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -29,10 +29,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#define PRONTO_PMU_COMMON_GDSCR 0x24
#define PRONTO_PMU_COMMON_GDSCR_SW_COLLAPSE BIT(0)
@@ -410,6 +410,15 @@
int ret, err_fatal_gpio, irq;
uint32_t regval;
+ int clk_ready = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-proxy-unvote", 0);
+ if (clk_ready < 0)
+ return clk_ready;
+
+ clk_ready = gpio_to_irq(clk_ready);
+ if (clk_ready < 0)
+ return clk_ready;
+
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -460,6 +469,7 @@
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
+ desc->proxy_unvote_irq = clk_ready;
if (pas_supported(PAS_WCNSS) > 0) {
desc->ops = &pil_pronto_ops_trusted;
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 66adc2b..0575a3d 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.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
@@ -23,8 +23,8 @@
#include <mach/subsystem_restart.h>
#include <mach/scm.h>
+#include <mach/ramdump.h>
-#include "ramdump.h"
#include "peripheral-loader.h"
#include "scm-pas.h"
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
index 1387433..f05bcdb 100644
--- a/arch/arm/mach-msm/pil-q6v4-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.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
@@ -24,9 +24,9 @@
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
+#include <mach/ramdump.h>
#include "smd_private.h"
-#include "ramdump.h"
#include "sysmon.h"
#include "peripheral-loader.h"
#include "pil-q6v4.h"
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
index f2b090f..1821ab1 100644
--- a/arch/arm/mach-msm/pil-q6v4-mss.c
+++ b/arch/arm/mach-msm/pil-q6v4-mss.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
@@ -22,9 +22,9 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "smd_private.h"
-#include "ramdump.h"
#include "peripheral-loader.h"
#include "pil-q6v4.h"
#include "scm-pas.h"
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 72253fd..3b2bbf3 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -27,11 +27,11 @@
#include <mach/subsystem_restart.h>
#include <mach/subsystem_notif.h>
#include <mach/scm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
#include "scm-pas.h"
-#include "ramdump.h"
#include "sysmon.h"
#define QDSP6SS_RST_EVB 0x010
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index cfd8daf..8f7d262 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -30,10 +30,10 @@
#include <mach/subsystem_restart.h>
#include <mach/clk.h>
#include <mach/msm_smsm.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
-#include "ramdump.h"
#include "sysmon.h"
/* Q6 Register Offsets */
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 33301de..a2665b4 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.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
@@ -23,10 +23,10 @@
#include <linux/wcnss_wlan.h>
#include <mach/subsystem_restart.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
#include "smd_private.h"
#define RIVA_PMU_A2XB_CFG 0xB8
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index b0150d4..4e9e54b 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -30,10 +30,10 @@
#include <mach/subsystem_restart.h>
#include <mach/msm_bus_board.h>
#include <mach/msm_bus.h>
+#include <mach/ramdump.h>
#include "peripheral-loader.h"
#include "scm-pas.h"
-#include "ramdump.h"
/* VENUS WRAPPER registers */
#define VENUS_WRAPPER_HW_VERSION 0x0
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 3c50bc6..cd1eaaf 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -1229,18 +1229,11 @@
},
};
-static int __devinit msm_pm_init(void)
+static int __init msm_pm_setup_saved_state(void)
{
pgd_t *pc_pgd;
pmd_t *pmd;
unsigned long pmdval;
- enum msm_pm_time_stats_id enable_stats[] = {
- MSM_PM_STAT_IDLE_WFI,
- MSM_PM_STAT_RETENTION,
- MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
- MSM_PM_STAT_IDLE_POWER_COLLAPSE,
- MSM_PM_STAT_SUSPEND,
- };
unsigned long exit_phys;
/* Page table for cores to come back up safely. */
@@ -1280,6 +1273,19 @@
clean_caches((unsigned long)&msm_pm_pc_pgd, sizeof(msm_pm_pc_pgd),
virt_to_phys(&msm_pm_pc_pgd));
+ return 0;
+}
+core_initcall(msm_pm_setup_saved_state);
+
+static int __init msm_pm_init(void)
+{
+ enum msm_pm_time_stats_id enable_stats[] = {
+ MSM_PM_STAT_IDLE_WFI,
+ MSM_PM_STAT_RETENTION,
+ MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
+ MSM_PM_STAT_IDLE_POWER_COLLAPSE,
+ MSM_PM_STAT_SUSPEND,
+ };
msm_pm_mode_sysfs_add();
msm_pm_add_stats(enable_stats, ARRAY_SIZE(enable_stats));
suspend_set_ops(&msm_pm_ops);
diff --git a/arch/arm/mach-msm/pm-data.c b/arch/arm/mach-msm/pm-data.c
index ccc2519..249032f 100644
--- a/arch/arm/mach-msm/pm-data.c
+++ b/arch/arm/mach-msm/pm-data.c
@@ -46,7 +46,7 @@
.idle_supported = 0,
.suspend_supported = 1,
.idle_enabled = 0,
- .suspend_enabled = 0,
+ .suspend_enabled = 1,
},
[MSM_PM_MODE(1, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
@@ -74,7 +74,7 @@
.idle_supported = 0,
.suspend_supported = 1,
.idle_enabled = 0,
- .suspend_enabled = 0,
+ .suspend_enabled = 1,
},
[MSM_PM_MODE(2, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
@@ -102,7 +102,7 @@
.idle_supported = 0,
.suspend_supported = 1,
.idle_enabled = 0,
- .suspend_enabled = 0,
+ .suspend_enabled = 1,
},
[MSM_PM_MODE(3, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)] = {
diff --git a/arch/arm/mach-msm/ramdump.c b/arch/arm/mach-msm/ramdump.c
index 7f09a56..be21025 100644
--- a/arch/arm/mach-msm/ramdump.c
+++ b/arch/arm/mach-msm/ramdump.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
@@ -25,7 +25,7 @@
#include <linux/elf.h>
#include <linux/wait.h>
-#include "ramdump.h"
+#include <mach/ramdump.h>
#define RAMDUMP_WAIT_MSECS 120000
diff --git a/arch/arm/mach-msm/rpm_stats.c b/arch/arm/mach-msm/rpm_stats.c
index 176c3de..cb8ed19 100644
--- a/arch/arm/mach-msm/rpm_stats.c
+++ b/arch/arm/mach-msm/rpm_stats.c
@@ -63,6 +63,8 @@
u32 count;
u64 last_entered_at;
u64 last_exited_at;
+ u64 accumulated;
+ u32 reserved[4];
};
static inline u64 get_time_in_sec(u64 counter)
@@ -84,6 +86,7 @@
char stat_type[5];
u64 time_in_last_mode;
u64 time_since_last_mode;
+ u64 actual_last_sleep;
stat_type[4] = 0;
memcpy(stat_type, &data->stat_type, sizeof(u32));
@@ -92,12 +95,13 @@
time_in_last_mode = get_time_in_msec(time_in_last_mode);
time_since_last_mode = arch_counter_get_cntpct() - data->last_exited_at;
time_since_last_mode = get_time_in_sec(time_since_last_mode);
+ actual_last_sleep = get_time_in_msec(data->accumulated);
return snprintf(buf , buflength,
"RPM Mode:%s\n\t count:%d\n time in last mode(msec):%llu\n"
- "time since last mode(sec):%llu\n",
+ "time since last mode(sec):%llu\n actual last sleep(msec):%llu\n",
stat_type, data->count, time_in_last_mode,
- time_since_last_mode);
+ time_since_last_mode, actual_last_sleep);
}
static inline u32 msm_rpmstats_read_long_register_v2(void __iomem *regbase,
@@ -140,6 +144,9 @@
i, offsetof(struct msm_rpm_stats_data_v2,
last_exited_at));
+ data.accumulated = msm_rpmstats_read_quad_register_v2(reg,
+ i, offsetof(struct msm_rpm_stats_data_v2,
+ accumulated));
length += msm_rpmstats_append_data_to_buf(prvdata->buf + length,
&data, sizeof(prvdata->buf) - length);
prvdata->read_idx++;
diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c
index f1a7185..f48b538 100644
--- a/arch/arm/mach-msm/scm-pas.c
+++ b/arch/arm/mach-msm/scm-pas.c
@@ -262,7 +262,7 @@
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()) {
+ if (cpu_is_msm8974() || cpu_is_msm8226() || cpu_is_msm8610()) {
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 {
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 40ef20e..8a9042e 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -38,6 +38,7 @@
#include <linux/suspend.h>
#include <linux/of.h>
#include <linux/of_irq.h>
+
#include <mach/msm_smd.h>
#include <mach/msm_iomap.h>
#include <mach/system.h>
@@ -45,11 +46,12 @@
#include <mach/socinfo.h>
#include <mach/proc_comm.h>
#include <mach/msm_ipc_logging.h>
+#include <mach/ramdump.h>
+
#include <asm/cacheflush.h>
#include "smd_private.h"
#include "modem_notifier.h"
-#include "ramdump.h"
#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
|| defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 169df1e..361df33 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.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
@@ -33,6 +33,8 @@
#include <mach/msm_iomap.h>
#include <mach/smem_log.h>
+#include <asm/arch_timer.h>
+
#include "smd_private.h"
#include "smd_rpc_sym.h"
#include "modem_notifier.h"
@@ -652,13 +654,7 @@
#else
static inline unsigned int read_timestamp(void)
{
- unsigned long long val;
-
- /* SMEM LOG uses a 32.768KHz timestamp */
- val = sched_clock() * 32768U;
- do_div(val, 1000000000U);
-
- return (unsigned int)val;
+ return (unsigned int)(arch_counter_get_cntpct());
}
#endif
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 5158f8e..83f7a1d 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -351,6 +351,9 @@
/* zinc IDs */
[178] = MSM_CPU_ZINC,
+ /* krypton IDs */
+ [187] = MSM_CPU_KRYPTON,
+
/* Uninitialized IDs are not known to run Linux.
MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
considered as unknown CPU. */
@@ -854,6 +857,10 @@
dummy_socinfo.id = 178;
strlcpy(dummy_socinfo.build_id, "msmzinc - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msmkrypton()) {
+ dummy_socinfo.id = 187;
+ strlcpy(dummy_socinfo.build_id, "msmkrypton - ",
+ sizeof(dummy_socinfo.build_id));
}
strlcat(dummy_socinfo.build_id, "Dummy socinfo",
sizeof(dummy_socinfo.build_id));
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
index cccca26..95a85f26 100644
--- a/arch/arm/mach-msm/wdog_debug.c
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -24,7 +24,7 @@
ret = scm_call_atomic2(SCM_SVC_BOOT,
SCM_WDOG_DEBUG_BOOT_PART, 0, BOOT_PART_EN_VAL);
if (ret)
- pr_err("failed to enable wdog debug\n");
+ pr_err("failed to enable wdog debug: %d\n", ret);
}
EXPORT_SYMBOL(msm_enable_wdog_debug);
@@ -35,6 +35,6 @@
ret = scm_call_atomic2(SCM_SVC_BOOT,
SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
if (ret)
- pr_err("failed to disable wdog debug\n");
+ pr_err("failed to disable wdog debug: %d\n", ret);
}
EXPORT_SYMBOL(msm_disable_wdog_debug);
diff --git a/block/row-iosched.c b/block/row-iosched.c
index 3baec8c..c8ba344 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -158,6 +158,20 @@
};
/**
+ * struct starvation_data - data for starvation management
+ * @starvation_limit: number of times this priority class
+ * can tolerate being starved
+ * @starvation_counter: number of requests from higher
+ * priority classes that were dispatched while this
+ * priority request were pending
+ *
+ */
+struct starvation_data {
+ int starvation_limit;
+ int starvation_counter;
+};
+
+/**
* struct row_queue - Per block device rqueue structure
* @dispatch_queue: dispatch rqueue
* @row_queues: array of priority request queues
@@ -170,6 +184,8 @@
* complete.
* @pending_urgent_rq: pointer to the pending urgent request
* @last_served_ioprio_class: I/O priority class that was last dispatched from
+ * @reg_prio_starvation: starvation data for REGULAR priority queues
+ * @low_prio_starvation: starvation data for LOW priority queues
* @cycle_flags: used for marking unserved queueus
*
*/
@@ -183,6 +199,12 @@
bool urgent_in_flight;
struct request *pending_urgent_rq;
int last_served_ioprio_class;
+
+#define ROW_REG_STARVATION_TOLLERANCE 50
+ struct starvation_data reg_prio_starvation;
+#define ROW_LOW_STARVATION_TOLLERANCE 1000
+ struct starvation_data low_prio_starvation;
+
unsigned int cycle_flags;
};
@@ -258,6 +280,42 @@
return HRTIMER_NORESTART;
}
+/*
+ * row_regular_req_pending() - Check if there are REGULAR priority requests
+ * Pending in scheduler
+ * @rd: pointer to struct row_data
+ *
+ * Returns True if there are REGULAR priority requests in scheduler queues.
+ * False, otherwise.
+ */
+static inline bool row_regular_req_pending(struct row_data *rd)
+{
+ int i;
+
+ for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++)
+ if (!list_empty(&rd->row_queues[i].fifo))
+ return true;
+ return false;
+}
+
+/*
+ * row_low_req_pending() - Check if there are LOW priority requests
+ * Pending in scheduler
+ * @rd: pointer to struct row_data
+ *
+ * Returns True if there are LOW priority requests in scheduler queues.
+ * False, otherwise.
+ */
+static inline bool row_low_req_pending(struct row_data *rd)
+{
+ int i;
+
+ for (i = ROWQ_LOW_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
+ if (!list_empty(&rd->row_queues[i].fifo))
+ return true;
+ return false;
+}
+
/******************* Elevator callback functions *********************/
/*
@@ -272,6 +330,7 @@
struct row_data *rd = (struct row_data *)q->elevator->elevator_data;
struct row_queue *rqueue = RQ_ROWQ(rq);
s64 diff_ms;
+ bool queue_was_empty = list_empty(&rqueue->fifo);
list_add_tail(&rq->queuelist, &rqueue->fifo);
rd->nr_reqs[rq_data_dir(rq)]++;
@@ -316,7 +375,8 @@
!rd->pending_urgent_rq && !rd->urgent_in_flight) {
/* Handle High Priority queues */
if (rqueue->prio < ROWQ_REG_PRIO_IDX &&
- rd->last_served_ioprio_class != IOPRIO_CLASS_RT) {
+ rd->last_served_ioprio_class != IOPRIO_CLASS_RT &&
+ queue_was_empty) {
row_log_rowq(rd, rqueue->prio,
"added (high prio) urgent request");
rq->cmd_flags |= REQ_URGENT;
@@ -472,12 +532,21 @@
row_log_rowq(rd, rqueue->prio,
" Dispatched request %p nr_disp = %d", rq,
rqueue->nr_dispatched);
- if (rqueue->prio < ROWQ_REG_PRIO_IDX)
+ if (rqueue->prio < ROWQ_REG_PRIO_IDX) {
rd->last_served_ioprio_class = IOPRIO_CLASS_RT;
- else if (rqueue->prio < ROWQ_LOW_PRIO_IDX)
+ if (row_regular_req_pending(rd))
+ rd->reg_prio_starvation.starvation_counter++;
+ if (row_low_req_pending(rd))
+ rd->low_prio_starvation.starvation_counter++;
+ } else if (rqueue->prio < ROWQ_LOW_PRIO_IDX) {
rd->last_served_ioprio_class = IOPRIO_CLASS_BE;
- else
+ rd->reg_prio_starvation.starvation_counter = 0;
+ if (row_low_req_pending(rd))
+ rd->low_prio_starvation.starvation_counter++;
+ } else {
rd->last_served_ioprio_class = IOPRIO_CLASS_IDLE;
+ rd->low_prio_starvation.starvation_counter = 0;
+ }
}
/*
@@ -517,7 +586,18 @@
rd->rd_idle_data.idling_queue_idx =
ROWQ_MAX_PRIO;
}
- ret = IOPRIO_CLASS_RT;
+
+ if (row_regular_req_pending(rd) &&
+ (rd->reg_prio_starvation.starvation_counter >=
+ rd->reg_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_BE;
+ else if (row_low_req_pending(rd) &&
+ (rd->low_prio_starvation.starvation_counter >=
+ rd->low_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_IDLE;
+ else
+ ret = IOPRIO_CLASS_RT;
+
goto done;
}
}
@@ -546,7 +626,12 @@
!force && row_queues_def[i].idling_enabled)
goto initiate_idling;
} else {
- ret = IOPRIO_CLASS_BE;
+ if (row_low_req_pending(rd) &&
+ (rd->low_prio_starvation.starvation_counter >=
+ rd->low_prio_starvation.starvation_limit))
+ ret = IOPRIO_CLASS_IDLE;
+ else
+ ret = IOPRIO_CLASS_BE;
goto done;
}
}
@@ -716,6 +801,10 @@
ktime_set(0, 0);
}
+ rdata->reg_prio_starvation.starvation_limit =
+ ROW_REG_STARVATION_TOLLERANCE;
+ rdata->low_prio_starvation.starvation_limit =
+ ROW_LOW_STARVATION_TOLLERANCE;
/*
* Currently idling is enabled only for READ queues. If we want to
* enable it for write queues also, note that idling frequency will
@@ -865,42 +954,42 @@
return count;
}
-#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \
+#define SHOW_FUNCTION(__FUNC, __VAR) \
static ssize_t __FUNC(struct elevator_queue *e, char *page) \
{ \
struct row_data *rowd = e->elevator_data; \
int __data = __VAR; \
- if (__CONV) \
- __data = jiffies_to_msecs(__data); \
return row_var_show(__data, (page)); \
}
SHOW_FUNCTION(row_hp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum);
SHOW_FUNCTION(row_rp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum);
SHOW_FUNCTION(row_hp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum);
SHOW_FUNCTION(row_rp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum);
SHOW_FUNCTION(row_rp_write_quantum_show,
- rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum);
SHOW_FUNCTION(row_lp_read_quantum_show,
- rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, 0);
+ rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum);
SHOW_FUNCTION(row_lp_swrite_quantum_show,
- rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, 0);
-SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms, 0);
-SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms, 0);
+ rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum);
+SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms);
+SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms);
+SHOW_FUNCTION(row_reg_starv_limit_show,
+ rowd->reg_prio_starvation.starvation_limit);
+SHOW_FUNCTION(row_low_starv_limit_show,
+ rowd->low_prio_starvation.starvation_limit);
#undef SHOW_FUNCTION
-#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
static ssize_t __FUNC(struct elevator_queue *e, \
const char *page, size_t count) \
{ \
struct row_data *rowd = e->elevator_data; \
int __data; \
int ret = row_var_store(&__data, (page), count); \
- if (__CONV) \
- __data = (int)msecs_to_jiffies(__data); \
if (__data < (MIN)) \
__data = (MIN); \
else if (__data > (MAX)) \
@@ -909,29 +998,35 @@
return ret; \
}
STORE_FUNCTION(row_hp_read_quantum_store,
-&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX, 0);
+&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX);
STORE_FUNCTION(row_rp_read_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_hp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rp_write_quantum_store,
&rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_lp_read_quantum_store,
&rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_lp_swrite_quantum_store,
&rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms,
- 1, INT_MAX, 0);
+ 1, INT_MAX);
+STORE_FUNCTION(row_reg_starv_limit_store,
+ &rowd->reg_prio_starvation.starvation_limit,
+ 1, INT_MAX);
+STORE_FUNCTION(row_low_starv_limit_store,
+ &rowd->low_prio_starvation.starvation_limit,
+ 1, INT_MAX);
#undef STORE_FUNCTION
@@ -949,6 +1044,8 @@
ROW_ATTR(lp_swrite_quantum),
ROW_ATTR(rd_idle_data),
ROW_ATTR(rd_idle_data_freq),
+ ROW_ATTR(reg_starv_limit),
+ ROW_ATTR(low_starv_limit),
__ATTR_NULL
};
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 2440404..8cc42df 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1530,6 +1530,45 @@
}
+static int qcedev_check_cipher_key(struct qcedev_cipher_op_req *req,
+ struct qcedev_control *podev)
+{
+ /* if intending to use HW key make sure key fields are set
+ * correctly and HW key is indeed supported in target
+ */
+ if (req->encklen == 0) {
+ int i;
+ for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
+ if (req->enckey[i])
+ goto error;
+ if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
+ (req->op != QCEDEV_OPER_DEC_NO_KEY))
+ if (!podev->platform_support.hw_key_support)
+ goto error;
+ } else {
+ if (req->encklen == QCEDEV_AES_KEY_192) {
+ if (!podev->ce_support.aes_key_192)
+ goto error;
+ } else {
+ /* if not using HW key make sure key
+ * length is valid
+ */
+ if ((req->mode == QCEDEV_AES_MODE_XTS)) {
+ if (!((req->encklen == QCEDEV_AES_KEY_128*2) ||
+ (req->encklen == QCEDEV_AES_KEY_256*2)))
+ goto error;
+ } else {
+ if (!((req->encklen == QCEDEV_AES_KEY_128) ||
+ (req->encklen == QCEDEV_AES_KEY_256)))
+ goto error;
+ }
+ }
+ }
+ return 0;
+error:
+ return -EINVAL;
+}
+
static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
struct qcedev_control *podev)
{
@@ -1542,36 +1581,13 @@
if ((req->alg >= QCEDEV_ALG_LAST) ||
(req->mode >= QCEDEV_AES_DES_MODE_LAST))
goto error;
- if (req->alg == QCEDEV_ALG_AES) {
- if ((req->mode == QCEDEV_AES_MODE_XTS) &&
- (!podev->ce_support.aes_xts))
- goto error;
- /* if intending to use HW key make sure key fields are set
- * correctly and HW key is indeed supported in target
- */
- if (req->encklen == 0) {
- int i;
- for (i = 0; i < QCEDEV_MAX_KEY_SIZE; i++)
- if (req->enckey[i])
+
+ if ((req->mode == QCEDEV_AES_MODE_XTS) && (!podev->ce_support.aes_xts))
goto error;
- if ((req->op != QCEDEV_OPER_ENC_NO_KEY) &&
- (req->op != QCEDEV_OPER_DEC_NO_KEY))
- if (!podev->platform_support.hw_key_support)
+
+ if (req->alg == QCEDEV_ALG_AES)
+ if (qcedev_check_cipher_key(req, podev))
goto error;
- } else {
- if (req->encklen == QCEDEV_AES_KEY_192) {
- if (!podev->ce_support.aes_key_192)
- goto error;
- } else {
- /* if not using HW key make sure key
- * length is valid
- */
- if (!((req->encklen == QCEDEV_AES_KEY_128) ||
- (req->encklen == QCEDEV_AES_KEY_256)))
- goto error;
- }
- }
- }
/* if using a byteoffset, make sure it is CTR mode using vbuf */
if (req->byteoffset) {
if (req->mode != QCEDEV_AES_MODE_CTR)
@@ -1607,6 +1623,11 @@
if (req->alg >= QCEDEV_ALG_SHA_ALG_LAST)
goto sha_error;
+ if ((req->alg == QCEDEV_ALG_SHA1_HMAC) ||
+ (req->alg == QCEDEV_ALG_SHA1_HMAC)) {
+ if (req->authklen == 0)
+ goto sha_error;
+ }
return 0;
sha_error:
return -EINVAL;
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 05ef87c..85c25c7 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -677,12 +677,10 @@
return 0;
};
-static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
- unsigned int len)
+
+static int _qcrypto_check_aes_keylen(struct crypto_ablkcipher *cipher,
+ struct crypto_priv *cp, unsigned int len)
{
- struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
- struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
- struct crypto_priv *cp = ctx->cp;
switch (len) {
case AES_KEYSIZE_128:
@@ -695,8 +693,40 @@
crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
return -EINVAL;
};
- ctx->enc_key_len = len;
- memcpy(ctx->enc_key, key, len);
+
+ return 0;
+}
+
+static int _qcrypto_setkey_aes(struct crypto_ablkcipher *cipher, const u8 *key,
+ unsigned int len)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_priv *cp = ctx->cp;
+
+ if (_qcrypto_check_aes_keylen(cipher, cp, len)) {
+ return -EINVAL;
+ } else {
+ ctx->enc_key_len = len;
+ memcpy(ctx->enc_key, key, len);
+ }
+ return 0;
+};
+
+static int _qcrypto_setkey_aes_xts(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int len)
+{
+ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+ struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_priv *cp = ctx->cp;
+
+
+ if (_qcrypto_check_aes_keylen(cipher, cp, len/2)) {
+ return -EINVAL;
+ } else {
+ ctx->enc_key_len = len;
+ memcpy(ctx->enc_key, key, len);
+ }
return 0;
};
@@ -3124,7 +3154,7 @@
.ivsize = AES_BLOCK_SIZE,
.min_keysize = AES_MIN_KEY_SIZE,
.max_keysize = AES_MAX_KEY_SIZE,
- .setkey = _qcrypto_setkey_aes,
+ .setkey = _qcrypto_setkey_aes_xts,
.encrypt = _qcrypto_enc_aes_xts,
.decrypt = _qcrypto_dec_aes_xts,
},
diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile
index 60a6b81..f4f9a92 100644
--- a/drivers/gpu/ion/Makefile
+++ b/drivers/gpu/ion/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o
+obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o ion_removed_heap.o
obj-$(CONFIG_CMA) += ion_cma_heap.o ion_cma_secure_heap.o
obj-$(CONFIG_ION_TEGRA) += tegra/
obj-$(CONFIG_ION_MSM) += msm/
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index d3434d8..a01ef3f 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -112,8 +112,6 @@
!(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC));
}
-static void ion_iommu_release(struct kref *kref);
-
/* this function should only be called while dev->lock is held */
static void ion_buffer_add(struct ion_device *dev,
struct ion_buffer *buffer)
@@ -140,61 +138,6 @@
rb_insert_color(&buffer->node, &dev->buffers);
}
-static void ion_iommu_add(struct ion_buffer *buffer,
- struct ion_iommu_map *iommu)
-{
- struct rb_node **p = &buffer->iommu_maps.rb_node;
- struct rb_node *parent = NULL;
- struct ion_iommu_map *entry;
-
- while (*p) {
- parent = *p;
- entry = rb_entry(parent, struct ion_iommu_map, node);
-
- if (iommu->key < entry->key) {
- p = &(*p)->rb_left;
- } else if (iommu->key > entry->key) {
- p = &(*p)->rb_right;
- } else {
- pr_err("%s: buffer %p already has mapping for domain %d"
- " and partition %d\n", __func__,
- buffer,
- iommu_map_domain(iommu),
- iommu_map_partition(iommu));
- BUG();
- }
- }
-
- rb_link_node(&iommu->node, parent, p);
- rb_insert_color(&iommu->node, &buffer->iommu_maps);
-
-}
-
-static struct ion_iommu_map *ion_iommu_lookup(struct ion_buffer *buffer,
- unsigned int domain_no,
- unsigned int partition_no)
-{
- struct rb_node **p = &buffer->iommu_maps.rb_node;
- struct rb_node *parent = NULL;
- struct ion_iommu_map *entry;
- uint64_t key = domain_no;
- key = key << 32 | partition_no;
-
- while (*p) {
- parent = *p;
- entry = rb_entry(parent, struct ion_iommu_map, node);
-
- if (key < entry->key)
- p = &(*p)->rb_left;
- else if (key > entry->key)
- p = &(*p)->rb_right;
- else
- return entry;
- }
-
- return NULL;
-}
-
static int ion_buffer_alloc_dirty(struct ion_buffer *buffer);
/* this function should only be called while dev->lock is held */
@@ -275,38 +218,6 @@
return ERR_PTR(ret);
}
-/**
- * Check for delayed IOMMU unmapping. Also unmap any outstanding
- * mappings which would otherwise have been leaked.
- */
-static void ion_iommu_delayed_unmap(struct ion_buffer *buffer)
-{
- struct ion_iommu_map *iommu_map;
- struct rb_node *node;
- const struct rb_root *rb = &(buffer->iommu_maps);
- unsigned long ref_count;
- unsigned int delayed_unmap;
-
- mutex_lock(&buffer->lock);
-
- while ((node = rb_first(rb)) != 0) {
- iommu_map = rb_entry(node, struct ion_iommu_map, node);
- ref_count = atomic_read(&iommu_map->ref.refcount);
- delayed_unmap = iommu_map->flags & ION_IOMMU_UNMAP_DELAYED;
-
- if ((delayed_unmap && ref_count > 1) || !delayed_unmap) {
- pr_err("%s: Virtual memory address leak in domain %u, partition %u\n",
- __func__, iommu_map->domain_info[DI_DOMAIN_NUM],
- iommu_map->domain_info[DI_PARTITION_NUM]);
- }
- /* set ref count to 1 to force release */
- kref_init(&iommu_map->ref);
- kref_put(&iommu_map->ref, ion_iommu_release);
- }
-
- mutex_unlock(&buffer->lock);
-}
-
static void ion_delayed_unsecure(struct ion_buffer *buffer)
{
if (buffer->heap->ops->unsecure_buffer)
@@ -323,7 +234,6 @@
buffer->heap->ops->unmap_dma(buffer->heap, buffer);
ion_delayed_unsecure(buffer);
- ion_iommu_delayed_unmap(buffer);
buffer->heap->ops->free(buffer);
mutex_lock(&dev->lock);
rb_erase(&buffer->node, &dev->buffers);
@@ -654,212 +564,6 @@
ion_buffer_kmap_put(buffer);
}
-static struct ion_iommu_map *__ion_iommu_map(struct ion_buffer *buffer,
- int domain_num, int partition_num, unsigned long align,
- unsigned long iova_length, unsigned long flags,
- unsigned long *iova)
-{
- struct ion_iommu_map *data;
- int ret;
-
- data = kmalloc(sizeof(*data), GFP_ATOMIC);
-
- if (!data)
- return ERR_PTR(-ENOMEM);
-
- data->buffer = buffer;
- iommu_map_domain(data) = domain_num;
- iommu_map_partition(data) = partition_num;
-
- ret = buffer->heap->ops->map_iommu(buffer, data,
- domain_num,
- partition_num,
- align,
- iova_length,
- flags);
-
- if (ret)
- goto out;
-
- kref_init(&data->ref);
- *iova = data->iova_addr;
-
- ion_iommu_add(buffer, data);
-
- return data;
-
-out:
- kfree(data);
- return ERR_PTR(ret);
-}
-
-int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
- int domain_num, int partition_num, unsigned long align,
- unsigned long iova_length, unsigned long *iova,
- unsigned long *buffer_size,
- unsigned long flags, unsigned long iommu_flags)
-{
- struct ion_buffer *buffer;
- struct ion_iommu_map *iommu_map;
- int ret = 0;
-
- if (IS_ERR_OR_NULL(client)) {
- pr_err("%s: client pointer is invalid\n", __func__);
- return -EINVAL;
- }
- if (IS_ERR_OR_NULL(handle)) {
- pr_err("%s: handle pointer is invalid\n", __func__);
- return -EINVAL;
- }
- if (IS_ERR_OR_NULL(handle->buffer)) {
- pr_err("%s: buffer pointer is invalid\n", __func__);
- return -EINVAL;
- }
-
- if (ION_IS_CACHED(flags)) {
- pr_err("%s: Cannot map iommu as cached.\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&client->lock);
- if (!ion_handle_validate(client, handle)) {
- pr_err("%s: invalid handle passed to map_kernel.\n",
- __func__);
- mutex_unlock(&client->lock);
- return -EINVAL;
- }
-
- buffer = handle->buffer;
- mutex_lock(&buffer->lock);
-
- if (!handle->buffer->heap->ops->map_iommu) {
- pr_err("%s: map_iommu is not implemented by this heap.\n",
- __func__);
- ret = -ENODEV;
- goto out;
- }
-
- /*
- * If clients don't want a custom iova length, just use whatever
- * the buffer size is
- */
- if (!iova_length)
- iova_length = buffer->size;
-
- if (buffer->size > iova_length) {
- pr_debug("%s: iova length %lx is not at least buffer size"
- " %x\n", __func__, iova_length, buffer->size);
- ret = -EINVAL;
- goto out;
- }
-
- if (buffer->size & ~PAGE_MASK) {
- pr_debug("%s: buffer size %x is not aligned to %lx", __func__,
- buffer->size, PAGE_SIZE);
- ret = -EINVAL;
- goto out;
- }
-
- if (iova_length & ~PAGE_MASK) {
- pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
- iova_length, PAGE_SIZE);
- ret = -EINVAL;
- goto out;
- }
-
- iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
- if (!iommu_map) {
- iommu_map = __ion_iommu_map(buffer, domain_num, partition_num,
- align, iova_length, flags, iova);
- if (!IS_ERR_OR_NULL(iommu_map)) {
- iommu_map->flags = iommu_flags;
-
- if (iommu_map->flags & ION_IOMMU_UNMAP_DELAYED)
- kref_get(&iommu_map->ref);
- } else {
- ret = PTR_ERR(iommu_map);
- }
- } else {
- if (iommu_map->flags != iommu_flags) {
- pr_err("%s: handle %p is already mapped with iommu flags %lx, trying to map with flags %lx\n",
- __func__, handle,
- iommu_map->flags, iommu_flags);
- ret = -EINVAL;
- } else if (iommu_map->mapped_size != iova_length) {
- pr_err("%s: handle %p is already mapped with length"
- " %x, trying to map with length %lx\n",
- __func__, handle, iommu_map->mapped_size,
- iova_length);
- ret = -EINVAL;
- } else {
- kref_get(&iommu_map->ref);
- *iova = iommu_map->iova_addr;
- }
- }
- if (!ret)
- buffer->iommu_map_cnt++;
- *buffer_size = buffer->size;
-out:
- mutex_unlock(&buffer->lock);
- mutex_unlock(&client->lock);
- return ret;
-}
-EXPORT_SYMBOL(ion_map_iommu);
-
-static void ion_iommu_release(struct kref *kref)
-{
- struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
- ref);
- struct ion_buffer *buffer = map->buffer;
-
- rb_erase(&map->node, &buffer->iommu_maps);
- buffer->heap->ops->unmap_iommu(map);
- kfree(map);
-}
-
-void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
- int domain_num, int partition_num)
-{
- struct ion_iommu_map *iommu_map;
- struct ion_buffer *buffer;
-
- if (IS_ERR_OR_NULL(client)) {
- pr_err("%s: client pointer is invalid\n", __func__);
- return;
- }
- if (IS_ERR_OR_NULL(handle)) {
- pr_err("%s: handle pointer is invalid\n", __func__);
- return;
- }
- if (IS_ERR_OR_NULL(handle->buffer)) {
- pr_err("%s: buffer pointer is invalid\n", __func__);
- return;
- }
-
- mutex_lock(&client->lock);
- buffer = handle->buffer;
-
- mutex_lock(&buffer->lock);
-
- iommu_map = ion_iommu_lookup(buffer, domain_num, partition_num);
-
- if (!iommu_map) {
- WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
- domain_num, partition_num, buffer);
- goto out;
- }
-
- kref_put(&iommu_map->ref, ion_iommu_release);
-
- buffer->iommu_map_cnt--;
-out:
- mutex_unlock(&buffer->lock);
-
- mutex_unlock(&client->lock);
-
-}
-EXPORT_SYMBOL(ion_unmap_iommu);
-
void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle)
{
struct ion_buffer *buffer;
@@ -903,52 +607,10 @@
}
EXPORT_SYMBOL(ion_unmap_kernel);
-int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
- void *uaddr, unsigned long offset, unsigned long len,
- unsigned int cmd)
-{
- struct ion_buffer *buffer;
- int ret = -EINVAL;
-
- mutex_lock(&client->lock);
- if (!ion_handle_validate(client, handle)) {
- pr_err("%s: invalid handle passed to do_cache_op.\n",
- __func__);
- mutex_unlock(&client->lock);
- return -EINVAL;
- }
- buffer = handle->buffer;
- mutex_lock(&buffer->lock);
-
- if (!ION_IS_CACHED(buffer->flags)) {
- ret = 0;
- goto out;
- }
-
- if (!handle->buffer->heap->ops->cache_op) {
- pr_err("%s: cache_op is not implemented by this heap.\n",
- __func__);
- ret = -ENODEV;
- goto out;
- }
-
-
- ret = buffer->heap->ops->cache_op(buffer->heap, buffer, uaddr,
- offset, len, cmd);
-
-out:
- mutex_unlock(&buffer->lock);
- mutex_unlock(&client->lock);
- return ret;
-
-}
-EXPORT_SYMBOL(ion_do_cache_op);
-
static int ion_debug_client_show(struct seq_file *s, void *unused)
{
struct ion_client *client = s->private;
struct rb_node *n;
- struct rb_node *n2;
seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s : %12.12s : %s\n",
"heap_name", "size_in_bytes", "handle refcount",
@@ -973,15 +635,6 @@
else
seq_printf(s, " : %12s", "N/A");
- for (n2 = rb_first(&handle->buffer->iommu_maps); n2;
- n2 = rb_next(n2)) {
- struct ion_iommu_map *imap =
- rb_entry(n2, struct ion_iommu_map, node);
- seq_printf(s, " : [%d,%d] - %8lx",
- imap->domain_info[DI_DOMAIN_NUM],
- imap->domain_info[DI_PARTITION_NUM],
- imap->iova_addr);
- }
seq_printf(s, "\n");
}
mutex_unlock(&client->lock);
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 9610dfe..0dd3054 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -24,11 +24,9 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/iommu.h>
#include <linux/seq_file.h>
#include "ion_priv.h"
-#include <mach/iommu_domains.h>
#include <asm/mach/map.h>
#include <asm/cacheflush.h>
#include <linux/msm_ion.h>
@@ -39,10 +37,6 @@
ion_phys_addr_t base;
unsigned long allocated_bytes;
unsigned long total_size;
- int (*request_region)(void *);
- int (*release_region)(void *);
- atomic_t map_count;
- void *bus_id;
unsigned int has_outer_cache;
};
@@ -130,79 +124,33 @@
buffer->sg_table = 0;
}
-static int ion_carveout_request_region(struct ion_carveout_heap *carveout_heap)
-{
- int ret_value = 0;
- if (atomic_inc_return(&carveout_heap->map_count) == 1) {
- if (carveout_heap->request_region) {
- ret_value = carveout_heap->request_region(
- carveout_heap->bus_id);
- if (ret_value) {
- pr_err("Unable to request SMI region");
- atomic_dec(&carveout_heap->map_count);
- }
- }
- }
- return ret_value;
-}
-
-static int ion_carveout_release_region(struct ion_carveout_heap *carveout_heap)
-{
- int ret_value = 0;
- if (atomic_dec_and_test(&carveout_heap->map_count)) {
- if (carveout_heap->release_region) {
- ret_value = carveout_heap->release_region(
- carveout_heap->bus_id);
- if (ret_value)
- pr_err("Unable to release SMI region");
- }
- }
- return ret_value;
-}
-
void *ion_carveout_heap_map_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
void *ret_value;
- if (ion_carveout_request_region(carveout_heap))
- return NULL;
-
if (ION_IS_CACHED(buffer->flags))
ret_value = ioremap_cached(buffer->priv_phys, buffer->size);
else
ret_value = ioremap(buffer->priv_phys, buffer->size);
- if (!ret_value)
- ion_carveout_release_region(carveout_heap);
return ret_value;
}
void ion_carveout_heap_unmap_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
-
__arm_iounmap(buffer->vaddr);
buffer->vaddr = NULL;
- ion_carveout_release_region(carveout_heap);
return;
}
int ion_carveout_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma)
{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
int ret_value = 0;
- if (ion_carveout_request_region(carveout_heap))
- return -EINVAL;
-
if (!ION_IS_CACHED(buffer->flags))
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -211,104 +159,9 @@
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
- if (ret_value)
- ion_carveout_release_region(carveout_heap);
return ret_value;
}
-void ion_carveout_heap_unmap_user(struct ion_heap *heap,
- struct ion_buffer *buffer)
-{
- struct ion_carveout_heap *carveout_heap =
- container_of(heap, struct ion_carveout_heap, heap);
- ion_carveout_release_region(carveout_heap);
-}
-
-int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
- void *vaddr, unsigned int offset, unsigned int length,
- unsigned int cmd)
-{
- 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;
-
- 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) {
- unsigned long pstart = buffer->priv_phys + offset;
- outer_cache_op(pstart, pstart + length);
- }
- return 0;
-}
-
static int ion_carveout_print_debug(struct ion_heap *heap, struct seq_file *s,
const struct rb_root *mem_map)
{
@@ -363,124 +216,16 @@
return 0;
}
-int ion_carveout_heap_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- struct iommu_domain *domain;
- int ret = 0;
- unsigned long extra;
- struct scatterlist *sglist = 0;
- int prot = IOMMU_WRITE | IOMMU_READ;
- prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
- data->mapped_size = iova_length;
-
- if (!msm_use_iommu()) {
- data->iova_addr = buffer->priv_phys;
- return 0;
- }
-
- extra = iova_length - buffer->size;
-
- ret = msm_allocate_iova_address(domain_num, partition_num,
- data->mapped_size, align,
- &data->iova_addr);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -ENOMEM;
- goto out1;
- }
-
- sglist = vmalloc(sizeof(*sglist));
- if (!sglist)
- goto out1;
-
- sg_init_table(sglist, 1);
- sglist->length = buffer->size;
- sglist->offset = 0;
- sglist->dma_address = buffer->priv_phys;
-
- ret = iommu_map_range(domain, data->iova_addr, sglist,
- buffer->size, prot);
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- if (extra) {
- unsigned long extra_iova_addr = data->iova_addr + buffer->size;
- unsigned long phys_addr = sg_phys(sglist);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- vfree(sglist);
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- vfree(sglist);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
-out:
-
- return ret;
-}
-
-void ion_carveout_heap_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
-
- if (!msm_use_iommu())
- return;
-
- domain_num = iommu_map_domain(data);
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
static struct ion_heap_ops carveout_heap_ops = {
.allocate = ion_carveout_heap_allocate,
.free = ion_carveout_heap_free,
.phys = ion_carveout_heap_phys,
.map_user = ion_carveout_heap_map_user,
.map_kernel = ion_carveout_heap_map_kernel,
- .unmap_user = ion_carveout_heap_unmap_user,
.unmap_kernel = ion_carveout_heap_unmap_kernel,
.map_dma = ion_carveout_heap_map_dma,
.unmap_dma = ion_carveout_heap_unmap_dma,
- .cache_op = ion_carveout_cache_ops,
.print_debug = ion_carveout_print_debug,
- .map_iommu = ion_carveout_heap_map_iommu,
- .unmap_iommu = ion_carveout_heap_unmap_iommu,
};
struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
@@ -511,19 +256,6 @@
carveout_heap->total_size = heap_data->size;
carveout_heap->has_outer_cache = heap_data->has_outer_cache;
- if (heap_data->extra_data) {
- struct ion_co_heap_pdata *extra_data =
- heap_data->extra_data;
-
- if (extra_data->setup_region)
- carveout_heap->bus_id = extra_data->setup_region();
- if (extra_data->request_region)
- carveout_heap->request_region =
- extra_data->request_region;
- if (extra_data->release_region)
- carveout_heap->release_region =
- extra_data->release_region;
- }
return &carveout_heap->heap;
}
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c
index 4f12e38..f64ad4d 100644
--- a/drivers/gpu/ion/ion_cma_heap.c
+++ b/drivers/gpu/ion/ion_cma_heap.c
@@ -178,148 +178,6 @@
return;
}
-int ion_cma_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- int ret = 0;
- struct iommu_domain *domain;
- unsigned long extra;
- unsigned long extra_iova_addr;
- struct ion_cma_buffer_info *info = buffer->priv_virt;
- struct sg_table *table = info->table;
- int prot = IOMMU_WRITE | IOMMU_READ;
-
- data->mapped_size = iova_length;
-
- if (!msm_use_iommu()) {
- data->iova_addr = info->handle;
- return 0;
- }
-
- extra = iova_length - buffer->size;
-
- ret = msm_allocate_iova_address(domain_num, partition_num,
- data->mapped_size, align,
- &data->iova_addr);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -EINVAL;
- goto out1;
- }
-
- ret = iommu_map_range(domain, data->iova_addr, table->sgl,
- buffer->size, prot);
-
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- extra_iova_addr = data->iova_addr + buffer->size;
- if (extra) {
- unsigned long phys_addr = sg_phys(table->sgl);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-out:
- return ret;
-}
-
-
-void ion_cma_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
-
- if (!msm_use_iommu())
- return;
-
- domain_num = iommu_map_domain(data);
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
-int ion_cma_cache_ops(struct ion_heap *heap,
- struct ion_buffer *buffer, void *vaddr,
- 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:
- 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:
- 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:
- 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:
- return -EINVAL;
- }
-
- if (cma_heap_has_outer_cache) {
- struct ion_cma_buffer_info *info = buffer->priv_virt;
-
- outer_cache_op(info->handle, info->handle + length);
- }
-
- return 0;
-}
-
static int ion_cma_print_debug(struct ion_heap *heap, struct seq_file *s,
const struct rb_root *mem_map)
{
@@ -358,9 +216,6 @@
.map_user = ion_cma_mmap,
.map_kernel = ion_cma_map_kernel,
.unmap_kernel = ion_cma_unmap_kernel,
- .map_iommu = ion_cma_map_iommu,
- .unmap_iommu = ion_cma_unmap_iommu,
- .cache_op = ion_cma_cache_ops,
.print_debug = ion_cma_print_debug,
};
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index 0fbcfbf..d622a51 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -44,7 +44,6 @@
bool is_cached;
};
-static int cma_heap_has_outer_cache;
/*
* Create scatter-list for the already allocated DMA buffer.
* This function could be replace by dma_common_get_sgtable
@@ -212,110 +211,6 @@
return;
}
-int ion_secure_cma_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- int ret = 0;
- struct iommu_domain *domain;
- unsigned long extra;
- unsigned long extra_iova_addr;
- struct ion_secure_cma_buffer_info *info = buffer->priv_virt;
- struct sg_table *table = info->table;
- int prot = IOMMU_WRITE | IOMMU_READ;
-
- data->mapped_size = iova_length;
-
- if (!msm_use_iommu()) {
- data->iova_addr = info->handle;
- return 0;
- }
-
- extra = iova_length - buffer->size;
-
- ret = msm_allocate_iova_address(domain_num, partition_num,
- data->mapped_size, align,
- &data->iova_addr);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -EINVAL;
- goto out1;
- }
-
- ret = iommu_map_range(domain, data->iova_addr, table->sgl,
- buffer->size, prot);
-
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- extra_iova_addr = data->iova_addr + buffer->size;
- if (extra) {
- unsigned long phys_addr = sg_phys(table->sgl);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-out:
- return ret;
-}
-
-
-void ion_secure_cma_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
-
- if (!msm_use_iommu())
- return;
-
- domain_num = iommu_map_domain(data);
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
-int ion_secure_cma_cache_ops(struct ion_heap *heap,
- struct ion_buffer *buffer, void *vaddr,
- unsigned int offset, unsigned int length,
- unsigned int cmd)
-{
- 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,
const struct rb_root *mem_map)
{
@@ -354,9 +249,6 @@
.map_user = ion_secure_cma_mmap,
.map_kernel = ion_secure_cma_map_kernel,
.unmap_kernel = ion_secure_cma_unmap_kernel,
- .map_iommu = ion_secure_cma_map_iommu,
- .unmap_iommu = ion_secure_cma_unmap_iommu,
- .cache_op = ion_secure_cma_cache_ops,
.print_debug = ion_secure_cma_print_debug,
.secure_buffer = ion_cp_secure_buffer,
.unsecure_buffer = ion_cp_unsecure_buffer,
@@ -376,7 +268,6 @@
* used to make the link with reserved CMA memory */
heap->priv = data->priv;
heap->type = ION_HEAP_TYPE_SECURE_DMA;
- cma_heap_has_outer_cache = data->has_outer_cache;
return heap;
}
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 88addab..f1868a8 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -67,10 +67,6 @@
* kernel space (un-cached).
* @umap_count: the total number of times this heap has been mapped in
* user space.
- * @iommu_iova: saved iova when mapping full heap at once.
- * @iommu_partition: partition used to map full heap.
- * @iommu_map_all: Indicates whether we should map whole heap into IOMMU.
- * @iommu_2x_map_domain: Indicates the domain to use for overmapping.
* @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
*/
struct ion_cp_heap {
@@ -90,11 +86,6 @@
unsigned long kmap_cached_count;
unsigned long kmap_uncached_count;
unsigned long umap_count;
- unsigned long iommu_iova[MAX_DOMAINS];
- unsigned long iommu_partition[MAX_DOMAINS];
- void *reserved_vrange;
- int iommu_map_all;
- int iommu_2x_map_domain;
unsigned int has_outer_cache;
atomic_t protect_cnt;
void *cpu_addr;
@@ -361,29 +352,6 @@
return offset;
}
-static void iommu_unmap_all(unsigned long domain_num,
- struct ion_cp_heap *cp_heap)
-{
- unsigned long left_to_unmap = cp_heap->total_size;
- unsigned long page_size = SZ_64K;
-
- struct iommu_domain *domain = msm_get_iommu_domain(domain_num);
- if (domain) {
- unsigned long temp_iova = cp_heap->iommu_iova[domain_num];
-
- while (left_to_unmap) {
- iommu_unmap(domain, temp_iova, page_size);
- temp_iova += page_size;
- left_to_unmap -= page_size;
- }
- if (domain_num == cp_heap->iommu_2x_map_domain)
- msm_iommu_unmap_extra(domain, temp_iova,
- cp_heap->total_size, SZ_64K);
- } else {
- pr_err("Unable to get IOMMU domain %lu\n", domain_num);
- }
-}
-
void ion_cp_free(struct ion_heap *heap, ion_phys_addr_t addr,
unsigned long size)
{
@@ -401,25 +369,6 @@
cp_heap->heap_protected == HEAP_NOT_PROTECTED)
ion_on_last_free(heap);
- /* Unmap everything if we previously mapped the whole heap at once. */
- if (!cp_heap->allocated_bytes) {
- unsigned int i;
- for (i = 0; i < MAX_DOMAINS; ++i) {
- if (cp_heap->iommu_iova[i]) {
- unsigned long vaddr_len = cp_heap->total_size;
-
- if (i == cp_heap->iommu_2x_map_domain)
- vaddr_len <<= 1;
- iommu_unmap_all(i, cp_heap);
-
- msm_free_iova_address(cp_heap->iommu_iova[i], i,
- cp_heap->iommu_partition[i],
- vaddr_len);
- }
- cp_heap->iommu_iova[i] = 0;
- cp_heap->iommu_partition[i] = 0;
- }
- }
mutex_unlock(&cp_heap->lock);
}
@@ -674,91 +623,6 @@
mutex_unlock(&cp_heap->lock);
}
-int ion_cp_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
- void *vaddr, unsigned int offset, unsigned int length,
- unsigned int cmd)
-{
- 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);
- 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;
-
- 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) {
- unsigned long pstart = buf->buffer + offset;
- outer_cache_op(pstart, pstart + length);
- }
- return 0;
-}
-
static int ion_cp_print_debug(struct ion_heap *heap, struct seq_file *s,
const struct rb_root *mem_map)
{
@@ -859,205 +723,6 @@
return ret_value;
}
-static int iommu_map_all(unsigned long domain_num, struct ion_cp_heap *cp_heap,
- int partition, unsigned long prot)
-{
- unsigned long left_to_map = cp_heap->total_size;
- unsigned long page_size = SZ_64K;
- int ret_value = 0;
- unsigned long virt_addr_len = cp_heap->total_size;
- struct iommu_domain *domain = msm_get_iommu_domain(domain_num);
-
- /* If we are mapping into the video domain we need to map twice the
- * size of the heap to account for prefetch issue in video core.
- */
- if (domain_num == cp_heap->iommu_2x_map_domain)
- virt_addr_len <<= 1;
-
- if (cp_heap->total_size & (SZ_64K-1)) {
- pr_err("Heap size is not aligned to 64K, cannot map into IOMMU\n");
- ret_value = -EINVAL;
- }
- if (cp_heap->base & (SZ_64K-1)) {
- pr_err("Heap physical address is not aligned to 64K, cannot map into IOMMU\n");
- ret_value = -EINVAL;
- }
- if (!ret_value && domain) {
- unsigned long temp_phys = cp_heap->base;
- unsigned long temp_iova;
-
- ret_value = msm_allocate_iova_address(domain_num, partition,
- virt_addr_len, SZ_64K,
- &temp_iova);
-
- if (ret_value) {
- pr_err("%s: could not allocate iova from domain %lu, partition %d\n",
- __func__, domain_num, partition);
- goto out;
- }
- cp_heap->iommu_iova[domain_num] = temp_iova;
-
- while (left_to_map) {
- int ret = iommu_map(domain, temp_iova, temp_phys,
- page_size, prot);
- if (ret) {
- pr_err("%s: could not map %lx in domain %p, error: %d\n",
- __func__, temp_iova, domain, ret);
- ret_value = -EAGAIN;
- goto free_iova;
- }
- temp_iova += page_size;
- temp_phys += page_size;
- left_to_map -= page_size;
- }
- if (domain_num == cp_heap->iommu_2x_map_domain)
- ret_value = msm_iommu_map_extra(domain, temp_iova,
- cp_heap->base,
- cp_heap->total_size,
- SZ_64K, prot);
- if (ret_value)
- goto free_iova;
- } else {
- pr_err("Unable to get IOMMU domain %lu\n", domain_num);
- ret_value = -ENOMEM;
- }
- goto out;
-
-free_iova:
- msm_free_iova_address(cp_heap->iommu_iova[domain_num], domain_num,
- partition, virt_addr_len);
-out:
- return ret_value;
-}
-
-static int ion_cp_heap_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- struct iommu_domain *domain;
- int ret = 0;
- unsigned long extra;
- struct ion_cp_heap *cp_heap =
- container_of(buffer->heap, struct ion_cp_heap, heap);
- int prot = IOMMU_WRITE | IOMMU_READ;
- struct ion_cp_buffer *buf = buffer->priv_virt;
- prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
- data->mapped_size = iova_length;
-
- if (!msm_use_iommu()) {
- data->iova_addr = buf->buffer;
- return 0;
- }
-
- if (cp_heap->iommu_iova[domain_num]) {
- /* Already mapped. */
- unsigned long offset = buf->buffer - cp_heap->base;
- data->iova_addr = cp_heap->iommu_iova[domain_num] + offset;
- return 0;
- } else if (cp_heap->iommu_map_all) {
- ret = iommu_map_all(domain_num, cp_heap, partition_num, prot);
- if (!ret) {
- unsigned long offset =
- buf->buffer - cp_heap->base;
- data->iova_addr =
- cp_heap->iommu_iova[domain_num] + offset;
- cp_heap->iommu_partition[domain_num] = partition_num;
- /*
- clear delayed map flag so that we don't interfere
- with this feature (we are already delaying).
- */
- data->flags &= ~ION_IOMMU_UNMAP_DELAYED;
- return 0;
- } else {
- cp_heap->iommu_iova[domain_num] = 0;
- cp_heap->iommu_partition[domain_num] = 0;
- return ret;
- }
- }
-
- extra = iova_length - buffer->size;
-
- ret = msm_allocate_iova_address(domain_num, partition_num,
- data->mapped_size, align,
- &data->iova_addr);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -ENOMEM;
- goto out1;
- }
-
- ret = iommu_map_range(domain, data->iova_addr, buffer->sg_table->sgl,
- buffer->size, prot);
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- if (extra) {
- unsigned long extra_iova_addr = data->iova_addr + buffer->size;
- unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-out:
- return ret;
-}
-
-static void ion_cp_heap_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
- struct ion_cp_heap *cp_heap =
- container_of(data->buffer->heap, struct ion_cp_heap, heap);
-
- if (!msm_use_iommu())
- return;
-
-
- domain_num = iommu_map_domain(data);
-
- /* If we are mapping everything we'll wait to unmap until everything
- is freed. */
- if (cp_heap->iommu_iova[domain_num])
- return;
-
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
static struct ion_heap_ops cp_heap_ops = {
.allocate = ion_cp_heap_allocate,
.free = ion_cp_heap_free,
@@ -1068,12 +733,9 @@
.unmap_kernel = ion_cp_heap_unmap_kernel,
.map_dma = ion_cp_heap_map_dma,
.unmap_dma = ion_cp_heap_unmap_dma,
- .cache_op = ion_cp_cache_ops,
.print_debug = ion_cp_print_debug,
.secure_heap = ion_cp_secure_heap,
.unsecure_heap = ion_cp_unsecure_heap,
- .map_iommu = ion_cp_heap_map_iommu,
- .unmap_iommu = ion_cp_heap_unmap_iommu,
.secure_buffer = ion_cp_secure_buffer,
.unsecure_buffer = ion_cp_unsecure_buffer,
};
@@ -1120,10 +782,6 @@
if (extra_data->release_region)
cp_heap->heap_release_region =
extra_data->release_region;
- cp_heap->iommu_map_all =
- extra_data->iommu_map_all;
- cp_heap->iommu_2x_map_domain =
- extra_data->iommu_2x_map_domain;
cp_heap->cma = extra_data->is_cma;
cp_heap->allow_non_secure_allocation =
extra_data->allow_nonsecure_alloc;
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 512ebf3..ca29016 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -30,7 +30,6 @@
struct ion_iommu_heap {
struct ion_heap heap;
- unsigned int has_outer_cache;
};
/*
@@ -315,157 +314,6 @@
return 0;
}
-int ion_iommu_heap_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- struct iommu_domain *domain;
- int ret = 0;
- unsigned long extra;
- int prot = IOMMU_WRITE | IOMMU_READ;
- prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
- BUG_ON(!msm_use_iommu());
-
- 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);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -ENOMEM;
- goto out1;
- }
-
- ret = iommu_map_range(domain, data->iova_addr,
- buffer->sg_table->sgl,
- buffer->size, prot);
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- if (extra) {
- unsigned long extra_iova_addr = data->iova_addr + buffer->size;
- unsigned long phys_addr = sg_phys(buffer->sg_table->sgl);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- buffer->size);
-
-out:
-
- return ret;
-}
-
-void ion_iommu_heap_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
-
- BUG_ON(!msm_use_iommu());
-
- domain_num = iommu_map_domain(data);
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
-static int ion_iommu_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
- void *vaddr, unsigned int offset, unsigned int length,
- unsigned int cmd)
-{
- void (*outer_cache_op)(phys_addr_t, phys_addr_t);
- struct ion_iommu_heap *iommu_heap =
- container_of(heap, struct ion_iommu_heap, heap);
-
- switch (cmd) {
- case ION_IOC_CLEAN_CACHES:
- 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:
- 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:
- 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:
- return -EINVAL;
- }
-
- if (iommu_heap->has_outer_cache) {
- unsigned long pstart;
- unsigned int i;
- struct ion_iommu_priv_data *data = buffer->priv_virt;
- if (!data)
- return -ENOMEM;
-
- for (i = 0; i < data->nrpages; ++i) {
- pstart = page_to_phys(data->pages[i]);
- outer_cache_op(pstart, pstart + PAGE_SIZE);
- }
- }
- return 0;
-}
-
static struct sg_table *ion_iommu_heap_map_dma(struct ion_heap *heap,
struct ion_buffer *buffer)
{
@@ -483,9 +331,6 @@
.map_user = ion_iommu_heap_map_user,
.map_kernel = ion_iommu_heap_map_kernel,
.unmap_kernel = ion_iommu_heap_unmap_kernel,
- .map_iommu = ion_iommu_heap_map_iommu,
- .unmap_iommu = ion_iommu_heap_unmap_iommu,
- .cache_op = ion_iommu_cache_ops,
.map_dma = ion_iommu_heap_map_dma,
.unmap_dma = ion_iommu_heap_unmap_dma,
};
@@ -500,7 +345,6 @@
iommu_heap->heap.ops = &iommu_heap_ops;
iommu_heap->heap.type = ION_HEAP_TYPE_IOMMU;
- iommu_heap->has_outer_cache = heap_data->has_outer_cache;
return &iommu_heap->heap;
}
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 8d45f9d..71527ae 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -65,8 +65,6 @@
struct sg_table *sg_table;
unsigned long *dirty;
struct list_head vmas;
- unsigned int iommu_map_cnt;
- struct rb_root iommu_maps;
int marked;
};
@@ -98,17 +96,6 @@
int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer,
struct vm_area_struct *vma);
void (*unmap_user) (struct ion_heap *mapper, struct ion_buffer *buffer);
- int (*cache_op)(struct ion_heap *heap, struct ion_buffer *buffer,
- void *vaddr, unsigned int offset,
- unsigned int length, unsigned int cmd);
- int (*map_iommu)(struct ion_buffer *buffer,
- struct ion_iommu_map *map_data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags);
- void (*unmap_iommu)(struct ion_iommu_map *data);
int (*print_debug)(struct ion_heap *heap, struct seq_file *s,
const struct rb_root *mem_map);
int (*secure_heap)(struct ion_heap *heap, int version, void *data);
diff --git a/drivers/gpu/ion/ion_removed_heap.c b/drivers/gpu/ion/ion_removed_heap.c
new file mode 100644
index 0000000..84d8d37
--- /dev/null
+++ b/drivers/gpu/ion/ion_removed_heap.c
@@ -0,0 +1,353 @@
+/*
+ * drivers/gpu/ion/ion_removed_heap.c
+ *
+ * Copyright (C) 2011 Google, Inc.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/spinlock.h>
+
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/ion.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/seq_file.h>
+#include "ion_priv.h"
+
+#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
+#include <linux/msm_ion.h>
+
+struct ion_removed_heap {
+ struct ion_heap heap;
+ struct gen_pool *pool;
+ ion_phys_addr_t base;
+ unsigned long allocated_bytes;
+ unsigned long total_size;
+ int (*request_region)(void *);
+ int (*release_region)(void *);
+ atomic_t map_count;
+ void *bus_id;
+};
+
+ion_phys_addr_t ion_removed_allocate(struct ion_heap *heap,
+ unsigned long size,
+ unsigned long align)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ unsigned long offset = gen_pool_alloc_aligned(removed_heap->pool,
+ size, ilog2(align));
+
+ if (!offset) {
+ if ((removed_heap->total_size -
+ removed_heap->allocated_bytes) >= size)
+ pr_debug("%s: heap %s has enough memory (%lx) but the allocation of size %lx still failed. Memory is probably fragmented.",
+ __func__, heap->name,
+ removed_heap->total_size -
+ removed_heap->allocated_bytes, size);
+ return ION_CARVEOUT_ALLOCATE_FAIL;
+ }
+
+ removed_heap->allocated_bytes += size;
+ return offset;
+}
+
+void ion_removed_free(struct ion_heap *heap, ion_phys_addr_t addr,
+ unsigned long size)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ if (addr == ION_CARVEOUT_ALLOCATE_FAIL)
+ return;
+ gen_pool_free(removed_heap->pool, addr, size);
+ removed_heap->allocated_bytes -= size;
+}
+
+static int ion_removed_heap_phys(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ *addr = buffer->priv_phys;
+ *len = buffer->size;
+ return 0;
+}
+
+static int ion_removed_heap_allocate(struct ion_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long size, unsigned long align,
+ unsigned long flags)
+{
+ buffer->priv_phys = ion_removed_allocate(heap, size, align);
+ return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
+}
+
+static void ion_removed_heap_free(struct ion_buffer *buffer)
+{
+ struct ion_heap *heap = buffer->heap;
+
+ ion_removed_free(heap, buffer->priv_phys, buffer->size);
+ buffer->priv_phys = ION_CARVEOUT_ALLOCATE_FAIL;
+}
+
+struct sg_table *ion_removed_heap_map_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct sg_table *table;
+ int ret;
+
+ table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ ret = sg_alloc_table(table, 1, GFP_KERNEL);
+ if (ret)
+ goto err0;
+
+ table->sgl->length = buffer->size;
+ table->sgl->offset = 0;
+ table->sgl->dma_address = buffer->priv_phys;
+
+ return table;
+
+err0:
+ kfree(table);
+ return ERR_PTR(ret);
+}
+
+void ion_removed_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ if (buffer->sg_table)
+ sg_free_table(buffer->sg_table);
+ kfree(buffer->sg_table);
+ buffer->sg_table = 0;
+}
+
+static int ion_removed_request_region(struct ion_removed_heap *removed_heap)
+{
+ int ret_value = 0;
+ if (atomic_inc_return(&removed_heap->map_count) == 1) {
+ if (removed_heap->request_region) {
+ ret_value = removed_heap->request_region(
+ removed_heap->bus_id);
+ if (ret_value) {
+ pr_err("Unable to request SMI region");
+ atomic_dec(&removed_heap->map_count);
+ }
+ }
+ }
+ return ret_value;
+}
+
+static int ion_removed_release_region(struct ion_removed_heap *removed_heap)
+{
+ int ret_value = 0;
+ if (atomic_dec_and_test(&removed_heap->map_count)) {
+ if (removed_heap->release_region) {
+ ret_value = removed_heap->release_region(
+ removed_heap->bus_id);
+ if (ret_value)
+ pr_err("Unable to release SMI region");
+ }
+ }
+ return ret_value;
+}
+
+void *ion_removed_heap_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ void *ret_value;
+
+ if (ion_removed_request_region(removed_heap))
+ return NULL;
+
+ if (ION_IS_CACHED(buffer->flags))
+ ret_value = ioremap_cached(buffer->priv_phys, buffer->size);
+ else
+ ret_value = ioremap(buffer->priv_phys, buffer->size);
+
+ if (!ret_value)
+ ion_removed_release_region(removed_heap);
+ return ret_value;
+}
+
+void ion_removed_heap_unmap_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ __arm_iounmap(buffer->vaddr);
+ buffer->vaddr = NULL;
+
+ ion_removed_release_region(removed_heap);
+ return;
+}
+
+int ion_removed_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ int ret_value = 0;
+
+ if (ion_removed_request_region(removed_heap))
+ return -EINVAL;
+
+ if (!ION_IS_CACHED(buffer->flags))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ ret_value = remap_pfn_range(vma, vma->vm_start,
+ __phys_to_pfn(buffer->priv_phys) + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+
+ if (ret_value)
+ ion_removed_release_region(removed_heap);
+ return ret_value;
+}
+
+void ion_removed_heap_unmap_user(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+ ion_removed_release_region(removed_heap);
+}
+
+static int ion_removed_print_debug(struct ion_heap *heap, struct seq_file *s,
+ const struct rb_root *mem_map)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ seq_printf(s, "total bytes currently allocated: %lx\n",
+ removed_heap->allocated_bytes);
+ seq_printf(s, "total heap size: %lx\n", removed_heap->total_size);
+
+ if (mem_map) {
+ unsigned long base = removed_heap->base;
+ unsigned long size = removed_heap->total_size;
+ unsigned long end = base+size;
+ unsigned long last_end = base;
+ struct rb_node *n;
+
+ seq_printf(s, "\nMemory Map\n");
+ seq_printf(s, "%16.s %14.s %14.s %14.s\n",
+ "client", "start address", "end address",
+ "size (hex)");
+
+ for (n = rb_first(mem_map); n; n = rb_next(n)) {
+ struct mem_map_data *data =
+ rb_entry(n, struct mem_map_data, node);
+ const char *client_name = "(null)";
+
+ if (last_end < data->addr) {
+ phys_addr_t da;
+
+ da = data->addr-1;
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ "FREE", &last_end, &da,
+ data->addr-last_end,
+ data->addr-last_end);
+ }
+
+ if (data->client_name)
+ client_name = data->client_name;
+
+ seq_printf(s, "%16.s %14pa %14pa %14lu (%lx)\n",
+ client_name, &data->addr,
+ &data->addr_end,
+ data->size, data->size);
+ last_end = data->addr_end+1;
+ }
+ if (last_end < end) {
+ seq_printf(s, "%16.s %14lx %14lx %14lu (%lx)\n", "FREE",
+ last_end, end-1, end-last_end, end-last_end);
+ }
+ }
+ return 0;
+}
+
+static struct ion_heap_ops removed_heap_ops = {
+ .allocate = ion_removed_heap_allocate,
+ .free = ion_removed_heap_free,
+ .phys = ion_removed_heap_phys,
+ .map_user = ion_removed_heap_map_user,
+ .map_kernel = ion_removed_heap_map_kernel,
+ .unmap_user = ion_removed_heap_unmap_user,
+ .unmap_kernel = ion_removed_heap_unmap_kernel,
+ .map_dma = ion_removed_heap_map_dma,
+ .unmap_dma = ion_removed_heap_unmap_dma,
+ .print_debug = ion_removed_print_debug,
+};
+
+struct ion_heap *ion_removed_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_removed_heap *removed_heap;
+ int ret;
+
+ removed_heap = kzalloc(sizeof(struct ion_removed_heap), GFP_KERNEL);
+ if (!removed_heap)
+ return ERR_PTR(-ENOMEM);
+
+ removed_heap->pool = gen_pool_create(12, -1);
+ if (!removed_heap->pool) {
+ kfree(removed_heap);
+ return ERR_PTR(-ENOMEM);
+ }
+ removed_heap->base = heap_data->base;
+ ret = gen_pool_add(removed_heap->pool, removed_heap->base,
+ heap_data->size, -1);
+ if (ret < 0) {
+ gen_pool_destroy(removed_heap->pool);
+ kfree(removed_heap);
+ return ERR_PTR(-EINVAL);
+ }
+ removed_heap->heap.ops = &removed_heap_ops;
+ removed_heap->heap.type = ION_HEAP_TYPE_REMOVED;
+ removed_heap->allocated_bytes = 0;
+ removed_heap->total_size = heap_data->size;
+
+ if (heap_data->extra_data) {
+ struct ion_co_heap_pdata *extra_data =
+ heap_data->extra_data;
+
+ if (extra_data->setup_region)
+ removed_heap->bus_id = extra_data->setup_region();
+ if (extra_data->request_region)
+ removed_heap->request_region =
+ extra_data->request_region;
+ if (extra_data->release_region)
+ removed_heap->release_region =
+ extra_data->release_region;
+ }
+ return &removed_heap->heap;
+}
+
+void ion_removed_heap_destroy(struct ion_heap *heap)
+{
+ struct ion_removed_heap *removed_heap =
+ container_of(heap, struct ion_removed_heap, heap);
+
+ gen_pool_destroy(removed_heap->pool);
+ kfree(removed_heap);
+ removed_heap = NULL;
+}
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index ceb30a4..af7f04b 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -24,9 +24,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/iommu.h>
#include <linux/seq_file.h>
-#include <mach/iommu_domains.h>
#include "ion_priv.h"
#include <mach/memory.h>
#include <asm/cacheflush.h>
@@ -35,8 +33,6 @@
static atomic_t system_heap_allocated;
static atomic_t system_contig_heap_allocated;
-static unsigned int system_heap_has_outer_cache;
-static unsigned int system_heap_contig_has_outer_cache;
struct page_info {
struct page *page;
@@ -210,32 +206,6 @@
vunmap(buffer->vaddr);
}
-void ion_system_heap_unmap_iommu(struct ion_iommu_map *data)
-{
- unsigned int domain_num;
- unsigned int partition_num;
- struct iommu_domain *domain;
-
- if (!msm_use_iommu())
- return;
-
- domain_num = iommu_map_domain(data);
- partition_num = iommu_map_partition(data);
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
- return;
- }
-
- iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-
- return;
-}
-
int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma)
{
@@ -262,66 +232,6 @@
return 0;
}
-int ion_system_heap_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
- void *vaddr, 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:
- 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:
- 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:
- 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:
- return -EINVAL;
- }
-
- if (system_heap_has_outer_cache) {
- unsigned long pstart;
- struct sg_table *table = buffer->priv_virt;
- struct scatterlist *sg;
- int i;
- for_each_sg(table->sgl, sg, table->nents, i) {
- struct page *page = sg_page(sg);
- pstart = page_to_phys(page);
- /*
- * If page -> phys is returning NULL, something
- * has really gone wrong...
- */
- if (!pstart) {
- WARN(1, "Could not translate virtual address to physical address\n");
- return -EINVAL;
- }
- outer_cache_op(pstart, pstart + PAGE_SIZE);
- }
- }
- return 0;
-}
-
static int ion_system_print_debug(struct ion_heap *heap, struct seq_file *s,
const struct rb_root *unused)
{
@@ -331,81 +241,6 @@
return 0;
}
-int ion_system_heap_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- int ret = 0;
- struct iommu_domain *domain;
- unsigned long extra;
- unsigned long extra_iova_addr;
- struct sg_table *table = buffer->priv_virt;
- int prot = IOMMU_WRITE | IOMMU_READ;
- prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
- if (!ION_IS_CACHED(flags))
- return -EINVAL;
-
- if (!msm_use_iommu())
- return -EINVAL;
-
- 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);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -ENOMEM;
- goto out1;
- }
-
- ret = iommu_map_range(domain, data->iova_addr, table->sgl,
- buffer->size, prot);
-
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- extra_iova_addr = data->iova_addr + buffer->size;
- if (extra) {
- unsigned long phys_addr = sg_phys(table->sgl);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- return ret;
-
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-out1:
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-out:
- return ret;
-}
-
static struct ion_heap_ops vmalloc_ops = {
.allocate = ion_system_heap_allocate,
.free = ion_system_heap_free,
@@ -414,10 +249,7 @@
.map_kernel = ion_system_heap_map_kernel,
.unmap_kernel = ion_system_heap_unmap_kernel,
.map_user = ion_system_heap_map_user,
- .cache_op = ion_system_heap_cache_ops,
.print_debug = ion_system_print_debug,
- .map_iommu = ion_system_heap_map_iommu,
- .unmap_iommu = ion_system_heap_unmap_iommu,
};
struct ion_heap *ion_system_heap_create(struct ion_platform_heap *pheap)
@@ -429,7 +261,6 @@
return ERR_PTR(-ENOMEM);
heap->ops = &vmalloc_ops;
heap->type = ION_HEAP_TYPE_SYSTEM;
- system_heap_has_outer_cache = pheap->has_outer_cache;
return heap;
}
@@ -508,46 +339,6 @@
}
}
-int ion_system_contig_heap_cache_ops(struct ion_heap *heap,
- struct ion_buffer *buffer, void *vaddr,
- 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 (system_heap_contig_has_outer_cache) {
- unsigned long pstart;
-
- pstart = virt_to_phys(buffer->priv_virt) + offset;
- if (!pstart) {
- WARN(1, "Could not do virt to phys translation on %p\n",
- buffer->priv_virt);
- return -EINVAL;
- }
-
- outer_cache_op(pstart, pstart + PAGE_SIZE);
- }
-
- return 0;
-}
-
static int ion_system_contig_print_debug(struct ion_heap *heap,
struct seq_file *s,
const struct rb_root *unused)
@@ -558,84 +349,6 @@
return 0;
}
-int ion_system_contig_heap_map_iommu(struct ion_buffer *buffer,
- struct ion_iommu_map *data,
- unsigned int domain_num,
- unsigned int partition_num,
- unsigned long align,
- unsigned long iova_length,
- unsigned long flags)
-{
- int ret = 0;
- struct iommu_domain *domain;
- unsigned long extra;
- struct scatterlist *sglist = 0;
- struct page *page = 0;
- int prot = IOMMU_WRITE | IOMMU_READ;
- prot |= ION_IS_CACHED(flags) ? IOMMU_CACHE : 0;
-
- if (!ION_IS_CACHED(flags))
- return -EINVAL;
-
- if (!msm_use_iommu()) {
- data->iova_addr = virt_to_phys(buffer->vaddr);
- return 0;
- }
-
- data->mapped_size = iova_length;
- extra = iova_length - buffer->size;
-
- ret = msm_allocate_iova_address(domain_num, partition_num,
- data->mapped_size, align,
- &data->iova_addr);
-
- if (ret)
- goto out;
-
- domain = msm_get_iommu_domain(domain_num);
-
- if (!domain) {
- ret = -ENOMEM;
- goto out1;
- }
- page = virt_to_page(buffer->vaddr);
-
- sglist = vmalloc(sizeof(*sglist));
- if (!sglist)
- goto out1;
-
- sg_init_table(sglist, 1);
- sg_set_page(sglist, page, buffer->size, 0);
-
- ret = iommu_map_range(domain, data->iova_addr, sglist,
- buffer->size, prot);
- if (ret) {
- pr_err("%s: could not map %lx in domain %p\n",
- __func__, data->iova_addr, domain);
- goto out1;
- }
-
- if (extra) {
- unsigned long extra_iova_addr = data->iova_addr + buffer->size;
- unsigned long phys_addr = sg_phys(sglist);
- ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
- extra, SZ_4K, prot);
- if (ret)
- goto out2;
- }
- vfree(sglist);
- return ret;
-out2:
- iommu_unmap_range(domain, data->iova_addr, buffer->size);
-
-out1:
- vfree(sglist);
- msm_free_iova_address(data->iova_addr, domain_num, partition_num,
- data->mapped_size);
-out:
- return ret;
-}
-
void *ion_system_contig_heap_map_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
@@ -657,10 +370,7 @@
.map_kernel = ion_system_contig_heap_map_kernel,
.unmap_kernel = ion_system_contig_heap_unmap_kernel,
.map_user = ion_system_contig_heap_map_user,
- .cache_op = ion_system_contig_heap_cache_ops,
.print_debug = ion_system_contig_print_debug,
- .map_iommu = ion_system_contig_heap_map_iommu,
- .unmap_iommu = ion_system_heap_unmap_iommu,
};
struct ion_heap *ion_system_contig_heap_create(struct ion_platform_heap *pheap)
@@ -672,7 +382,6 @@
return ERR_PTR(-ENOMEM);
heap->ops = &kmalloc_ops;
heap->type = ION_HEAP_TYPE_SYSTEM_CONTIG;
- system_heap_contig_has_outer_cache = pheap->has_outer_cache;
return heap;
}
diff --git a/drivers/gpu/ion/msm/Makefile b/drivers/gpu/ion/msm/Makefile
index 1893405..becdb02 100644
--- a/drivers/gpu/ion/msm/Makefile
+++ b/drivers/gpu/ion/msm/Makefile
@@ -1 +1 @@
-obj-y += msm_ion.o ion_cp_common.o
+obj-y += msm_ion.o ion_cp_common.o ion_iommu_map.o
diff --git a/drivers/gpu/ion/msm/ion_iommu_map.c b/drivers/gpu/ion/msm/ion_iommu_map.c
new file mode 100644
index 0000000..ae4ae37
--- /dev/null
+++ b/drivers/gpu/ion/msm/ion_iommu_map.c
@@ -0,0 +1,538 @@
+/* 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
+ * 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/export.h>
+#include <linux/iommu.h>
+#include <linux/ion.h>
+#include <linux/kernel.h>
+#include <linux/kref.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+
+#include <mach/iommu_domains.h>
+
+enum {
+ DI_PARTITION_NUM = 0,
+ DI_DOMAIN_NUM = 1,
+ DI_MAX,
+};
+
+#define iommu_map_domain(__m) ((__m)->domain_info[1])
+#define iommu_map_partition(__m) ((__m)->domain_info[0])
+
+/**
+ * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
+ * @iova_addr - iommu virtual address
+ * @node - rb node to exist in the buffer's tree of iommu mappings
+ * @domain_info - contains the partition number and domain number
+ * domain_info[1] = domain number
+ * domain_info[0] = partition number
+ * @ref - for reference counting this mapping
+ * @mapped_size - size of the iova space mapped
+ * (may not be the same as the buffer size)
+ * @flags - iommu domain/partition specific flags.
+ *
+ * Represents a mapping of one ion buffer to a particular iommu domain
+ * and address range. There may exist other mappings of this buffer in
+ * different domains or address ranges. All mappings will have the same
+ * cacheability and security.
+ */
+struct ion_iommu_map {
+ unsigned long iova_addr;
+ struct rb_node node;
+ union {
+ int domain_info[DI_MAX];
+ uint64_t key;
+ };
+ struct ion_iommu_meta *meta;
+ struct kref ref;
+ int mapped_size;
+ unsigned long flags;
+};
+
+
+struct ion_iommu_meta {
+ struct rb_node node;
+ struct ion_handle *handle;
+ struct rb_root iommu_maps;
+ struct kref ref;
+ struct sg_table *table;
+ unsigned long size;
+ struct mutex lock;
+};
+
+static struct rb_root iommu_root;
+DEFINE_MUTEX(msm_iommu_map_mutex);
+
+static void ion_iommu_meta_add(struct ion_iommu_meta *meta)
+{
+ struct rb_root *root = &iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_meta *entry;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_meta, node);
+
+ if (meta->handle < entry->handle) {
+ p = &(*p)->rb_left;
+ } else if (meta->handle > entry->handle) {
+ p = &(*p)->rb_right;
+ } else {
+ pr_err("%s: handle %p already exists\n", __func__,
+ entry->handle);
+ BUG();
+ }
+ }
+
+ rb_link_node(&meta->node, parent, p);
+ rb_insert_color(&meta->node, root);
+}
+
+
+static struct ion_iommu_meta *ion_iommu_meta_lookup(struct ion_handle *handle)
+{
+ struct rb_root *root = &iommu_root;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_meta *entry = NULL;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_meta, node);
+
+ if (handle < entry->handle)
+ p = &(*p)->rb_left;
+ else if (handle > entry->handle)
+ p = &(*p)->rb_right;
+ else
+ return entry;
+ }
+
+ return NULL;
+}
+
+
+
+static void ion_iommu_add(struct ion_iommu_meta *meta,
+ struct ion_iommu_map *iommu)
+{
+ struct rb_node **p = &meta->iommu_maps.rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_map *entry;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_map, node);
+
+ if (iommu->key < entry->key) {
+ p = &(*p)->rb_left;
+ } else if (iommu->key > entry->key) {
+ p = &(*p)->rb_right;
+ } else {
+ pr_err("%s: handle %p already has mapping for domain %d and partition %d\n",
+ __func__,
+ meta->handle,
+ iommu_map_domain(iommu),
+ iommu_map_partition(iommu));
+ BUG();
+ }
+ }
+
+ rb_link_node(&iommu->node, parent, p);
+ rb_insert_color(&iommu->node, &meta->iommu_maps);
+}
+
+
+static struct ion_iommu_map *ion_iommu_lookup(
+ struct ion_iommu_meta *meta,
+ unsigned int domain_no,
+ unsigned int partition_no)
+{
+ struct rb_node **p = &meta->iommu_maps.rb_node;
+ struct rb_node *parent = NULL;
+ struct ion_iommu_map *entry;
+ uint64_t key = domain_no;
+ key = key << 32 | partition_no;
+
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct ion_iommu_map, node);
+
+ if (key < entry->key)
+ p = &(*p)->rb_left;
+ else if (key > entry->key)
+ p = &(*p)->rb_right;
+ else
+ return entry;
+ }
+
+ return NULL;
+}
+
+static int ion_iommu_map_iommu(struct ion_iommu_meta *meta,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ struct iommu_domain *domain;
+ int ret = 0;
+ unsigned long extra, size;
+ struct sg_table *table;
+ int prot = IOMMU_WRITE | IOMMU_READ;
+
+
+ size = meta->size;
+ data->mapped_size = iova_length;
+ extra = iova_length - size;
+ table = meta->table;
+
+ /* 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);
+
+ if (ret)
+ goto out;
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ ret = iommu_map_range(domain, data->iova_addr,
+ table->sgl,
+ size, prot);
+ if (ret) {
+ pr_err("%s: could not map %lx in domain %p\n",
+ __func__, data->iova_addr, domain);
+ goto out1;
+ }
+
+ if (extra) {
+ unsigned long extra_iova_addr = data->iova_addr + size;
+ unsigned long phys_addr = sg_phys(table->sgl);
+ ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
+ extra, SZ_4K, prot);
+ if (ret)
+ goto out2;
+ }
+ return ret;
+
+out2:
+ iommu_unmap_range(domain, data->iova_addr, size);
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ size);
+
+out:
+
+ return ret;
+}
+
+static void ion_iommu_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ BUG_ON(!msm_use_iommu());
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ iommu_unmap_range(domain, data->iova_addr, data->mapped_size);
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
+
+
+
+static struct ion_iommu_map *__ion_iommu_map(struct ion_iommu_meta *meta,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long flags,
+ unsigned long *iova)
+{
+ struct ion_iommu_map *data;
+ int ret;
+
+ data = kmalloc(sizeof(*data), GFP_ATOMIC);
+
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+
+ iommu_map_domain(data) = domain_num;
+ iommu_map_partition(data) = partition_num;
+
+ ret = ion_iommu_map_iommu(meta, data,
+ domain_num,
+ partition_num,
+ align,
+ iova_length,
+ flags);
+
+ if (ret)
+ goto out;
+
+ kref_init(&data->ref);
+ *iova = data->iova_addr;
+ data->meta = meta;
+
+ ion_iommu_add(meta, data);
+
+ return data;
+
+out:
+ kfree(data);
+ return ERR_PTR(ret);
+}
+
+static struct ion_iommu_meta *ion_iommu_meta_create(struct ion_handle *handle,
+ struct sg_table *table,
+ unsigned long size)
+{
+ struct ion_iommu_meta *meta;
+
+ meta = kzalloc(sizeof(*meta), GFP_KERNEL);
+
+ if (!meta)
+ return ERR_PTR(-ENOMEM);
+
+ meta->handle = handle;
+ meta->table = table;
+ meta->size = size;
+ kref_init(&meta->ref);
+ mutex_init(&meta->lock);
+ ion_iommu_meta_add(meta);
+
+ return meta;
+}
+
+static void ion_iommu_meta_destroy(struct kref *kref)
+{
+ struct ion_iommu_meta *meta = container_of(kref, struct ion_iommu_meta,
+ ref);
+
+
+ rb_erase(&meta->node, &iommu_root);
+ kfree(meta);
+}
+
+static void ion_iommu_meta_put(struct ion_iommu_meta *meta)
+{
+ /*
+ * Need to lock here to prevent race against map/unmap
+ */
+ mutex_lock(&msm_iommu_map_mutex);
+ kref_put(&meta->ref, ion_iommu_meta_destroy);
+ mutex_unlock(&msm_iommu_map_mutex);
+}
+
+int ion_map_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num, unsigned long align,
+ unsigned long iova_length, unsigned long *iova,
+ unsigned long *buffer_size,
+ unsigned long flags, unsigned long iommu_flags)
+{
+ struct ion_iommu_map *iommu_map;
+ struct ion_iommu_meta *iommu_meta = NULL;
+ struct sg_table *table;
+ struct scatterlist *sg;
+ int ret = 0;
+ int i;
+ unsigned long size = 0;
+
+ if (IS_ERR_OR_NULL(client)) {
+ pr_err("%s: client pointer is invalid\n", __func__);
+ return -EINVAL;
+ }
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: handle pointer is invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ table = ion_sg_table(client, handle);
+
+ if (IS_ERR_OR_NULL(table))
+ return PTR_ERR(table);
+
+ for_each_sg(table->sgl, sg, table->nents, i)
+ size += sg_dma_len(sg);
+
+ if (!msm_use_iommu()) {
+ unsigned long pa = sg_dma_address(table->sgl);
+ if (pa == 0)
+ pa = sg_phys(table->sgl);
+ *iova = pa;
+ *buffer_size = size;
+ }
+ /*
+ * If clients don't want a custom iova length, just use whatever
+ * the buffer size is
+ */
+ if (!iova_length)
+ iova_length = size;
+
+ if (size > iova_length) {
+ pr_debug("%s: iova length %lx is not at least buffer size %lx\n",
+ __func__, iova_length, size);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (size & ~PAGE_MASK) {
+ pr_debug("%s: buffer size %lx is not aligned to %lx", __func__,
+ size, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (iova_length & ~PAGE_MASK) {
+ pr_debug("%s: iova_length %lx is not aligned to %lx", __func__,
+ iova_length, PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mutex_lock(&msm_iommu_map_mutex);
+ iommu_meta = ion_iommu_meta_lookup(handle);
+
+ if (!iommu_meta)
+ iommu_meta = ion_iommu_meta_create(handle, table, size);
+ else
+ kref_get(&iommu_meta->ref);
+
+ mutex_unlock(&msm_iommu_map_mutex);
+
+ iommu_map = ion_iommu_lookup(iommu_meta, domain_num, partition_num);
+ if (!iommu_map) {
+ iommu_map = __ion_iommu_map(iommu_meta, domain_num,
+ partition_num, align, iova_length,
+ flags, iova);
+ if (!IS_ERR_OR_NULL(iommu_map)) {
+ iommu_map->flags = iommu_flags;
+ ret = 0;
+ } else {
+ ret = PTR_ERR(iommu_map);
+ goto out;
+ }
+ } else {
+ if (iommu_map->flags != iommu_flags) {
+ pr_err("%s: handle %p is already mapped with iommu flags %lx, trying to map with flags %lx\n",
+ __func__, handle,
+ iommu_map->flags, iommu_flags);
+ ret = -EINVAL;
+ goto out;
+ } else if (iommu_map->mapped_size != iova_length) {
+ pr_err("%s: handle %p is already mapped with length %x, trying to map with length %lx\n",
+ __func__, handle, iommu_map->mapped_size,
+ iova_length);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ kref_get(&iommu_map->ref);
+ *iova = iommu_map->iova_addr;
+ }
+ }
+ *buffer_size = size;
+ return ret;
+
+out:
+
+ ion_iommu_meta_put(iommu_meta);
+ return ret;
+}
+EXPORT_SYMBOL(ion_map_iommu);
+
+
+static void ion_iommu_map_release(struct kref *kref)
+{
+ struct ion_iommu_map *map = container_of(kref, struct ion_iommu_map,
+ ref);
+ struct ion_iommu_meta *meta = map->meta;
+
+ rb_erase(&map->node, &meta->iommu_maps);
+ ion_iommu_heap_unmap_iommu(map);
+ kfree(map);
+}
+
+void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle,
+ int domain_num, int partition_num)
+{
+ struct ion_iommu_map *iommu_map;
+ struct ion_iommu_meta *meta;
+
+ if (IS_ERR_OR_NULL(client)) {
+ pr_err("%s: client pointer is invalid\n", __func__);
+ return;
+ }
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: handle pointer is invalid\n", __func__);
+ return;
+ }
+
+
+ mutex_lock(&msm_iommu_map_mutex);
+ meta = ion_iommu_meta_lookup(handle);
+ if (!meta) {
+ WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
+ domain_num, partition_num, handle);
+ mutex_lock(&msm_iommu_map_mutex);
+ goto out;
+
+ }
+ mutex_unlock(&msm_iommu_map_mutex);
+
+ mutex_lock(&meta->lock);
+ iommu_map = ion_iommu_lookup(meta, domain_num, partition_num);
+
+ if (!iommu_map) {
+ WARN(1, "%s: (%d,%d) was never mapped for %p\n", __func__,
+ domain_num, partition_num, handle);
+ mutex_unlock(&meta->lock);
+ goto out;
+ }
+
+ kref_put(&iommu_map->ref, ion_iommu_map_release);
+ mutex_unlock(&meta->lock);
+
+ ion_iommu_meta_put(meta);
+
+out:
+ return;
+}
+EXPORT_SYMBOL(ion_unmap_iommu);
+
+
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 4b55875..9259de2 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -26,8 +26,10 @@
#include <linux/rwsem.h>
#include <linux/uaccess.h>
#include <linux/memblock.h>
+#include <linux/dma-mapping.h>
#include <mach/ion.h>
#include <mach/msm_memtypes.h>
+#include <asm/cacheflush.h>
#include "../ion_priv.h"
#include "ion_cp_common.h"
@@ -177,6 +179,210 @@
}
EXPORT_SYMBOL(msm_ion_do_cache_op);
+static int ion_no_pages_cache_ops(struct ion_client *client,
+ struct ion_handle *handle,
+ void *vaddr,
+ unsigned int offset, unsigned int length,
+ unsigned int cmd)
+{
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL;
+ unsigned int size_to_vmap, total_size;
+ int i, j, ret;
+ void *ptr = NULL;
+ ion_phys_addr_t buff_phys = 0;
+ ion_phys_addr_t buff_phys_start = 0;
+ size_t buf_length = 0;
+
+ ret = ion_phys(client, handle, &buff_phys_start, &buf_length);
+ if (ret)
+ return -EINVAL;
+
+ buff_phys = buff_phys_start;
+
+ 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 = buf_length;
+
+ 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;
+ }
+ }
+
+ outer_cache_op(buff_phys_start + offset,
+ buff_phys_start + offset + length);
+
+ return 0;
+}
+
+#ifdef CONFIG_OUTER_CACHE
+static void ion_pages_outer_cache_op(void (*op)(phys_addr_t, phys_addr_t),
+ struct sg_table *table)
+{
+ unsigned long pstart;
+ struct scatterlist *sg;
+ int i;
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ struct page *page = sg_page(sg);
+ pstart = page_to_phys(page);
+ /*
+ * If page -> phys is returning NULL, something
+ * has really gone wrong...
+ */
+ if (!pstart) {
+ WARN(1, "Could not translate virtual address to physical address\n");
+ return;
+ }
+ op(pstart, pstart + PAGE_SIZE);
+ }
+}
+#else
+static void ion_pages_outer_cache_op(void (*op)(phys_addr_t, phys_addr_t),
+ struct sg_table *table)
+{
+
+}
+#endif
+
+static int ion_pages_cache_ops(struct ion_client *client,
+ struct ion_handle *handle,
+ void *vaddr, unsigned int offset, unsigned int length,
+ unsigned int cmd)
+{
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t);
+ struct sg_table *table = NULL;
+
+ table = ion_sg_table(client, handle);
+ if (IS_ERR_OR_NULL(table))
+ return PTR_ERR(table);
+
+ switch (cmd) {
+ case ION_IOC_CLEAN_CACHES:
+ if (!vaddr)
+ dma_sync_sg_for_device(NULL, table->sgl,
+ table->nents, DMA_TO_DEVICE);
+ else
+ dmac_clean_range(vaddr, vaddr + length);
+ outer_cache_op = outer_clean_range;
+ break;
+ case ION_IOC_INV_CACHES:
+ if (!vaddr)
+ dma_sync_sg_for_cpu(NULL, table->sgl,
+ 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:
+ if (!vaddr) {
+ dma_sync_sg_for_device(NULL, table->sgl,
+ table->nents, DMA_TO_DEVICE);
+ dma_sync_sg_for_cpu(NULL, table->sgl,
+ table->nents, DMA_FROM_DEVICE);
+ } else {
+ dmac_flush_range(vaddr, vaddr + length);
+ }
+ outer_cache_op = outer_flush_range;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ion_pages_outer_cache_op(outer_cache_op, table);
+
+ return 0;
+}
+
+int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle,
+ void *uaddr, unsigned long offset, unsigned long len,
+ unsigned int cmd)
+{
+ int ret = -EINVAL;
+ unsigned long flags;
+ struct sg_table *table;
+ struct page *page;
+
+ ret = ion_handle_get_flags(client, handle, &flags);
+ if (ret)
+ return -EINVAL;
+
+ if (!ION_IS_CACHED(flags))
+ return 0;
+
+ table = ion_sg_table(client, handle);
+
+ if (IS_ERR_OR_NULL(table))
+ return PTR_ERR(table);
+
+ page = sg_page(table->sgl);
+
+ if (page)
+ ret = ion_pages_cache_ops(client, handle, uaddr,
+ offset, len, cmd);
+ else
+ ret = ion_no_pages_cache_ops(client, handle, uaddr,
+ offset, len, cmd);
+
+ return ret;
+
+}
+
static ion_phys_addr_t msm_ion_get_base(unsigned long size, int memory_type,
unsigned int align)
{
@@ -770,6 +976,10 @@
heap = ion_secure_cma_heap_create(heap_data);
break;
#endif
+ case ION_HEAP_TYPE_REMOVED:
+ heap = ion_removed_heap_create(heap_data);
+ break;
+
default:
heap = ion_heap_create(heap_data);
}
@@ -807,6 +1017,9 @@
ion_secure_cma_heap_destroy(heap);
break;
#endif
+ case ION_HEAP_TYPE_REMOVED:
+ ion_removed_heap_destroy(heap);
+ break;
default:
ion_heap_destroy(heap);
}
diff --git a/drivers/gpu/ion/msm_ion_priv.h b/drivers/gpu/ion/msm_ion_priv.h
index 44f434a..2de4e8a 100644
--- a/drivers/gpu/ion/msm_ion_priv.h
+++ b/drivers/gpu/ion/msm_ion_priv.h
@@ -26,42 +26,6 @@
#include <linux/iommu.h>
#include <linux/seq_file.h>
-enum {
- DI_PARTITION_NUM = 0,
- DI_DOMAIN_NUM = 1,
- DI_MAX,
-};
-
-/**
- * struct ion_iommu_map - represents a mapping of an ion buffer to an iommu
- * @iova_addr - iommu virtual address
- * @node - rb node to exist in the buffer's tree of iommu mappings
- * @domain_info - contains the partition number and domain number
- * domain_info[1] = domain number
- * domain_info[0] = partition number
- * @ref - for reference counting this mapping
- * @mapped_size - size of the iova space mapped
- * (may not be the same as the buffer size)
- * @flags - iommu domain/partition specific flags.
- *
- * Represents a mapping of one ion buffer to a particular iommu domain
- * and address range. There may exist other mappings of this buffer in
- * different domains or address ranges. All mappings will have the same
- * cacheability and security.
- */
-struct ion_iommu_map {
- unsigned long iova_addr;
- struct rb_node node;
- union {
- int domain_info[DI_MAX];
- uint64_t key;
- };
- struct ion_buffer *buffer;
- struct kref ref;
- int mapped_size;
- unsigned long flags;
-};
-
/**
* struct mem_map_data - represents information about the memory map for a heap
* @node: rb node used to store in the tree of mem_map_data
@@ -79,9 +43,6 @@
const char *client_name;
};
-#define iommu_map_domain(__m) ((__m)->domain_info[1])
-#define iommu_map_partition(__m) ((__m)->domain_info[0])
-
struct ion_heap *ion_iommu_heap_create(struct ion_platform_heap *);
void ion_iommu_heap_destroy(struct ion_heap *);
@@ -96,6 +57,9 @@
void ion_secure_cma_heap_destroy(struct ion_heap *);
#endif
+struct ion_heap *ion_removed_heap_create(struct ion_platform_heap *);
+void ion_removed_heap_destroy(struct ion_heap *);
+
#define ION_CP_ALLOCATE_FAIL -1
#define ION_RESERVED_ALLOCATE_FAIL -1
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index a2f0e60..c768bb7 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -396,6 +396,19 @@
#define A3XX_VBIF_OUT_AXI_AMEMTYPE_CONF0 0x3058
#define A3XX_VBIF_OUT_AXI_AOOO_EN 0x305E
#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
+#define A3XX_VBIF_PERF_CNT_EN 0x3070
+#define A3XX_VBIF_PERF_CNT_CLR 0x3071
+#define A3XX_VBIF_PERF_CNT_SEL 0x3072
+#define A3XX_VBIF_PERF_CNT0_LO 0x3073
+#define A3XX_VBIF_PERF_CNT0_HI 0x3074
+#define A3XX_VBIF_PERF_CNT1_LO 0x3075
+#define A3XX_VBIF_PERF_CNT1_HI 0x3076
+#define A3XX_VBIF_PERF_PWR_CNT0_LO 0x3077
+#define A3XX_VBIF_PERF_PWR_CNT0_HI 0x3078
+#define A3XX_VBIF_PERF_PWR_CNT1_LO 0x3079
+#define A3XX_VBIF_PERF_PWR_CNT1_HI 0x307a
+#define A3XX_VBIF_PERF_PWR_CNT2_LO 0x307b
+#define A3XX_VBIF_PERF_PWR_CNT2_HI 0x307c
/* Bit flags for RBBM_CTL */
#define RBBM_RBBM_CTL_RESET_PWR_CTR0 BIT(0)
@@ -670,11 +683,11 @@
#define A305C_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
-#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
+#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A305B_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A330_RBBM_GPR0_CTL_DEFAULT 0x00000000
-#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x00000000
+#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x05515455
/* COUNTABLE FOR SP PERFCOUNTER */
#define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E
@@ -682,4 +695,20 @@
#define SP0_ICL1_MISSES 0x1A
#define SP_FS_CFLOW_INSTRUCTIONS 0x0C
+/* VBIF PERFCOUNTER ENA/CLR values */
+#define VBIF_PERF_CNT_0 BIT(0)
+#define VBIF_PERF_CNT_1 BIT(1)
+#define VBIF_PERF_PWR_CNT_0 BIT(2)
+#define VBIF_PERF_PWR_CNT_1 BIT(3)
+#define VBIF_PERF_PWR_CNT_2 BIT(4)
+
+/* VBIF PERFCOUNTER SEL values */
+#define VBIF_PERF_CNT_0_SEL 0
+#define VBIF_PERF_CNT_0_SEL_MASK 0x7f
+#define VBIF_PERF_CNT_1_SEL 8
+#define VBIF_PERF_CNT_1_SEL_MASK 0x7f00
+
+/* VBIF countables */
+#define VBIF_DDR_TOTAL_CYCLES 110
+
#endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 62b6a71..5589ff0 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1859,7 +1859,8 @@
}
if (status)
KGSL_FT_ERR(rb->device,
- "Failed to find the command sequence after eop timestamp\n");
+ "Failed to find the command sequence after eop timestamp %x\n",
+ global_eop);
return status;
}
@@ -1972,44 +1973,38 @@
/* 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;
+ /* Look for the command stream that is right after the global eop */
ret = _find_cmd_seq_after_eop_ts(rb, &rb_rptr,
ft_data->global_eop + 1, false);
if (ret) {
ft_data->ft_policy |= KGSL_FT_TEMP_DISABLE;
return;
- } else
+ } else {
+ ft_data->start_of_replay_cmds = rb_rptr;
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;
+ if (context) {
+ 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 seq\n");
+ ret = 0;
+ return;
+ }
+ ft_data->start_of_replay_cmds = rb_rptr;
+ ft_data->replay_for_snapshot = rb_rptr;
}
- ft_data->start_of_replay_cmds = rb_rptr;
- ft_data->replay_for_snapshot = rb_rptr;
}
}
}
@@ -2046,9 +2041,6 @@
_adreno_ft_restart_device(struct kgsl_device *device,
struct kgsl_context *context)
{
-
- struct adreno_context *adreno_context = context->devctxt;
-
/* restart device */
if (adreno_stop(device)) {
KGSL_FT_ERR(device, "Device stop failed\n");
@@ -2065,9 +2057,11 @@
return 1;
}
- if (context)
+ if (context) {
+ struct adreno_context *adreno_context = context->devctxt;
kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
KGSL_MEMSTORE_GLOBAL);
+ }
/* 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 */
@@ -2168,13 +2162,22 @@
struct adreno_context *adreno_context = NULL;
struct adreno_context *last_active_ctx = adreno_dev->drawctxt_active;
unsigned int long_ib = 0;
+ static int no_context_ft;
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;
+ if (no_context_ft) {
+ /*
+ * If 2 consecutive no context ft occurred then
+ * just reset GPU
+ */
+ no_context_ft = 0;
+ goto play_good_cmds;
+ }
} else {
+ no_context_ft = 0;
adreno_context = context->devctxt;
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
/*
@@ -2230,7 +2233,7 @@
}
/* Do not try the reply if hang is due to a pagefault */
- if (adreno_context->pagefault) {
+ if (adreno_context && 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;
@@ -2295,7 +2298,7 @@
/* EOF not found in RB, discard till EOF in
next IB submission */
- if (i == ft_data->bad_rb_size) {
+ if (adreno_context && (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");
@@ -2332,8 +2335,14 @@
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 */
+ /*
+ * If we fail here we can try to invalidate another
+ * context and try fault tolerance again, although
+ * we will only try ft with no context once to avoid
+ * going into continuous loop of trying ft with no context
+ */
+ if (!context)
+ no_context_ft = 1;
ret = -EAGAIN;
KGSL_FT_ERR(device, "Playing good commands unsuccessful\n");
goto done;
@@ -3166,6 +3175,31 @@
"Fault tolerance no context found\n");
}
}
+ 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 ? curr_context->pid_name : "",
+ curr_context ? curr_context->id : 0,
+ (kgsl_readtimestamp(device, context,
+ KGSL_TIMESTAMP_RETIRED) + 1),
+ curr_global_ts + 1);
+ return 1;
+ }
if (curr_context != NULL) {
@@ -3175,31 +3209,6 @@
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))) {
@@ -3229,10 +3238,6 @@
}
}
}
- } else {
- KGSL_FT_ERR(device,
- "Last context unknown id:%d\n",
- curr_context_id);
}
} else {
/* GPU is moving forward */
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 13c723a..be5c786 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2752,6 +2752,58 @@
return;
}
+static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device,
+ unsigned int counter,
+ unsigned int countable)
+{
+ unsigned int in, out, bit, sel;
+
+ if (countable > 0x7f)
+ return;
+
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
+
+ if (counter == 0) {
+ bit = VBIF_PERF_CNT_0;
+ sel = (sel & ~VBIF_PERF_CNT_0_SEL_MASK) | countable;
+ } else if (counter == 1) {
+ bit = VBIF_PERF_CNT_1;
+ sel = (sel & ~VBIF_PERF_CNT_1_SEL_MASK)
+ | (countable << VBIF_PERF_CNT_1_SEL);
+ }
+
+ out = in | bit;
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+}
+
+static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
+ unsigned int countable)
+{
+ unsigned int in, out, bit;
+
+ adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
+ if (countable == 0)
+ bit = VBIF_PERF_PWR_CNT_0;
+ else if (countable == 1)
+ bit = VBIF_PERF_PWR_CNT_1;
+ else
+ bit = VBIF_PERF_PWR_CNT_2;
+
+ out = in | bit;
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit);
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
+
+ adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
+}
+
/*
* a3xx_perfcounter_enable - Configure a performance counter for a countable
* @adreno_dev - Adreno device to configure
@@ -2775,9 +2827,13 @@
if (counter > a3xx_perfcounter_reglist[group].count)
return;
- /* Special case - power */
+ /* Special cases */
if (group == KGSL_PERFCOUNTER_GROUP_PWR)
return a3xx_perfcounter_enable_pwr(device, countable);
+ else if (group == KGSL_PERFCOUNTER_GROUP_VBIF)
+ return a3xx_perfcounter_enable_vbif(device, counter, countable);
+ else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
+ return a3xx_perfcounter_enable_vbif_pwr(device, countable);
reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
@@ -3265,6 +3321,16 @@
{ KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
};
+static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO },
+};
+static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO },
+};
+
static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
{ a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) },
{ a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) },
@@ -3279,6 +3345,8 @@
{ a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) },
{ a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) },
{ a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) },
+ { a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) },
+ { a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) },
};
static struct adreno_perfcounters a3xx_perfcounters = {
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index aea3431..f0b9b05 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -74,7 +74,8 @@
DMX_FRAME_ERROR, /* Frame alignment error */
DMX_FIFO_ERROR, /* Receiver FIFO overrun */
DMX_MISSED_ERROR, /* Receiver missed packet */
- DMX_OK_DECODER_BUF /* Received OK, new ES data in decoder buffer */
+ DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
+ DMX_OK_IDX /* Received OK, new index event */
} ;
@@ -131,6 +132,8 @@
struct {
u64 id;
} marker;
+
+ struct dmx_index_event_info idx_event;
};
};
@@ -222,8 +225,10 @@
struct timespec timeout);
int (*start_filtering) (struct dmx_ts_feed* feed);
int (*stop_filtering) (struct dmx_ts_feed* feed);
- int (*set_indexing_params) (struct dmx_ts_feed *feed,
- struct dmx_indexing_video_params *params);
+ int (*set_video_codec) (struct dmx_ts_feed *feed,
+ enum dmx_video_codec video_codec);
+ int (*set_idx_params) (struct dmx_ts_feed *feed,
+ struct dmx_indexing_params *idx_params);
int (*get_decoder_buff_status)(
struct dmx_ts_feed *feed,
struct dmx_buffer_status *dmx_buffer_status);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 219970b..ca71c06 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1714,8 +1714,44 @@
return 0;
}
-static int dvb_dmxdev_ts_fullness_callback(
- struct dmx_ts_feed *filter,
+static int dvb_dmxdev_set_indexing_params(struct dmxdev_filter *dmxdevfilter,
+ struct dmx_indexing_params *idx_params)
+{
+ int found_pid;
+ struct dmxdev_feed *feed;
+ struct dmxdev_feed *ts_feed = NULL;
+
+ if (!idx_params ||
+ (dmxdevfilter->state < DMXDEV_STATE_SET) ||
+ (dmxdevfilter->type != DMXDEV_TYPE_PES) ||
+ ((dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) &&
+ (dmxdevfilter->params.pes.output != DMX_OUT_TSDEMUX_TAP)))
+ return -EINVAL;
+
+ if (idx_params->enable && !idx_params->types)
+ return -EINVAL;
+
+ found_pid = 0;
+ list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
+ if (feed->pid == idx_params->pid) {
+ found_pid = 1;
+ ts_feed = feed;
+ ts_feed->idx_params = *idx_params;
+ if ((dmxdevfilter->state == DMXDEV_STATE_GO) &&
+ ts_feed->ts->set_idx_params)
+ ts_feed->ts->set_idx_params(
+ ts_feed->ts, idx_params);
+ break;
+ }
+ }
+
+ if (!found_pid)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int dvb_dmxdev_ts_fullness_callback(struct dmx_ts_feed *filter,
int required_space)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
@@ -2349,6 +2385,17 @@
return 0;
}
+ if (dmx_data_ready->status == DMX_OK_IDX) {
+ dprintk("dmxdev: event callback DMX_OK_IDX\n");
+ event.type = DMX_EVENT_NEW_INDEX_ENTRY;
+ event.params.index = dmx_data_ready->idx_event;
+
+ dvb_dmxdev_add_event(events, &event);
+ spin_unlock(&dmxdevfilter->dev->lock);
+ wake_up_all(&buffer->queue);
+ return 0;
+ }
+
if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
event.type = DMX_EVENT_NEW_ES_DATA;
event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -2706,15 +2753,13 @@
if (tsfeed->set_secure_mode)
tsfeed->set_secure_mode(tsfeed, &feed->sec_mode);
- /* Support indexing for video PES */
if ((para->pes_type == DMX_PES_VIDEO0) ||
(para->pes_type == DMX_PES_VIDEO1) ||
(para->pes_type == DMX_PES_VIDEO2) ||
(para->pes_type == DMX_PES_VIDEO3)) {
-
- if (tsfeed->set_indexing_params) {
- ret = tsfeed->set_indexing_params(tsfeed,
- ¶->video_params);
+ if (tsfeed->set_video_codec) {
+ ret = tsfeed->set_video_codec(tsfeed,
+ para->video_codec);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux,
@@ -2724,6 +2769,12 @@
}
}
+ if ((filter->params.pes.output == DMX_OUT_TS_TAP) ||
+ (filter->params.pes.output == DMX_OUT_TSDEMUX_TAP))
+ if (tsfeed->set_idx_params)
+ tsfeed->set_idx_params(
+ tsfeed, &feed->idx_params);
+
ret = tsfeed->start_filtering(tsfeed);
if (ret < 0) {
dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
@@ -3034,6 +3085,7 @@
feed->pid = pid;
feed->sec_mode.is_secured = 0;
+ feed->idx_params.enable = 0;
list_add(&feed->next, &filter->feed.ts);
if (filter->state >= DMXDEV_STATE_GO)
@@ -3158,23 +3210,6 @@
if (params->pes_type > DMX_PES_OTHER || params->pes_type < 0)
return -EINVAL;
- if (params->flags & DMX_ENABLE_INDEXING) {
- if (!(dmxdev->capabilities & DMXDEV_CAP_INDEXING))
- return -EINVAL;
-
- /* can do indexing only on video PES */
- if ((params->pes_type != DMX_PES_VIDEO0) &&
- (params->pes_type != DMX_PES_VIDEO1) &&
- (params->pes_type != DMX_PES_VIDEO2) &&
- (params->pes_type != DMX_PES_VIDEO3))
- return -EINVAL;
-
- /* can do indexing only when recording */
- if ((params->output != DMX_OUT_TS_TAP) &&
- (params->output != DMX_OUT_TSDEMUX_TAP))
- return -EINVAL;
- }
-
dmxdevfilter->type = DMXDEV_TYPE_PES;
memcpy(&dmxdevfilter->params, params,
sizeof(struct dmx_pes_filter_params));
@@ -3580,6 +3615,15 @@
mutex_unlock(&dmxdevfilter->mutex);
break;
+ case DMX_SET_INDEXING_PARAMS:
+ if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+ mutex_unlock(&dmxdev->mutex);
+ return -ERESTARTSYS;
+ }
+ ret = dvb_dmxdev_set_indexing_params(dmxdevfilter, parg);
+ mutex_unlock(&dmxdevfilter->mutex);
+ break;
+
default:
ret = -EINVAL;
break;
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 7845b75..2ed99ae 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -59,6 +59,7 @@
struct dmxdev_feed {
u16 pid;
struct dmx_secure_mode sec_mode;
+ struct dmx_indexing_params idx_params;
struct dmx_ts_feed *ts;
struct list_head next;
};
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 3f73c4d..3f3d222 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -65,6 +65,91 @@
printk(x); \
} while (0)
+static const struct dvb_dmx_video_patterns mpeg2_seq_hdr = {
+ {0x00, 0x00, 0x01, 0xB3},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ 4,
+ DMX_IDX_MPEG_SEQ_HEADER
+};
+
+static const struct dvb_dmx_video_patterns mpeg2_gop = {
+ {0x00, 0x00, 0x01, 0xB8},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ 4,
+ DMX_IDX_MPEG_GOP
+};
+
+static const struct dvb_dmx_video_patterns mpeg2_iframe = {
+ {0x00, 0x00, 0x01, 0x00, 0x00, 0x08},
+ {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38},
+ 6,
+ DMX_IDX_MPEG_I_FRAME_START
+};
+
+static const struct dvb_dmx_video_patterns mpeg2_pframe = {
+ {0x00, 0x00, 0x01, 0x00, 0x00, 0x10},
+ {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38},
+ 6,
+ DMX_IDX_MPEG_P_FRAME_START
+};
+
+static const struct dvb_dmx_video_patterns mpeg2_bframe = {
+ {0x00, 0x00, 0x01, 0x00, 0x00, 0x18},
+ {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38},
+ 6,
+ DMX_IDX_MPEG_B_FRAME_START
+};
+
+static const struct dvb_dmx_video_patterns h264_sps = {
+ {0x00, 0x00, 0x01, 0x07},
+ {0xFF, 0xFF, 0xFF, 0x1F},
+ 4,
+ DMX_IDX_H264_SPS
+};
+
+static const struct dvb_dmx_video_patterns h264_pps = {
+ {0x00, 0x00, 0x01, 0x08},
+ {0xFF, 0xFF, 0xFF, 0x1F},
+ 4,
+ DMX_IDX_H264_PPS
+};
+
+static const struct dvb_dmx_video_patterns h264_idr = {
+ {0x00, 0x00, 0x01, 0x05, 0x80},
+ {0xFF, 0xFF, 0xFF, 0x1F, 0x80},
+ 5,
+ DMX_IDX_H264_IDR_START
+};
+
+static const struct dvb_dmx_video_patterns h264_non_idr = {
+ {0x00, 0x00, 0x01, 0x01, 0x80},
+ {0xFF, 0xFF, 0xFF, 0x1F, 0x80},
+ 5,
+ DMX_IDX_H264_NON_IDR_START
+};
+
+static const struct dvb_dmx_video_patterns vc1_seq_hdr = {
+ {0x00, 0x00, 0x01, 0x0F},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ 4,
+ DMX_IDX_VC1_SEQ_HEADER
+};
+
+static const struct dvb_dmx_video_patterns vc1_entry_point = {
+ {0x00, 0x00, 0x01, 0x0E},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ 4,
+ DMX_IDX_VC1_ENTRY_POINT
+};
+
+static const struct dvb_dmx_video_patterns vc1_frame = {
+ {0x00, 0x00, 0x01, 0x0D},
+ {0xFF, 0xFF, 0xFF, 0xFF},
+ 4,
+ DMX_IDX_VC1_FRAME_START
+};
+
+
/******************************************************************************
* static inlined helper functions
******************************************************************************/
@@ -122,6 +207,236 @@
* Software filter functions
******************************************************************************/
+/*
+ * Check if two patterns are identical, taking mask into consideration.
+ * @pattern1: the first byte pattern to compare.
+ * @pattern2: the second byte pattern to compare.
+ * @mask: the bit mask to use.
+ * @pattern_size: the length of both patterns and the mask, in bytes.
+ *
+ * Return: 1 if patterns match, 0 otherwise.
+ */
+static inline int dvb_dmx_patterns_match(const u8 *pattern1, const u8 *pattern2,
+ const u8 *mask, size_t pattern_size)
+{
+ int i;
+
+ /*
+ * Assumption: it is OK to access pattern1, pattern2 and mask.
+ * This function performs no sanity checks to keep things fast.
+ */
+
+ for (i = 0; i < pattern_size; i++)
+ if ((pattern1[i] & mask[i]) != (pattern2[i] & mask[i]))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * dvb_dmx_video_pattern_search -
+ * search for framing patterns in a given buffer.
+ *
+ * Optimized version: first search for a common substring, e.g. 0x00 0x00 0x01.
+ * If this string is found, go over all the given patterns (all must start
+ * with this string) and search for their ending in the buffer.
+ *
+ * Assumption: the patterns we look for do not spread over more than two
+ * buffers.
+ *
+ * @paterns: the full patterns information to look for.
+ * @patterns_num: the number of patterns to look for.
+ * @buf: the buffer to search.
+ * @buf_size: the size of the buffer to search. we search the entire buffer.
+ * @prefix_size_masks: a bit mask (per pattern) of possible prefix sizes to use
+ * when searching for a pattern that started at the last buffer.
+ * Updated in this function for use in the next lookup.
+ * @results: lookup results (offset, type, used_prefix_size) per found pattern,
+ * up to DVB_DMX_MAX_FOUND_PATTERNS.
+ *
+ * Return:
+ * Number of patterns found (up to DVB_DMX_MAX_FOUND_PATTERNS).
+ * 0 if pattern was not found.
+ * error value on failure.
+ */
+int dvb_dmx_video_pattern_search(
+ const struct dvb_dmx_video_patterns
+ *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM],
+ int patterns_num,
+ const u8 *buf,
+ size_t buf_size,
+ struct dvb_dmx_video_prefix_size_masks *prefix_size_masks,
+ struct dvb_dmx_video_patterns_results *results)
+{
+ int i, j;
+ unsigned int current_size;
+ u32 prefix;
+ int found = 0;
+ int start_offset = 0;
+ /* the starting common substring to look for */
+ u8 string[] = {0x00, 0x00, 0x01};
+ /* the mask for the starting string */
+ u8 string_mask[] = {0xFF, 0xFF, 0xFF};
+ /* the size of the starting string (in bytes) */
+ size_t string_size = 3;
+
+ if ((patterns == NULL) || (patterns_num <= 0) || (buf == NULL))
+ return -EINVAL;
+
+ memset(results, 0, sizeof(struct dvb_dmx_video_patterns_results));
+
+ /*
+ * handle prefix - disregard string, simply check all patterns,
+ * looking for a matching suffix at the very beginning of the buffer.
+ */
+ for (j = 0; (j < patterns_num) && !found; j++) {
+ prefix = prefix_size_masks->size_mask[j];
+ current_size = 32;
+ while (prefix) {
+ if (prefix & (0x1 << (current_size - 1))) {
+ /*
+ * check that we don't look further
+ * than buf_size boundary
+ */
+ if ((int)(patterns[j]->size - current_size) >
+ buf_size)
+ break;
+
+ if (dvb_dmx_patterns_match(
+ (patterns[j]->pattern + current_size),
+ buf, (patterns[j]->mask + current_size),
+ (patterns[j]->size - current_size))) {
+
+ /*
+ * pattern found using prefix at the
+ * very beginning of the buffer, so
+ * offset is 0, but we already zeroed
+ * everything in the beginning of the
+ * function. that's why the next line
+ * is commented.
+ */
+ /* results->info[found].offset = 0; */
+ results->info[found].type =
+ patterns[j]->type;
+ results->info[found].used_prefix_size =
+ current_size;
+ found++;
+ /*
+ * save offset to start looking from
+ * in the buffer, to avoid reusing the
+ * data of a pattern we already found.
+ */
+ start_offset = (patterns[j]->size -
+ current_size);
+
+ if (found >= DVB_DMX_MAX_FOUND_PATTERNS)
+ goto next_prefix_lookup;
+ /*
+ * we don't want to search for the same
+ * pattern with several possible prefix
+ * sizes if we have already found it,
+ * so we break from the inner loop.
+ * since we incremented 'found', we
+ * will not search for additional
+ * patterns using a prefix - that would
+ * imply ambiguous patterns where one
+ * pattern can be included in another.
+ * the for loop will exit.
+ */
+ break;
+ }
+ }
+ prefix &= ~(0x1 << (current_size - 1));
+ current_size--;
+ }
+ }
+
+ /*
+ * Search buffer for entire pattern, starting with the string.
+ * Note the external for loop does not execute if buf_size is
+ * smaller than string_size (the cast to int is required, since
+ * size_t is unsigned).
+ */
+ for (i = start_offset; i < (int)(buf_size - string_size + 1); i++) {
+ if (dvb_dmx_patterns_match(string, (buf + i), string_mask,
+ string_size)) {
+ /* now search for patterns: */
+ for (j = 0; j < patterns_num; j++) {
+ /* avoid overflow to next buffer */
+ if ((i + patterns[j]->size) > buf_size)
+ continue;
+
+ if (dvb_dmx_patterns_match(
+ (patterns[j]->pattern + string_size),
+ (buf + i + string_size),
+ (patterns[j]->mask + string_size),
+ (patterns[j]->size - string_size))) {
+
+ results->info[found].offset = i;
+ results->info[found].type =
+ patterns[j]->type;
+ /*
+ * save offset to start next prefix
+ * lookup, to avoid reusing the data
+ * of any pattern we already found.
+ */
+ if ((i + patterns[j]->size) >
+ start_offset)
+ start_offset = (i +
+ patterns[j]->size);
+ /*
+ * did not use a prefix to find this
+ * pattern, but we zeroed everything
+ * in the beginning of the function.
+ * So no need to zero used_prefix_size
+ * for results->info[found]
+ */
+
+ found++;
+ if (found >= DVB_DMX_MAX_FOUND_PATTERNS)
+ goto next_prefix_lookup;
+ /*
+ * theoretically we don't have to break
+ * here, but we don't want to search
+ * for the other matching patterns on
+ * the very same same place in the
+ * buffer. That would mean the
+ * (pattern & mask) combinations are
+ * not unique. So we break from inner
+ * loop and move on to the next place
+ * in the buffer.
+ */
+ break;
+ }
+ }
+ }
+ }
+
+next_prefix_lookup:
+ /* check for possible prefix sizes for the next buffer */
+ for (j = 0; j < patterns_num; j++) {
+ prefix_size_masks->size_mask[j] = 0;
+ for (i = 1; i < patterns[j]->size; i++) {
+ /*
+ * avoid looking outside of the buffer
+ * or reusing previously used data.
+ */
+ if (i > (buf_size - start_offset))
+ break;
+
+ if (dvb_dmx_patterns_match(patterns[j]->pattern,
+ (buf + buf_size - i),
+ patterns[j]->mask, i)) {
+ prefix_size_masks->size_mask[j] |=
+ (1 << (i - 1));
+ }
+ }
+ }
+
+ return found;
+}
+EXPORT_SYMBOL(dvb_dmx_video_pattern_search);
+
static inline int dvb_dmx_swfilter_payload(struct dvb_demux_feed *feed,
const u8 *buf)
{
@@ -434,6 +749,374 @@
return 0;
}
+static int dvb_demux_save_idx_event(struct dvb_demux_feed *feed,
+ struct dmx_index_event_info *idx_event,
+ int traverse_from_tail)
+{
+ struct dmx_index_entry *idx_entry;
+ struct dmx_index_entry *curr_entry;
+ struct list_head *pos;
+
+ /* get entry from free list */
+ if (list_empty(&feed->rec_info->idx_info.free_list)) {
+ printk(KERN_ERR "%s: index free list is empty\n", __func__);
+ return -ENOMEM;
+ }
+
+ idx_entry = list_first_entry(&feed->rec_info->idx_info.free_list,
+ struct dmx_index_entry, next);
+ list_del(&idx_entry->next);
+
+ idx_entry->event = *idx_event;
+
+ pos = &feed->rec_info->idx_info.ready_list;
+ if (traverse_from_tail) {
+ list_for_each_entry_reverse(curr_entry,
+ &feed->rec_info->idx_info.ready_list, next) {
+ if (curr_entry->event.match_tsp_num <=
+ idx_event->match_tsp_num) {
+ pos = &curr_entry->next;
+ break;
+ }
+ }
+ } else {
+ list_for_each_entry(curr_entry,
+ &feed->rec_info->idx_info.ready_list, next) {
+ if (curr_entry->event.match_tsp_num >
+ idx_event->match_tsp_num) {
+ pos = &curr_entry->next;
+ break;
+ }
+ }
+ }
+
+ if (traverse_from_tail)
+ list_add(&idx_entry->next, pos);
+ else
+ list_add_tail(&idx_entry->next, pos);
+
+ return 0;
+}
+
+int dvb_demux_push_idx_event(struct dvb_demux_feed *feed,
+ struct dmx_index_event_info *idx_event)
+{
+ int ret;
+
+ spin_lock(&feed->demux->lock);
+ ret = dvb_demux_save_idx_event(feed, idx_event, 1);
+ spin_unlock(&feed->demux->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(dvb_demux_push_idx_event);
+
+static inline void dvb_dmx_notify_indexing(struct dvb_demux_feed *feed)
+{
+ struct dmx_data_ready dmx_data_ready;
+ struct dmx_index_entry *curr_entry;
+ struct list_head *n, *pos;
+
+ dmx_data_ready.status = DMX_OK_IDX;
+
+ list_for_each_safe(pos, n, &feed->rec_info->idx_info.ready_list) {
+ curr_entry = list_entry(pos, struct dmx_index_entry, next);
+
+ if ((feed->rec_info->idx_info.min_pattern_tsp_num == (u64)-1) ||
+ (curr_entry->event.match_tsp_num <=
+ feed->rec_info->idx_info.min_pattern_tsp_num)) {
+ dmx_data_ready.idx_event = curr_entry->event;
+ feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
+ list_del(&curr_entry->next);
+ list_add_tail(&curr_entry->next,
+ &feed->rec_info->idx_info.free_list);
+ }
+ }
+}
+
+void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed)
+{
+ spin_lock(&feed->demux->lock);
+ dvb_dmx_notify_indexing(feed);
+ spin_unlock(&feed->demux->lock);
+}
+EXPORT_SYMBOL(dvb_dmx_notify_idx_events);
+
+static void dvb_dmx_process_pattern_result(struct dvb_demux_feed *feed,
+ struct dvb_dmx_video_patterns_results *patterns, int pattern,
+ u64 curr_stc, u64 prev_stc,
+ u64 curr_match_tsp, u64 prev_match_tsp,
+ u64 curr_pusi_tsp, u64 prev_pusi_tsp)
+{
+ int mpeg_frame_start;
+ int h264_frame_start;
+ int vc1_frame_start;
+ int seq_start;
+ u64 frame_end_in_seq;
+ struct dmx_index_event_info idx_event;
+
+ idx_event.pid = feed->pid;
+ if (patterns->info[pattern].used_prefix_size) {
+ idx_event.match_tsp_num = prev_match_tsp;
+ idx_event.last_pusi_tsp_num = prev_pusi_tsp;
+ idx_event.stc = prev_stc;
+ } else {
+ idx_event.match_tsp_num = curr_match_tsp;
+ idx_event.last_pusi_tsp_num = curr_pusi_tsp;
+ idx_event.stc = curr_stc;
+ }
+
+ /* notify on frame-end if needed */
+ if (feed->prev_frame_valid) {
+ if (feed->prev_frame_type & DMX_IDX_MPEG_I_FRAME_START) {
+ idx_event.type = DMX_IDX_MPEG_I_FRAME_END;
+ frame_end_in_seq = DMX_IDX_MPEG_FIRST_SEQ_FRAME_END;
+ } else if (feed->prev_frame_type & DMX_IDX_MPEG_P_FRAME_START) {
+ idx_event.type = DMX_IDX_MPEG_P_FRAME_END;
+ frame_end_in_seq = DMX_IDX_MPEG_FIRST_SEQ_FRAME_END;
+ } else if (feed->prev_frame_type & DMX_IDX_MPEG_B_FRAME_START) {
+ idx_event.type = DMX_IDX_MPEG_B_FRAME_END;
+ frame_end_in_seq = DMX_IDX_MPEG_FIRST_SEQ_FRAME_END;
+ } else if (feed->prev_frame_type & DMX_IDX_H264_IDR_START) {
+ idx_event.type = DMX_IDX_H264_IDR_END;
+ frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
+ } else if (feed->prev_frame_type & DMX_IDX_H264_NON_IDR_START) {
+ idx_event.type = DMX_IDX_H264_NON_IDR_END;
+ frame_end_in_seq = DMX_IDX_H264_FIRST_SPS_FRAME_END;
+ } else {
+ idx_event.type = DMX_IDX_VC1_FRAME_END;
+ frame_end_in_seq = DMX_IDX_VC1_FIRST_SEQ_FRAME_END;
+ }
+
+ if (feed->idx_params.types & idx_event.type)
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+
+ if (feed->first_frame_in_seq_notified &&
+ feed->idx_params.types & frame_end_in_seq) {
+ idx_event.type = frame_end_in_seq;
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ feed->first_frame_in_seq_notified = 0;
+ }
+ }
+
+ seq_start = patterns->info[pattern].type &
+ (DMX_IDX_MPEG_SEQ_HEADER | DMX_IDX_H264_SPS |
+ DMX_IDX_VC1_SEQ_HEADER);
+
+ /* did we find start of sequence/SPS? */
+ if (seq_start) {
+ feed->first_frame_in_seq = 1;
+ feed->first_frame_in_seq_notified = 0;
+ feed->prev_frame_valid = 0;
+ idx_event.type = patterns->info[pattern].type;
+ if (feed->idx_params.types & idx_event.type)
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ return;
+ }
+
+ mpeg_frame_start = patterns->info[pattern].type &
+ (DMX_IDX_MPEG_I_FRAME_START |
+ DMX_IDX_MPEG_P_FRAME_START |
+ DMX_IDX_MPEG_B_FRAME_START);
+
+ h264_frame_start = patterns->info[pattern].type &
+ (DMX_IDX_H264_IDR_START | DMX_IDX_H264_NON_IDR_START);
+
+ vc1_frame_start = patterns->info[pattern].type &
+ DMX_IDX_VC1_FRAME_START;
+
+ if (!mpeg_frame_start && !h264_frame_start && !vc1_frame_start) {
+ /* neither sequence nor frame, notify on the entry if needed */
+ idx_event.type = patterns->info[pattern].type;
+ if (feed->idx_params.types & idx_event.type)
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ feed->prev_frame_valid = 0;
+ return;
+ }
+
+ /* notify on first frame in sequence/sps if needed */
+ if (feed->first_frame_in_seq) {
+ feed->first_frame_in_seq = 0;
+ feed->first_frame_in_seq_notified = 1;
+ if (mpeg_frame_start)
+ idx_event.type = DMX_IDX_MPEG_FIRST_SEQ_FRAME_START;
+ else if (h264_frame_start)
+ idx_event.type = DMX_IDX_H264_FIRST_SPS_FRAME_START;
+ else
+ idx_event.type = DMX_IDX_VC1_FIRST_SEQ_FRAME_START;
+
+ if (feed->idx_params.types & idx_event.type)
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ }
+
+ /* notify on frame start if needed */
+ idx_event.type = patterns->info[pattern].type;
+ if (feed->idx_params.types & idx_event.type)
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+
+ feed->prev_frame_valid = 1;
+ feed->prev_frame_type = patterns->info[pattern].type;
+}
+
+void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed,
+ struct dvb_dmx_video_patterns_results *patterns, int pattern,
+ u64 curr_stc, u64 prev_stc,
+ u64 curr_match_tsp, u64 prev_match_tsp,
+ u64 curr_pusi_tsp, u64 prev_pusi_tsp)
+{
+ spin_lock(&feed->demux->lock);
+ dvb_dmx_process_pattern_result(feed,
+ patterns, pattern,
+ curr_stc, prev_stc,
+ curr_match_tsp, prev_match_tsp,
+ curr_pusi_tsp, prev_pusi_tsp);
+ spin_unlock(&feed->demux->lock);
+}
+EXPORT_SYMBOL(dvb_dmx_process_idx_pattern);
+
+static void dvb_dmx_index(struct dvb_demux_feed *feed,
+ const u8 *buf,
+ const u8 timestamp[TIMESTAMP_LEN])
+{
+ int i;
+ int p;
+ u64 stc;
+ int found_patterns;
+ int count = payload(buf);
+ u64 min_pattern_tsp_num;
+ struct dvb_demux_feed *tmp_feed;
+ struct dvb_demux *demux = feed->demux;
+ struct dmx_index_event_info idx_event;
+ struct dvb_dmx_video_patterns_results patterns;
+
+ if (feed->demux->convert_ts)
+ feed->demux->convert_ts(feed, timestamp, &stc);
+ else
+ stc = 0;
+
+ idx_event.pid = feed->pid;
+ idx_event.stc = stc;
+ idx_event.match_tsp_num = feed->rec_info->ts_output_count;
+
+ /* PUSI ? */
+ if (buf[1] & 0x40) {
+ feed->curr_pusi_tsp_num = feed->rec_info->ts_output_count;
+ if (feed->idx_params.types & DMX_IDX_PUSI) {
+ idx_event.type = DMX_IDX_PUSI;
+ idx_event.last_pusi_tsp_num =
+ feed->curr_pusi_tsp_num;
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ }
+ }
+
+ /*
+ * if we still did not encounter a TS packet with PUSI indication,
+ * we cannot report index entries yet as we need to provide
+ * the TS packet number with PUSI indication preceeding the TS
+ * packet pointed by the reported index entry.
+ */
+ if (feed->curr_pusi_tsp_num == (u64)-1) {
+ dvb_dmx_notify_indexing(feed);
+ return;
+ }
+
+ if ((feed->idx_params.types & DMX_IDX_RAI) && /* index RAI? */
+ (buf[3] & 0x20) && /* adaptation field exists? */
+ (buf[4] > 0) && /* adaptation field len > 0 ? */
+ (buf[5] & 0x40)) { /* RAI is set? */
+ idx_event.type = DMX_IDX_RAI;
+ idx_event.last_pusi_tsp_num =
+ feed->curr_pusi_tsp_num;
+ dvb_demux_save_idx_event(feed, &idx_event, 1);
+ }
+
+ /*
+ * if no pattern search is required, or the TS packet has no payload,
+ * pattern search is not executed.
+ */
+ if (!feed->pattern_num || !count) {
+ dvb_dmx_notify_indexing(feed);
+ return;
+ }
+
+ p = 188 - count; /* payload start */
+
+ found_patterns =
+ dvb_dmx_video_pattern_search(feed->patterns,
+ feed->pattern_num, &buf[p], count,
+ &feed->prefix_size, &patterns);
+
+ for (i = 0; i < found_patterns; i++)
+ dvb_dmx_process_pattern_result(feed, &patterns, i,
+ stc, feed->prev_stc,
+ feed->rec_info->ts_output_count, feed->prev_tsp_num,
+ feed->curr_pusi_tsp_num, feed->prev_pusi_tsp_num);
+
+ feed->prev_tsp_num = feed->rec_info->ts_output_count;
+ feed->prev_pusi_tsp_num = feed->curr_pusi_tsp_num;
+ feed->prev_stc = stc;
+ feed->last_pattern_tsp_num = feed->rec_info->ts_output_count;
+
+ /*
+ * it is possible to have a TS packet that has a prefix of
+ * a video pattern but the video pattern is not identified yet
+ * until we get the next TS packet of that PID. When we get
+ * the next TS packet of that PID, pattern-search would
+ * detect that we have a new index entry that starts in the
+ * previous TS packet.
+ * In order to notify the user on index entries with match_tsp_num
+ * in ascending order, index events with match_tsp_num up to
+ * the last_pattern_tsp_num are notified now to the user,
+ * the rest can't be notified now as we might hit the above
+ * scenario and cause the events not to be notified with
+ * ascending order of match_tsp_num.
+ */
+ if (feed->rec_info->idx_info.pattern_search_feeds_num == 1) {
+ /*
+ * optimization for case we have only one PID
+ * with video pattern search, in this case
+ * min_pattern_tsp_num is simply updated to the new
+ * TS packet number of the PID with pattern search.
+ */
+ feed->rec_info->idx_info.min_pattern_tsp_num =
+ feed->last_pattern_tsp_num;
+ dvb_dmx_notify_indexing(feed);
+ return;
+ }
+
+ /*
+ * if we have more than one PID with pattern search,
+ * min_pattern_tsp_num needs to be updated now based on
+ * last_pattern_tsp_num of all PIDs with pattern search.
+ */
+ min_pattern_tsp_num = (u64)-1;
+ i = feed->rec_info->idx_info.pattern_search_feeds_num;
+ list_for_each_entry(tmp_feed, &demux->feed_list, list_head) {
+ if ((tmp_feed->state != DMX_STATE_GO) ||
+ (tmp_feed->type != DMX_TYPE_TS) ||
+ (tmp_feed->feed.ts.buffer.ringbuff !=
+ feed->feed.ts.buffer.ringbuff))
+ continue;
+
+ if ((tmp_feed->last_pattern_tsp_num != (u64)-1) &&
+ ((min_pattern_tsp_num == (u64)-1) ||
+ (tmp_feed->last_pattern_tsp_num <
+ min_pattern_tsp_num)))
+ min_pattern_tsp_num = tmp_feed->last_pattern_tsp_num;
+
+ if (tmp_feed->pattern_num) {
+ i--;
+ if (i == 0)
+ break;
+ }
+ }
+
+ feed->rec_info->idx_info.min_pattern_tsp_num = min_pattern_tsp_num;
+
+ /* notify all index entries up to min_pattern_tsp_num */
+ dvb_dmx_notify_indexing(feed);
+}
+
static inline void dvb_dmx_swfilter_output_packet(
struct dvb_demux_feed *feed,
const u8 *buf,
@@ -456,6 +1139,11 @@
if (feed->tsp_out_format == DMX_TSP_FORMAT_192_TAIL)
feed->cb.ts(timestamp, TIMESTAMP_LEN, NULL,
0, &feed->feed.ts, DMX_OK);
+
+ if (feed->idx_params.enable)
+ dvb_dmx_index(feed, buf, timestamp);
+
+ feed->rec_info->ts_output_count++;
}
static inline void dvb_dmx_configure_decoder_fullness(
@@ -633,7 +1321,7 @@
((f)->feed.ts.is_filtering) && \
(((f)->ts_type & (TS_PACKET | TS_DEMUX)) == TS_PACKET))
-void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf,
+static void dvb_dmx_swfilter_one_packet(struct dvb_demux *demux, const u8 *buf,
const u8 timestamp[TIMESTAMP_LEN])
{
struct dvb_demux_feed *feed;
@@ -713,6 +1401,14 @@
dvb_dmx_swfilter_output_packet(feed, buf, timestamp);
}
}
+
+void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf,
+ const u8 timestamp[TIMESTAMP_LEN])
+{
+ spin_lock(&demux->lock);
+ dvb_dmx_swfilter_one_packet(demux, buf, timestamp);
+ spin_unlock(&demux->lock);
+}
EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf,
@@ -777,7 +1473,7 @@
while (count--) {
if (buf[0] == 0x47)
- dvb_dmx_swfilter_packet(demux, buf, timestamp);
+ dvb_dmx_swfilter_one_packet(demux, buf, timestamp);
buf += 188;
}
@@ -857,10 +1553,11 @@
if (pktsize == 192 &&
leadingbytes &&
demux->tsbuf[leadingbytes] == 0x47) /* double check */
- dvb_dmx_swfilter_packet(demux,
+ dvb_dmx_swfilter_one_packet(demux,
demux->tsbuf + TIMESTAMP_LEN, timestamp);
else if (demux->tsbuf[0] == 0x47) /* double check */
- dvb_dmx_swfilter_packet(demux, demux->tsbuf, timestamp);
+ dvb_dmx_swfilter_one_packet(demux,
+ demux->tsbuf, timestamp);
demux->tsbufp = 0;
p += j;
}
@@ -889,13 +1586,13 @@
q = &buf[p+leadingbytes];
memcpy(timestamp, &buf[p], TIMESTAMP_LEN);
} else {
- memcpy(timestamp, &buf[188], TIMESTAMP_LEN);
+ memcpy(timestamp, &buf[p+188], TIMESTAMP_LEN);
}
} else {
memset(timestamp, 0, TIMESTAMP_LEN);
}
- dvb_dmx_swfilter_packet(demux, q, timestamp);
+ dvb_dmx_swfilter_one_packet(demux, q, timestamp);
p += pktsize;
}
@@ -990,6 +1687,249 @@
return &demux->feed[i];
}
+const struct dvb_dmx_video_patterns *dvb_dmx_get_pattern(u64 dmx_idx_pattern)
+{
+ switch (dmx_idx_pattern) {
+ case DMX_IDX_MPEG_SEQ_HEADER:
+ return &mpeg2_seq_hdr;
+
+ case DMX_IDX_MPEG_GOP:
+ return &mpeg2_gop;
+
+ case DMX_IDX_MPEG_I_FRAME_START:
+ return &mpeg2_iframe;
+
+ case DMX_IDX_MPEG_P_FRAME_START:
+ return &mpeg2_pframe;
+
+ case DMX_IDX_MPEG_B_FRAME_START:
+ return &mpeg2_bframe;
+
+ case DMX_IDX_H264_SPS:
+ return &h264_sps;
+
+ case DMX_IDX_H264_PPS:
+ return &h264_pps;
+
+ case DMX_IDX_H264_IDR_START:
+ return &h264_idr;
+
+ case DMX_IDX_H264_NON_IDR_START:
+ return &h264_non_idr;
+
+ case DMX_IDX_VC1_SEQ_HEADER:
+ return &vc1_seq_hdr;
+
+ case DMX_IDX_VC1_ENTRY_POINT:
+ return &vc1_entry_point;
+
+ case DMX_IDX_VC1_FRAME_START:
+ return &vc1_frame;
+
+ default:
+ return NULL;
+ }
+}
+EXPORT_SYMBOL(dvb_dmx_get_pattern);
+
+static void dvb_dmx_init_idx_state(struct dvb_demux_feed *feed)
+{
+ feed->prev_tsp_num = (u64)-1;
+ feed->curr_pusi_tsp_num = (u64)-1;
+ feed->prev_pusi_tsp_num = (u64)-1;
+ feed->prev_frame_valid = 0;
+ feed->first_frame_in_seq = 0;
+ feed->first_frame_in_seq_notified = 0;
+ feed->last_pattern_tsp_num = (u64)-1;
+ feed->pattern_num = 0;
+ memset(&feed->prefix_size, 0,
+ sizeof(struct dvb_dmx_video_prefix_size_masks));
+
+ if (feed->idx_params.types &
+ (DMX_IDX_MPEG_SEQ_HEADER |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_START |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_END)) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_MPEG_SEQ_HEADER);
+ feed->pattern_num++;
+ }
+
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types & DMX_IDX_MPEG_GOP)) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_MPEG_GOP);
+ feed->pattern_num++;
+ }
+
+ /* MPEG2 I-frame */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_MPEG_I_FRAME_START | DMX_IDX_MPEG_I_FRAME_END |
+ DMX_IDX_MPEG_P_FRAME_END | DMX_IDX_MPEG_B_FRAME_END |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_START |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_MPEG_I_FRAME_START);
+ feed->pattern_num++;
+ }
+
+ /* MPEG2 P-frame */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_MPEG_P_FRAME_START | DMX_IDX_MPEG_P_FRAME_END |
+ DMX_IDX_MPEG_I_FRAME_END | DMX_IDX_MPEG_B_FRAME_END |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_START |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_MPEG_P_FRAME_START);
+ feed->pattern_num++;
+ }
+
+ /* MPEG2 B-frame */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_MPEG_B_FRAME_START | DMX_IDX_MPEG_B_FRAME_END |
+ DMX_IDX_MPEG_I_FRAME_END | DMX_IDX_MPEG_P_FRAME_END |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_START |
+ DMX_IDX_MPEG_FIRST_SEQ_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_MPEG_B_FRAME_START);
+ feed->pattern_num++;
+ }
+
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_H264_SPS |
+ DMX_IDX_H264_FIRST_SPS_FRAME_START |
+ DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_H264_SPS);
+ feed->pattern_num++;
+ }
+
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types & DMX_IDX_H264_PPS)) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_H264_PPS);
+ feed->pattern_num++;
+ }
+
+ /* H264 IDR */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_H264_IDR_START | DMX_IDX_H264_IDR_END |
+ DMX_IDX_H264_NON_IDR_END |
+ DMX_IDX_H264_FIRST_SPS_FRAME_END |
+ DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_H264_IDR_START);
+ feed->pattern_num++;
+ }
+
+ /* H264 non-IDR */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_H264_NON_IDR_START | DMX_IDX_H264_NON_IDR_END |
+ DMX_IDX_H264_IDR_END |
+ DMX_IDX_H264_FIRST_SPS_FRAME_END |
+ DMX_IDX_H264_FIRST_SPS_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_H264_NON_IDR_START);
+ feed->pattern_num++;
+ }
+
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_VC1_SEQ_HEADER |
+ DMX_IDX_VC1_FIRST_SEQ_FRAME_START |
+ DMX_IDX_VC1_FIRST_SEQ_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_VC1_SEQ_HEADER);
+ feed->pattern_num++;
+ }
+
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types & DMX_IDX_VC1_ENTRY_POINT)) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_VC1_ENTRY_POINT);
+ feed->pattern_num++;
+ }
+
+ /* VC1 frame */
+ if ((feed->pattern_num < DVB_DMX_MAX_SEARCH_PATTERN_NUM) &&
+ (feed->idx_params.types &
+ (DMX_IDX_VC1_FRAME_START | DMX_IDX_VC1_FRAME_END |
+ DMX_IDX_VC1_FIRST_SEQ_FRAME_START |
+ DMX_IDX_VC1_FIRST_SEQ_FRAME_END))) {
+ feed->patterns[feed->pattern_num] =
+ dvb_dmx_get_pattern(DMX_IDX_VC1_FRAME_START);
+ feed->pattern_num++;
+ }
+
+ if (feed->pattern_num)
+ feed->rec_info->idx_info.pattern_search_feeds_num++;
+}
+
+static struct dvb_demux_rec_info *dvb_dmx_alloc_rec_info(
+ struct dmx_ts_feed *ts_feed)
+{
+ int i;
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+ struct dvb_demux *demux = feed->demux;
+ struct dvb_demux_rec_info *rec_info;
+ struct dvb_demux_feed *tmp_feed;
+
+ /* check if this feed share recording buffer with other active feeds */
+ list_for_each_entry(tmp_feed, &demux->feed_list, list_head) {
+ if ((tmp_feed->state == DMX_STATE_GO) &&
+ (tmp_feed->type == DMX_TYPE_TS) &&
+ (tmp_feed != feed) &&
+ (tmp_feed->feed.ts.buffer.ringbuff ==
+ ts_feed->buffer.ringbuff)) {
+ /* indexing information is shared between the feeds */
+ tmp_feed->rec_info->ref_count++;
+ return tmp_feed->rec_info;
+ }
+ }
+
+ /* Need to allocate a new indexing info */
+ for (i = 0; i < demux->feednum; i++)
+ if (!demux->rec_info_pool[i].ref_count)
+ break;
+
+ if (i == demux->feednum)
+ return NULL;
+
+ rec_info = &demux->rec_info_pool[i];
+ rec_info->ref_count++;
+ INIT_LIST_HEAD(&rec_info->idx_info.free_list);
+ INIT_LIST_HEAD(&rec_info->idx_info.ready_list);
+
+ for (i = 0; i < DMX_IDX_EVENT_QUEUE_SIZE; i++)
+ list_add(&rec_info->idx_info.events[i].next,
+ &rec_info->idx_info.free_list);
+
+ rec_info->ts_output_count = 0;
+ rec_info->idx_info.min_pattern_tsp_num = (u64)-1;
+ rec_info->idx_info.pattern_search_feeds_num = 0;
+
+ return rec_info;
+}
+
+static void dvb_dmx_free_rec_info(struct dmx_ts_feed *ts_feed)
+{
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+
+ if (!feed->rec_info || !feed->rec_info->ref_count) {
+ printk(KERN_ERR "%s: invalid idx info state\n", __func__);
+ return;
+ }
+
+ feed->rec_info->ref_count--;
+
+ return;
+}
+
static int dvb_demux_feed_find(struct dvb_demux_feed *feed)
{
struct dvb_demux_feed *entry;
@@ -1105,7 +2045,22 @@
feed->first_cc = 1;
+ if ((feed->ts_type & TS_PACKET) &&
+ !(feed->ts_type & TS_PAYLOAD_ONLY)) {
+ feed->rec_info = dvb_dmx_alloc_rec_info(ts_feed);
+ if (!feed->rec_info) {
+ mutex_unlock(&demux->mutex);
+ return -ENOMEM;
+ }
+ dvb_dmx_init_idx_state(feed);
+ } else {
+ feed->pattern_num = 0;
+ feed->rec_info = NULL;
+ }
+
if ((ret = demux->start_feed(feed)) < 0) {
+ dvb_dmx_free_rec_info(ts_feed);
+ feed->rec_info = NULL;
mutex_unlock(&demux->mutex);
return ret;
}
@@ -1143,6 +2098,14 @@
ts_feed->is_filtering = 0;
feed->state = DMX_STATE_ALLOCATED;
spin_unlock_irq(&demux->lock);
+
+ if (feed->rec_info) {
+ if (feed->pattern_num)
+ feed->rec_info->idx_info.pattern_search_feeds_num--;
+ dvb_dmx_free_rec_info(ts_feed);
+ feed->rec_info = NULL;
+ }
+
mutex_unlock(&demux->mutex);
return ret;
@@ -1242,14 +2205,41 @@
return ret;
}
-static int dmx_ts_set_indexing_params(
+static int dmx_ts_set_video_codec(
struct dmx_ts_feed *ts_feed,
- struct dmx_indexing_video_params *params)
+ enum dmx_video_codec video_codec)
{
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
- memcpy(&feed->indexing_params, params,
- sizeof(struct dmx_indexing_video_params));
+ feed->video_codec = video_codec;
+
+ return 0;
+}
+
+static int dmx_ts_set_idx_params(struct dmx_ts_feed *ts_feed,
+ struct dmx_indexing_params *idx_params)
+{
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+ struct dvb_demux *dvbdmx = feed->demux;
+
+ mutex_lock(&dvbdmx->mutex);
+
+ if ((feed->state == DMX_STATE_GO) &&
+ !feed->rec_info) {
+ mutex_unlock(&dvbdmx->mutex);
+ return -EINVAL;
+ }
+ feed->idx_params = *idx_params;
+
+ if (feed->state == DMX_STATE_GO) {
+ spin_lock_irq(&dvbdmx->lock);
+ if (feed->pattern_num)
+ feed->rec_info->idx_info.pattern_search_feeds_num--;
+ dvb_dmx_init_idx_state(feed);
+ spin_unlock_irq(&dvbdmx->lock);
+ }
+
+ mutex_unlock(&dvbdmx->mutex);
return 0;
}
@@ -1386,8 +2376,7 @@
feed->secure_mode.is_secured = 0;
feed->buffer = NULL;
feed->tsp_out_format = DMX_TSP_FORMAT_188;
- memset(&feed->indexing_params, 0,
- sizeof(struct dmx_indexing_video_params));
+ feed->idx_params.enable = 0;
/* default behaviour - pass first PES data even if it is
* partial PES data from previous PES that we didn't receive its header.
@@ -1403,7 +2392,8 @@
(*ts_feed)->start_filtering = dmx_ts_feed_start_filtering;
(*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering;
(*ts_feed)->set = dmx_ts_feed_set;
- (*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
+ (*ts_feed)->set_video_codec = dmx_ts_set_video_codec;
+ (*ts_feed)->set_idx_params = dmx_ts_set_idx_params;
(*ts_feed)->set_tsp_out_format = dmx_ts_set_tsp_out_format;
(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
(*ts_feed)->reuse_decoder_buffer = dmx_ts_feed_reuse_decoder_buffer;
@@ -2017,6 +3007,16 @@
return -ENOMEM;
}
+ dvbdemux->rec_info_pool = vmalloc(dvbdemux->feednum *
+ sizeof(struct dvb_demux_rec_info));
+ if (!dvbdemux->rec_info_pool) {
+ vfree(dvbdemux->feed);
+ vfree(dvbdemux->filter);
+ dvbdemux->feed = NULL;
+ dvbdemux->filter = NULL;
+ return -ENOMEM;
+ }
+
dvbdemux->total_process_time = 0;
dvbdemux->total_crc_time = 0;
snprintf(dvbdemux->alias,
@@ -2045,9 +3045,12 @@
dvbdemux->filter[i].state = DMX_STATE_FREE;
dvbdemux->filter[i].index = i;
}
+
for (i = 0; i < dvbdemux->feednum; i++) {
dvbdemux->feed[i].state = DMX_STATE_FREE;
dvbdemux->feed[i].index = i;
+
+ dvbdemux->rec_info_pool[i].ref_count = 0;
}
dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
@@ -2117,6 +3120,7 @@
vfree(dvbdemux->cnt_storage);
vfree(dvbdemux->filter);
vfree(dvbdemux->feed);
+ vfree(dvbdemux->rec_info_pool);
}
EXPORT_SYMBOL(dvb_dmx_release);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index fc04219..879aad2 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -69,6 +69,88 @@
#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
+
+struct dmx_index_entry {
+ struct dmx_index_event_info event;
+ struct list_head next;
+};
+
+#define DMX_IDX_EVENT_QUEUE_SIZE 100
+struct dvb_demux_rec_info {
+ /* Reference counter for number of feeds using this information */
+ int ref_count;
+
+ /* Counter for number of TS packets output to recording buffer */
+ u64 ts_output_count;
+
+ /* Indexing information */
+ struct {
+ /*
+ * Minimum TS packet number encountered in recording filter
+ * among all feeds that search for video patterns
+ */
+ u64 min_pattern_tsp_num;
+
+ /* Number of feeds with video pattern search request */
+ u8 pattern_search_feeds_num;
+
+ /* Index entries pool */
+ struct dmx_index_entry events[DMX_IDX_EVENT_QUEUE_SIZE];
+
+ /* List of free entries that can be used for new index events */
+ struct list_head free_list;
+
+ /* List holding ready index entries not notified to user yet */
+ struct list_head ready_list;
+ } idx_info;
+};
+
+#define DVB_DMX_MAX_PATTERN_LEN 6
+struct dvb_dmx_video_patterns {
+ /* the byte pattern to look for */
+ u8 pattern[DVB_DMX_MAX_PATTERN_LEN];
+
+ /* the byte mask to use (same length as pattern) */
+ u8 mask[DVB_DMX_MAX_PATTERN_LEN];
+
+ /* the length of the pattern, in bytes */
+ size_t size;
+
+ /* the type of the pattern. One of DMX_IDX_* definitions */
+ u64 type;
+};
+
+#define DVB_DMX_MAX_FOUND_PATTERNS 20
+#define DVB_DMX_MAX_SEARCH_PATTERN_NUM 20
+struct dvb_dmx_video_prefix_size_masks {
+ /*
+ * a bit mask (per pattern) of possible prefix sizes to use
+ * when searching for a pattern that started in the previous TS packet.
+ * Updated by dvb_dmx_video_pattern_search for use in the next lookup.
+ */
+ u32 size_mask[DVB_DMX_MAX_FOUND_PATTERNS];
+};
+
+struct dvb_dmx_video_patterns_results {
+ struct {
+ /*
+ * The offset in the buffer where the pattern was found.
+ * If a pattern is found using a prefix (i.e. started on the
+ * previous buffer), offset is zero.
+ */
+ u32 offset;
+
+ /*
+ * The type of the pattern found.
+ * One of DMX_IDX_* definitions.
+ */
+ u64 type;
+
+ /* The prefix size that was used to find this pattern */
+ u32 used_prefix_size;
+ } info[DVB_DMX_MAX_FOUND_PATTERNS];
+};
+
struct dvb_demux_feed {
union {
struct dmx_ts_feed ts;
@@ -105,6 +187,21 @@
int first_cc;
int pusi_seen; /* prevents feeding of garbage from previous section */
+ struct dvb_demux_rec_info *rec_info;
+ u64 prev_tsp_num;
+ u64 prev_stc;
+ u64 curr_pusi_tsp_num;
+ u64 prev_pusi_tsp_num;
+ int prev_frame_valid;
+ u64 prev_frame_type;
+ int first_frame_in_seq;
+ int first_frame_in_seq_notified;
+ u64 last_pattern_tsp_num;
+ int pattern_num;
+ const struct dvb_dmx_video_patterns
+ *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM];
+ struct dvb_dmx_video_prefix_size_masks prefix_size;
+
u32 peslen;
u32 pes_tei_counter;
u32 pes_cont_err_counter;
@@ -113,7 +210,8 @@
struct list_head list_head;
unsigned int index; /* a unique index for each feed (can be used as hardware pid filter index) */
- struct dmx_indexing_video_params indexing_params;
+ enum dmx_video_codec video_codec;
+ struct dmx_indexing_params idx_params;
};
struct dvb_demux {
@@ -141,6 +239,9 @@
const u8 *src, size_t len);
int (*oob_command)(struct dvb_demux_feed *feed,
struct dmx_oob_command *cmd);
+ void (*convert_ts)(struct dvb_demux_feed *feed,
+ const u8 timestamp[TIMESTAMP_LEN],
+ u64 *timestampIn27Mhz);
int users;
#define MAX_DVB_DEMUX_USERS 10
@@ -178,6 +279,8 @@
dmx_section_fullness sec;
} buffer_ctrl;
+ struct dvb_demux_rec_info *rec_info_pool;
+
/*
* the following is used for debugfs exposing info
* about dvb demux performance.
@@ -204,6 +307,22 @@
enum dmx_tsp_format_t tsp_format);
void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf,
const u8 timestamp[TIMESTAMP_LEN]);
+const struct dvb_dmx_video_patterns *dvb_dmx_get_pattern(u64 dmx_idx_pattern);
+int dvb_dmx_video_pattern_search(
+ const struct dvb_dmx_video_patterns
+ *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM],
+ int patterns_num,
+ const u8 *buf, size_t buf_size,
+ struct dvb_dmx_video_prefix_size_masks *prefix_size_masks,
+ struct dvb_dmx_video_patterns_results *results);
+int dvb_demux_push_idx_event(struct dvb_demux_feed *feed,
+ struct dmx_index_event_info *idx_event);
+void dvb_dmx_process_idx_pattern(struct dvb_demux_feed *feed,
+ struct dvb_dmx_video_patterns_results *patterns, int pattern,
+ u64 curr_stc, u64 prev_stc,
+ u64 curr_match_tsp, u64 prev_match_tsp,
+ u64 curr_pusi_tsp, u64 prev_pusi_tsp);
+void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed);
/**
* dvb_dmx_is_video_feed - Returns whether the PES feed
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 802349a..71087d9 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -195,9 +195,18 @@
static int camera_v4l2_reqbufs(struct file *filep, void *fh,
struct v4l2_requestbuffers *req)
{
+ int ret;
+ struct msm_session *session;
struct camera_v4l2_private *sp = fh_to_private(fh);
-
- return vb2_reqbufs(&sp->vb2_q, req);
+ struct msm_video_device *pvdev = video_drvdata(filep);
+ unsigned int session_id = pvdev->vdev->num;
+ session = msm_session_find(session_id);
+ if (WARN_ON(!session))
+ return -EIO;
+ mutex_lock(&session->lock);
+ ret = vb2_reqbufs(&sp->vb2_q, req);
+ mutex_unlock(&session->lock);
+ return ret;
}
static int camera_v4l2_querybuf(struct file *filep, void *fh,
@@ -209,17 +218,35 @@
static int camera_v4l2_qbuf(struct file *filep, void *fh,
struct v4l2_buffer *pb)
{
+ int ret;
+ struct msm_session *session;
struct camera_v4l2_private *sp = fh_to_private(fh);
-
- return vb2_qbuf(&sp->vb2_q, pb);
+ struct msm_video_device *pvdev = video_drvdata(filep);
+ unsigned int session_id = pvdev->vdev->num;
+ session = msm_session_find(session_id);
+ if (WARN_ON(!session))
+ return -EIO;
+ mutex_lock(&session->lock);
+ ret = vb2_qbuf(&sp->vb2_q, pb);
+ mutex_unlock(&session->lock);
+ return ret;
}
static int camera_v4l2_dqbuf(struct file *filep, void *fh,
struct v4l2_buffer *pb)
{
+ int ret;
+ struct msm_session *session;
struct camera_v4l2_private *sp = fh_to_private(fh);
-
- return vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
+ struct msm_video_device *pvdev = video_drvdata(filep);
+ unsigned int session_id = pvdev->vdev->num;
+ session = msm_session_find(session_id);
+ if (WARN_ON(!session))
+ return -EIO;
+ mutex_lock(&session->lock);
+ ret = vb2_dqbuf(&sp->vb2_q, pb, filep->f_flags & O_NONBLOCK);
+ mutex_unlock(&session->lock);
+ return ret;
}
static int camera_v4l2_streamon(struct file *filep, void *fh,
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 56ec259..9f1c81a 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -30,69 +30,6 @@
#include "msm_vb2.h"
#include "msm_sd.h"
-struct msm_queue_head {
- struct list_head list;
- spinlock_t lock;
- int len;
- int max;
-};
-
-/** msm_event:
- *
- * event sent by imaging server
- **/
-struct msm_event {
- struct video_device *vdev;
- atomic_t on_heap;
-};
-
-struct msm_command {
- struct list_head list;
- struct v4l2_event event;
- atomic_t on_heap;
-};
-
-/** struct msm_command_ack
- *
- * Object of command_ack_q, which is
- * created per open operation
- *
- * contains struct msm_command
- **/
-struct msm_command_ack {
- struct list_head list;
- struct msm_queue_head command_q;
- wait_queue_head_t wait;
- int stream_id;
-};
-
-struct msm_v4l2_subdev {
- /* FIXME: for session close and error handling such
- * as daemon shutdown */
- int close_sequence;
-};
-
-struct msm_session {
- struct list_head list;
-
- /* session index */
- unsigned int session_id;
-
- /* event queue sent by imaging server */
- struct msm_event event_q;
-
- /* ACK by imaging server. Object type of
- * struct msm_command_ack per open,
- * assumption is application can send
- * command on every opened video node */
- struct msm_queue_head command_ack_q;
-
- /* real streams(either data or metadate) owned by one
- * session struct msm_stream */
- struct msm_queue_head stream_q;
- struct mutex lock;
-};
-
static struct v4l2_device *msm_v4l2_dev;
static struct msm_queue_head *msm_session_q;
@@ -248,6 +185,17 @@
return (ack->stream_id == *(unsigned int *)d2) ? 1 : 0;
}
+
+struct msm_session *msm_session_find(unsigned int session_id)
+{
+ struct msm_session *session;
+ session = msm_queue_find(msm_session_q, struct msm_session,
+ list, __msm_queue_find_session, &session_id);
+ if (WARN_ON(!session))
+ return NULL;
+ return session;
+}
+
int msm_create_stream(unsigned int session_id,
unsigned int stream_id, struct vb2_queue *q)
{
@@ -492,7 +440,7 @@
list_for_each_entry(sd, &msm_v4l2_dev->subdevs, list)
__msm_sd_close_session_streams(sd, sd_close);
spin_unlock_irqrestore(&msm_v4l2_dev->lock, flags);
-
+ INIT_LIST_HEAD(&stream->queued_list);
return 0;
}
@@ -709,7 +657,7 @@
msecs_to_jiffies(timeout));
if (list_empty_careful(&cmd_ack->command_q.list)) {
if (!rc) {
- pr_err("%s: Ankit Timed out\n", __func__);
+ pr_err("%s: Timed out\n", __func__);
rc = -ETIMEDOUT;
}
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/msm.h b/drivers/media/platform/msm/camera_v2/msm.h
index 39901ad..d57cf8d 100644
--- a/drivers/media/platform/msm/camera_v2/msm.h
+++ b/drivers/media/platform/msm/camera_v2/msm.h
@@ -38,6 +38,69 @@
atomic_t opened;
};
+struct msm_queue_head {
+ struct list_head list;
+ spinlock_t lock;
+ int len;
+ int max;
+};
+
+/** msm_event:
+ *
+ * event sent by imaging server
+ **/
+struct msm_event {
+ struct video_device *vdev;
+ atomic_t on_heap;
+};
+
+struct msm_command {
+ struct list_head list;
+ struct v4l2_event event;
+ atomic_t on_heap;
+};
+
+/** struct msm_command_ack
+ *
+ * Object of command_ack_q, which is
+ * created per open operation
+ *
+ * contains struct msm_command
+ **/
+struct msm_command_ack {
+ struct list_head list;
+ struct msm_queue_head command_q;
+ wait_queue_head_t wait;
+ int stream_id;
+};
+
+struct msm_v4l2_subdev {
+ /* FIXME: for session close and error handling such
+ * as daemon shutdown */
+ int close_sequence;
+};
+
+struct msm_session {
+ struct list_head list;
+
+ /* session index */
+ unsigned int session_id;
+
+ /* event queue sent by imaging server */
+ struct msm_event event_q;
+
+ /* ACK by imaging server. Object type of
+ * struct msm_command_ack per open,
+ * assumption is application can send
+ * command on every opened video node */
+ struct msm_queue_head command_ack_q;
+
+ /* real streams(either data or metadate) owned by one
+ * session struct msm_stream */
+ struct msm_queue_head stream_q;
+ struct mutex lock;
+};
+
int msm_post_event(struct v4l2_event *event, int timeout);
int msm_create_session(unsigned int session, struct video_device *vdev);
int msm_destroy_session(unsigned int session_id);
@@ -52,5 +115,5 @@
struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
unsigned int stream_id);
struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
-
+struct msm_session *msm_session_find(unsigned int session_id);
#endif /*_MSM_H */
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 29262af..8fa8f8d 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -48,7 +48,6 @@
}
msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
msm_vb2_buf->in_freeq = 0;
- msm_vb2_buf->stream = stream;
return 0;
}
@@ -66,7 +65,7 @@
return;
}
- stream = msm_vb2->stream;
+ stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s:%d] NULL stream", __func__, __LINE__);
return;
@@ -91,7 +90,7 @@
return -EINVAL;
}
- stream = msm_vb2->stream;
+ stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s:%d] NULL stream", __func__, __LINE__);
return -EINVAL;
@@ -122,7 +121,7 @@
return;
}
- stream = msm_vb2->stream;
+ stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s:%d] NULL stream", __func__, __LINE__);
return;
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
index 027d344..7082f85 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.h
@@ -42,7 +42,6 @@
struct vb2_buffer vb2_buf;
struct list_head list;
int in_freeq;
- struct msm_stream *stream;
};
struct msm_vb2_private_data {
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 1a481ce..431d35d 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
@@ -95,80 +95,6 @@
static int mpq_sdmx_debug;
module_param(mpq_sdmx_debug, int, S_IRUGO | S_IWUSR);
-
-/**
- * Maximum allowed framing pattern size
- */
-#define MPQ_MAX_PATTERN_SIZE 6
-
-/**
- * Number of patterns to look for when doing framing, per video standard
- */
-#define MPQ_MPEG2_PATTERN_NUM 5
-#define MPQ_H264_PATTERN_NUM 5
-#define MPQ_VC1_PATTERN_NUM 3
-
-/*
- * mpq_framing_pattern_lookup_params - framing pattern lookup parameters.
- *
- * @pattern: the byte pattern to look for.
- * @mask: the byte mask to use (same length as pattern).
- * @size: the length of the pattern, in bytes.
- * @type: the type of the pattern.
- */
-struct mpq_framing_pattern_lookup_params {
- u8 pattern[MPQ_MAX_PATTERN_SIZE];
- u8 mask[MPQ_MAX_PATTERN_SIZE];
- size_t size;
- enum dmx_framing_pattern_type type;
-};
-
-/*
- * Pre-defined video framing lookup pattern information.
- * Note: the first pattern in each patterns database must
- * be the Sequence Header (or equivalent SPS in H.264).
- * The code assumes this is the case when prepending
- * Sequence Header data in case it is required.
- */
-static const struct mpq_framing_pattern_lookup_params
- mpeg2_patterns[MPQ_MPEG2_PATTERN_NUM] = {
- {{0x00, 0x00, 0x01, 0xB3}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_MPEG2_SEQUENCE_HEADER},
- {{0x00, 0x00, 0x01, 0xB8}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_MPEG2_GOP_HEADER},
- {{0x00, 0x00, 0x01, 0x00, 0x00, 0x08},
- {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_I_PIC},
- {{0x00, 0x00, 0x01, 0x00, 0x00, 0x10},
- {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_P_PIC},
- {{0x00, 0x00, 0x01, 0x00, 0x00, 0x18},
- {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38}, 6,
- DMX_FRM_MPEG2_B_PIC}
-};
-
-static const struct mpq_framing_pattern_lookup_params
- h264_patterns[MPQ_H264_PATTERN_NUM] = {
- {{0x00, 0x00, 0x01, 0x07}, {0xFF, 0xFF, 0xFF, 0x1F}, 4,
- DMX_FRM_H264_SPS},
- {{0x00, 0x00, 0x01, 0x08}, {0xFF, 0xFF, 0xFF, 0x1F}, 4,
- DMX_FRM_H264_PPS},
- {{0x00, 0x00, 0x01, 0x05, 0x80}, {0xFF, 0xFF, 0xFF, 0x1F, 0x80}, 5,
- DMX_FRM_H264_IDR_PIC},
- {{0x00, 0x00, 0x01, 0x01, 0x80}, {0xFF, 0xFF, 0xFF, 0x1F, 0x80}, 5,
- DMX_FRM_H264_NON_IDR_PIC}
-};
-
-static const struct mpq_framing_pattern_lookup_params
- vc1_patterns[MPQ_VC1_PATTERN_NUM] = {
- {{0x00, 0x00, 0x01, 0x0F}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_SEQUENCE_HEADER},
- {{0x00, 0x00, 0x01, 0x0E}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_ENTRY_POINT_HEADER},
- {{0x00, 0x00, 0x01, 0x0D}, {0xFF, 0xFF, 0xFF, 0xFF}, 4,
- DMX_FRM_VC1_FRAME_START_CODE}
-};
-
/* Global data-structure for managing demux devices */
static struct
{
@@ -211,312 +137,74 @@
/* Check if a framing pattern is a video frame pattern or a header pattern */
static inline int mpq_dmx_is_video_frame(
- enum dmx_indexing_video_standard standard,
- enum dmx_framing_pattern_type pattern_type)
+ enum dmx_video_codec codec,
+ u64 pattern_type)
{
- switch (standard) {
- case DMX_INDEXING_MPEG2:
- if ((pattern_type == DMX_FRM_MPEG2_I_PIC) ||
- (pattern_type == DMX_FRM_MPEG2_P_PIC) ||
- (pattern_type == DMX_FRM_MPEG2_B_PIC))
+ switch (codec) {
+ case DMX_VIDEO_CODEC_MPEG2:
+ if ((pattern_type == DMX_IDX_MPEG_I_FRAME_START) ||
+ (pattern_type == DMX_IDX_MPEG_P_FRAME_START) ||
+ (pattern_type == DMX_IDX_MPEG_B_FRAME_START))
return 1;
return 0;
- case DMX_INDEXING_H264:
- if ((pattern_type == DMX_FRM_H264_IDR_PIC) ||
- (pattern_type == DMX_FRM_H264_NON_IDR_PIC))
+
+ case DMX_VIDEO_CODEC_H264:
+ if ((pattern_type == DMX_IDX_H264_IDR_START) ||
+ (pattern_type == DMX_IDX_H264_NON_IDR_START))
return 1;
return 0;
- case DMX_INDEXING_VC1:
- if (pattern_type == DMX_FRM_VC1_FRAME_START_CODE)
+
+ case DMX_VIDEO_CODEC_VC1:
+ if (pattern_type == DMX_IDX_VC1_FRAME_START)
return 1;
return 0;
+
default:
return -EINVAL;
}
}
/*
- * mpq_framing_pattern_lookup_results - framing lookup results
+ * mpq_dmx_get_pattern_params - Returns the required video
+ * patterns for framing operation based on video codec.
*
- * @offset: The offset in the buffer where the pattern was found.
- * If a pattern is found using a prefix (i.e. started on the
- * previous buffer), offset is zero.
- * @type: the type of the pattern found.
- * @used_prefix_size: the prefix size that was used to find this pattern
- */
-struct mpq_framing_pattern_lookup_results {
- struct {
- u32 offset;
- enum dmx_framing_pattern_type type;
- u32 used_prefix_size;
- } info[MPQ_MAX_FOUND_PATTERNS];
-};
-
-/*
- * Check if two patterns are identical, taking mask into consideration.
- * @pattern1: the first byte pattern to compare.
- * @pattern2: the second byte pattern to compare.
- * @mask: the bit mask to use.
- * @pattern_size: the length of both patterns and the mask, in bytes.
- *
- * Return: 1 if patterns match, 0 otherwise.
- */
-static inline int mpq_dmx_patterns_match(const u8 *pattern1, const u8 *pattern2,
- const u8 *mask, size_t pattern_size)
-{
- int i;
-
- /*
- * Assumption: it is OK to access pattern1, pattern2 and mask.
- * This function performs no sanity checks to keep things fast.
- */
-
- for (i = 0; i < pattern_size; i++)
- if ((pattern1[i] & mask[i]) != (pattern2[i] & mask[i]))
- return 0;
-
- return 1;
-}
-
-/*
- * mpq_dmx_framing_pattern_search -
- * search for framing patterns in a given buffer.
- *
- * Optimized version: first search for a common substring, e.g. 0x00 0x00 0x01.
- * If this string is found, go over all the given patterns (all must start
- * with this string) and search for their ending in the buffer.
- *
- * Assumption: the patterns we look for do not spread over more than two
- * buffers.
- *
- * @paterns: the full patterns information to look for.
- * @patterns_num: the number of patterns to look for.
- * @buf: the buffer to search.
- * @buf_size: the size of the buffer to search. we search the entire buffer.
- * @prefix_size_masks: a bit mask (per pattern) of possible prefix sizes to use
- * when searching for a pattern that started at the last buffer.
- * Updated in this function for use in the next lookup.
- * @results: lookup results (offset, type, used_prefix_size) per found pattern,
- * up to MPQ_MAX_FOUND_PATTERNS.
- *
- * Return:
- * Number of patterns found (up to MPQ_MAX_FOUND_PATTERNS).
- * 0 if pattern was not found.
- * Negative error value on failure.
- */
-static int mpq_dmx_framing_pattern_search(
- const struct mpq_framing_pattern_lookup_params *patterns,
- int patterns_num,
- const u8 *buf,
- size_t buf_size,
- struct mpq_framing_prefix_size_masks *prefix_size_masks,
- struct mpq_framing_pattern_lookup_results *results)
-{
- int i, j;
- unsigned int current_size;
- u32 prefix;
- int found = 0;
- int start_offset = 0;
- /* the starting common substring to look for */
- u8 string[] = {0x00, 0x00, 0x01};
- /* the mask for the starting string */
- u8 string_mask[] = {0xFF, 0xFF, 0xFF};
- /* the size of the starting string (in bytes) */
- size_t string_size = 3;
-
- /* sanity checks - can be commented out for optimization purposes */
- if ((patterns == NULL) || (patterns_num <= 0) || (buf == NULL)) {
- MPQ_DVB_ERR_PRINT("%s: invalid parameters\n", __func__);
- return -EINVAL;
- }
-
- memset(results, 0, sizeof(struct mpq_framing_pattern_lookup_results));
-
- /*
- * handle prefix - disregard string, simply check all patterns,
- * looking for a matching suffix at the very beginning of the buffer.
- */
- for (j = 0; (j < patterns_num) && !found; j++) {
- prefix = prefix_size_masks->size_mask[j];
- current_size = 32;
- while (prefix) {
- if (prefix & (0x1 << (current_size - 1))) {
- /*
- * check that we don't look further
- * than buf_size boundary
- */
- if ((int)(patterns[j].size - current_size) >
- buf_size)
- break;
-
- if (mpq_dmx_patterns_match(
- (patterns[j].pattern + current_size),
- buf, (patterns[j].mask + current_size),
- (patterns[j].size - current_size))) {
-
- MPQ_DVB_DBG_PRINT(
- "%s: Found matching pattern using prefix of size %d\n",
- __func__, current_size);
- /*
- * pattern found using prefix at the
- * very beginning of the buffer, so
- * offset is 0, but we already zeroed
- * everything in the beginning of the
- * function. that's why the next line
- * is commented.
- */
- /* results->info[found].offset = 0; */
- results->info[found].type =
- patterns[j].type;
- results->info[found].used_prefix_size =
- current_size;
- found++;
- /*
- * save offset to start looking from
- * in the buffer, to avoid reusing the
- * data of a pattern we already found.
- */
- start_offset = (patterns[j].size -
- current_size);
-
- if (found >= MPQ_MAX_FOUND_PATTERNS)
- goto next_prefix_lookup;
- /*
- * we don't want to search for the same
- * pattern with several possible prefix
- * sizes if we have already found it,
- * so we break from the inner loop.
- * since we incremented 'found', we
- * will not search for additional
- * patterns using a prefix - that would
- * imply ambiguous patterns where one
- * pattern can be included in another.
- * the for loop will exit.
- */
- break;
- }
- }
- prefix &= ~(0x1 << (current_size - 1));
- current_size--;
- }
- }
-
- /*
- * Search buffer for entire pattern, starting with the string.
- * Note the external for loop does not execute if buf_size is
- * smaller than string_size (the cast to int is required, since
- * size_t is unsigned).
- */
- for (i = start_offset; i < (int)(buf_size - string_size + 1); i++) {
- if (mpq_dmx_patterns_match(string, (buf + i), string_mask,
- string_size)) {
- /* now search for patterns: */
- for (j = 0; j < patterns_num; j++) {
- /* avoid overflow to next buffer */
- if ((i + patterns[j].size) > buf_size)
- continue;
-
- if (mpq_dmx_patterns_match(
- (patterns[j].pattern + string_size),
- (buf + i + string_size),
- (patterns[j].mask + string_size),
- (patterns[j].size - string_size))) {
-
- results->info[found].offset = i;
- results->info[found].type =
- patterns[j].type;
- /*
- * save offset to start next prefix
- * lookup, to avoid reusing the data
- * of any pattern we already found.
- */
- if ((i + patterns[j].size) >
- start_offset)
- start_offset = (i +
- patterns[j].size);
- /*
- * did not use a prefix to find this
- * pattern, but we zeroed everything
- * in the beginning of the function.
- * So no need to zero used_prefix_size
- * for results->info[found]
- */
-
- found++;
- if (found >= MPQ_MAX_FOUND_PATTERNS)
- goto next_prefix_lookup;
- /*
- * theoretically we don't have to break
- * here, but we don't want to search
- * for the other matching patterns on
- * the very same same place in the
- * buffer. That would mean the
- * (pattern & mask) combinations are
- * not unique. So we break from inner
- * loop and move on to the next place
- * in the buffer.
- */
- break;
- }
- }
- }
- }
-
-next_prefix_lookup:
- /* check for possible prefix sizes for the next buffer */
- for (j = 0; j < patterns_num; j++) {
- prefix_size_masks->size_mask[j] = 0;
- for (i = 1; i < patterns[j].size; i++) {
- /*
- * avoid looking outside of the buffer
- * or reusing previously used data.
- */
- if (i > (buf_size - start_offset))
- break;
-
- if (mpq_dmx_patterns_match(patterns[j].pattern,
- (buf + buf_size - i),
- patterns[j].mask, i)) {
- prefix_size_masks->size_mask[j] |=
- (1 << (i - 1));
- }
- }
- }
-
- return found;
-}
-
-/*
- * mpq_dmx_get_pattern_params -
- * get a pointer to the relevant pattern parameters structure,
- * based on the video parameters.
- *
- * @video_params: the video parameters (e.g. video standard).
- * @patterns: a pointer to a pointer to the pattern parameters,
- * updated by this function.
+ * @video_codec: the video codec.
+ * @patterns: a pointer to the pattern parameters, updated by this function.
* @patterns_num: number of patterns, updated by this function.
*/
static inline int mpq_dmx_get_pattern_params(
- struct dmx_indexing_video_params *video_params,
- const struct mpq_framing_pattern_lookup_params **patterns,
- int *patterns_num)
+ enum dmx_video_codec video_codec,
+ const struct dvb_dmx_video_patterns
+ *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM],
+ int *patterns_num)
{
- switch (video_params->standard) {
- case DMX_INDEXING_MPEG2:
- *patterns = mpeg2_patterns;
- *patterns_num = MPQ_MPEG2_PATTERN_NUM;
+ switch (video_codec) {
+ case DMX_VIDEO_CODEC_MPEG2:
+ patterns[0] = dvb_dmx_get_pattern(DMX_IDX_MPEG_SEQ_HEADER);
+ patterns[1] = dvb_dmx_get_pattern(DMX_IDX_MPEG_GOP);
+ patterns[2] = dvb_dmx_get_pattern(DMX_IDX_MPEG_I_FRAME_START);
+ patterns[3] = dvb_dmx_get_pattern(DMX_IDX_MPEG_P_FRAME_START);
+ patterns[4] = dvb_dmx_get_pattern(DMX_IDX_MPEG_B_FRAME_START);
+ *patterns_num = 5;
break;
- case DMX_INDEXING_H264:
- *patterns = h264_patterns;
- *patterns_num = MPQ_H264_PATTERN_NUM;
+
+ case DMX_VIDEO_CODEC_H264:
+ patterns[0] = dvb_dmx_get_pattern(DMX_IDX_H264_SPS);
+ patterns[1] = dvb_dmx_get_pattern(DMX_IDX_H264_PPS);
+ patterns[2] = dvb_dmx_get_pattern(DMX_IDX_H264_IDR_START);
+ patterns[3] = dvb_dmx_get_pattern(DMX_IDX_H264_NON_IDR_START);
+ *patterns_num = 4;
break;
- case DMX_INDEXING_VC1:
- *patterns = vc1_patterns;
- *patterns_num = MPQ_VC1_PATTERN_NUM;
+
+ case DMX_VIDEO_CODEC_VC1:
+ patterns[0] = dvb_dmx_get_pattern(DMX_IDX_VC1_SEQ_HEADER);
+ patterns[1] = dvb_dmx_get_pattern(DMX_IDX_VC1_ENTRY_POINT);
+ patterns[2] = dvb_dmx_get_pattern(DMX_IDX_VC1_FRAME_START);
+ *patterns_num = 3;
break;
+
default:
MPQ_DVB_ERR_PRINT("%s: invalid parameters\n", __func__);
- *patterns = NULL;
*patterns_num = 0;
return -EINVAL;
}
@@ -1648,9 +1336,9 @@
/* get and store framing information if required */
if (!mpq_dmx_info.decoder_framing) {
mpq_dmx_get_pattern_params(
- &mpq_feed->dvb_demux_feed->indexing_params,
- &feed_data->patterns, &feed_data->patterns_num);
- if (feed_data->patterns == NULL) {
+ mpq_feed->dvb_demux_feed->video_codec,
+ feed_data->patterns, &feed_data->patterns_num);
+ if (!feed_data->patterns_num) {
MPQ_DVB_ERR_PRINT(
"%s: FAILED to get framing pattern parameters\n",
__func__);
@@ -1740,10 +1428,10 @@
&feed_data->frame_offset);
feed_data->last_pattern_offset = 0;
feed_data->pending_pattern_len = 0;
- feed_data->last_framing_match_type = DMX_FRM_UNKNOWN;
+ feed_data->last_framing_match_type = 0;
feed_data->found_sequence_header_pattern = 0;
memset(&feed_data->prefix_size, 0,
- sizeof(struct mpq_framing_prefix_size_masks));
+ sizeof(struct dvb_dmx_video_prefix_size_masks));
feed_data->first_prefix_size = 0;
feed_data->saved_pts_dts_info.pts_exist = 0;
feed_data->saved_pts_dts_info.dts_exist = 0;
@@ -2613,7 +2301,7 @@
/* Report last pattern found */
if ((feed_data->pending_pattern_len) &&
- mpq_dmx_is_video_frame(feed->indexing_params.standard,
+ mpq_dmx_is_video_frame(feed->video_codec,
feed_data->last_framing_match_type)) {
meta_data.packet_type = DMX_FRAMING_INFO_PACKET;
mpq_dmx_write_pts_dts(feed_data,
@@ -2734,7 +2422,7 @@
struct mpq_demux *mpq_demux;
struct mpq_feed *mpq_feed;
- struct mpq_framing_pattern_lookup_results framing_res;
+ struct dvb_dmx_video_patterns_results framing_res;
struct mpq_streambuffer_packet_header packet;
struct mpq_adapter_video_meta_data meta_data;
int bytes_written = 0;
@@ -2864,7 +2552,7 @@
* the decoder requires demux to do framing,
* so search for the patterns now.
*/
- found_patterns = mpq_dmx_framing_pattern_search(
+ found_patterns = dvb_dmx_video_pattern_search(
feed_data->patterns,
feed_data->patterns_num,
(buf + ts_payload_offset),
@@ -2872,17 +2560,17 @@
&feed_data->prefix_size,
&framing_res);
- if (!(feed_data->found_sequence_header_pattern)) {
+ if (!feed_data->found_sequence_header_pattern) {
for (i = 0; i < found_patterns; i++) {
if ((framing_res.info[i].type ==
- DMX_FRM_MPEG2_SEQUENCE_HEADER) ||
+ DMX_IDX_MPEG_SEQ_HEADER) ||
(framing_res.info[i].type ==
- DMX_FRM_H264_SPS) ||
- (framing_res.info[i].type ==
- DMX_FRM_VC1_SEQUENCE_HEADER)) {
+ DMX_IDX_H264_SPS) ||
+ (framing_res.info[i].type ==
+ DMX_IDX_VC1_SEQ_HEADER)) {
MPQ_DVB_DBG_PRINT(
- "%s: Found Sequence Pattern, buf %p, i = %d, offset = %d, type = %d\n",
+ "%s: Found Sequence Pattern, buf %p, i = %d, offset = %d, type = %lld\n",
__func__, buf, i,
framing_res.info[i].offset,
framing_res.info[i].type);
@@ -2925,10 +2613,10 @@
if (feed_data->first_pts_dts_copy) {
for (i = first_pattern; i < found_patterns; i++) {
is_video_frame = mpq_dmx_is_video_frame(
- feed->indexing_params.standard,
+ feed->video_codec,
framing_res.info[i].type);
- if (is_video_frame) {
+ if (is_video_frame == 1) {
mpq_dmx_save_pts_dts(feed_data);
feed_data->first_pts_dts_copy = 0;
break;
@@ -2938,12 +2626,12 @@
/*
* write prefix used to find first Sequence pattern, if needed.
- * feed_data->patterns[0].pattern always contains the Sequence
- * pattern.
+ * feed_data->patterns[0]->pattern always contains the sequence
+ * header pattern.
*/
if (feed_data->first_prefix_size) {
if (mpq_streambuffer_data_write(stream_buffer,
- (feed_data->patterns[0].pattern),
+ (feed_data->patterns[0]->pattern),
feed_data->first_prefix_size) < 0) {
mpq_demux->decoder_drop_count +=
feed_data->first_prefix_size;
@@ -3045,9 +2733,8 @@
}
is_video_frame = mpq_dmx_is_video_frame(
- feed->indexing_params.standard,
+ feed->video_codec,
feed_data->last_framing_match_type);
-
if (is_video_frame == 1) {
mpq_dmx_write_pts_dts(feed_data,
&(meta_data.info.framing.pts_dts_info));
@@ -3507,6 +3194,20 @@
return ret;
}
+void mpq_dmx_convert_tts(struct dvb_demux_feed *feed,
+ const u8 timestamp[TIMESTAMP_LEN],
+ u64 *timestampIn27Mhz)
+{
+ if (unlikely(!timestampIn27Mhz))
+ return;
+
+ *timestampIn27Mhz = timestamp[2] << 16;
+ *timestampIn27Mhz += timestamp[1] << 8;
+ *timestampIn27Mhz += timestamp[0];
+ *timestampIn27Mhz *= 256; /* convert from 105.47 KHZ to 27MHz */
+}
+EXPORT_SYMBOL(mpq_dmx_convert_tts);
+
int mpq_sdmx_open_session(struct mpq_demux *mpq_demux)
{
enum sdmx_status ret = SDMX_SUCCESS;
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
index 4c2a9f4..80b5428 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.h
@@ -31,8 +31,6 @@
*/
#define TSIF_NAME_LENGTH 20
-#define MPQ_MAX_FOUND_PATTERNS 5
-
/**
* struct ts_packet_header - Transport packet header
* as defined in MPEG2 transport stream standard.
@@ -200,17 +198,6 @@
#endif
} __packed;
-/*
- * mpq_framing_prefix_size_masks - possible prefix sizes.
- *
- * @size_mask: a bit mask (per pattern) of possible prefix sizes to use
- * when searching for a pattern that started in the last buffer.
- * Updated in mpq_dmx_framing_pattern_search for use in the next lookup
- */
-struct mpq_framing_prefix_size_masks {
- u32 size_mask[MPQ_MAX_FOUND_PATTERNS];
-};
-
/**
* mpq_decoder_buffers_desc - decoder buffer(s) management information.
*
@@ -295,14 +282,15 @@
u32 pes_header_offset;
int fullness_wait_cancel;
enum mpq_adapter_stream_if stream_interface;
- const struct mpq_framing_pattern_lookup_params *patterns;
+ const struct dvb_dmx_video_patterns
+ *patterns[DVB_DMX_MAX_SEARCH_PATTERN_NUM];
int patterns_num;
u32 frame_offset;
u32 last_pattern_offset;
u32 pending_pattern_len;
- enum dmx_framing_pattern_type last_framing_match_type;
+ u64 last_framing_match_type;
int found_sequence_header_pattern;
- struct mpq_framing_prefix_size_masks prefix_size;
+ struct dvb_dmx_video_prefix_size_masks prefix_size;
u32 first_prefix_size;
struct dmx_pts_dts_info saved_pts_dts_info;
struct dmx_pts_dts_info new_pts_dts_info;
@@ -651,6 +639,20 @@
struct dmx_secure_mode *secure_mode);
/**
+ * mpq_dmx_convert_tts - Convert timestamp attached by HW to each TS
+ * packet to 27MHz.
+ *
+ * @feed: The feed with TTS attached
+ * @timestamp: Buffer holding the timestamp attached by the HW
+ * @timestampIn27Mhz: Timestamp result in 27MHz
+ *
+ * Return error code
+*/
+void mpq_dmx_convert_tts(struct dvb_demux_feed *feed,
+ const u8 timestamp[TIMESTAMP_LEN],
+ u64 *timestampIn27Mhz);
+
+/**
* mpq_sdmx_open_session - Handle the details of opening a new secure demux
* session for the specified mpq demux instance. Multiple calls to this
* is allowed, reference counting is managed to open it only when needed.
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
index 0d40520..8855e85 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tsif.c
@@ -688,6 +688,7 @@
mpq_demux->demux.reuse_decoder_buffer = mpq_dmx_reuse_decoder_buffer;
mpq_demux->demux.set_secure_mode = NULL;
mpq_demux->demux.oob_command = mpq_dmx_oob_command;
+ mpq_demux->demux.convert_ts = mpq_dmx_convert_tts;
/* Initialize dvb_demux object */
result = dvb_dmx_init(&mpq_demux->demux);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
index f0f8fa9..193141a 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v1.c
@@ -1743,6 +1743,7 @@
mpq_demux->demux.reuse_decoder_buffer = mpq_dmx_reuse_decoder_buffer;
mpq_demux->demux.set_secure_mode = mpq_dmx_set_secure_mode;
mpq_demux->demux.oob_command = mpq_dmx_oob_command;
+ mpq_demux->demux.convert_ts = mpq_dmx_convert_tts;
/* Initialize dvb_demux object */
result = dvb_dmx_init(&mpq_demux->demux);
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
index 81a2a93..c306488 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_v2.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_tspp_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
@@ -128,6 +128,7 @@
mpq_demux->demux.reuse_decoder_buffer = NULL;
mpq_demux->demux.set_secure_mode = NULL;
mpq_demux->demux.oob_command = NULL;
+ mpq_demux->demux.convert_ts = NULL;
/* Initialize dvb_demux object */
result = dvb_dmx_init(&mpq_demux->demux);
diff --git a/drivers/media/platform/msm/dvb/include/mpq_adapter.h b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
index b55f367..19abbbe 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
@@ -14,6 +14,7 @@
#define _MPQ_ADAPTER_H
#include "dvbdev.h"
+#include "dvb_demux.h"
#include "mpq_stream_buffer.h"
@@ -36,31 +37,6 @@
MPQ_ADAPTER_MAX_NUM_OF_INTERFACES,
};
-
-enum dmx_framing_pattern_type {
- /* MPEG-2 */
- DMX_FRM_MPEG2_SEQUENCE_HEADER,
- DMX_FRM_MPEG2_GOP_HEADER,
- DMX_FRM_MPEG2_I_PIC,
- DMX_FRM_MPEG2_P_PIC,
- DMX_FRM_MPEG2_B_PIC,
- /* H.264 */
- DMX_FRM_H264_SPS,
- DMX_FRM_H264_PPS,
- /* H.264 First Coded slice of an IDR Picture */
- DMX_FRM_H264_IDR_PIC,
- /* H.264 First Coded slice of a non-IDR Picture */
- DMX_FRM_H264_NON_IDR_PIC,
- /* VC-1 Sequence Header*/
- DMX_FRM_VC1_SEQUENCE_HEADER,
- /* VC-1 Entry Point Header (Advanced Profile only) */
- DMX_FRM_VC1_ENTRY_POINT_HEADER,
- /* VC-1 Frame Start Code */
- DMX_FRM_VC1_FRAME_START_CODE,
- /* Unknown or invalid framing information */
- DMX_FRM_UNKNOWN
-};
-
enum dmx_packet_type {
DMX_PES_PACKET,
DMX_FRAMING_INFO_PACKET,
@@ -83,8 +59,9 @@
};
struct dmx_framing_packet_info {
- /** framing pattern type */
- enum dmx_framing_pattern_type pattern_type;
+ /** framing pattern type, one of DMX_IDX_* definitions */
+ u64 pattern_type;
+
/** PTS/DTS information */
struct dmx_pts_dts_info pts_dts_info;
};
diff --git a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
index 3f33535..0908a6e 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -131,24 +131,24 @@
switch (meta_data.packet_type) {
case DMX_FRAMING_INFO_PACKET:
switch (meta_data.info.framing.pattern_type) {
- case DMX_FRM_H264_SPS:
- case DMX_FRM_MPEG2_SEQUENCE_HEADER:
- case DMX_FRM_VC1_SEQUENCE_HEADER:
+ case DMX_IDX_H264_SPS:
+ case DMX_IDX_MPEG_SEQ_HEADER:
+ case DMX_IDX_VC1_SEQ_HEADER:
DBG("SPS FOUND\n");
frame_found = false;
break;
- case DMX_FRM_H264_PPS:
- case DMX_FRM_MPEG2_GOP_HEADER:
- case DMX_FRM_VC1_ENTRY_POINT_HEADER:
+ case DMX_IDX_H264_PPS:
+ case DMX_IDX_MPEG_GOP:
+ case DMX_IDX_VC1_ENTRY_POINT:
DBG("PPS FOUND\n");
frame_found = false;
break;
- case DMX_FRM_H264_IDR_PIC:
- case DMX_FRM_H264_NON_IDR_PIC:
- case DMX_FRM_MPEG2_I_PIC:
- case DMX_FRM_MPEG2_P_PIC:
- case DMX_FRM_MPEG2_B_PIC:
- case DMX_FRM_VC1_FRAME_START_CODE:
+ case DMX_IDX_H264_IDR_START:
+ case DMX_IDX_H264_NON_IDR_START:
+ case DMX_IDX_MPEG_I_FRAME_START:
+ case DMX_IDX_MPEG_P_FRAME_START:
+ case DMX_IDX_MPEG_B_FRAME_START:
+ case DMX_IDX_VC1_FRAME_START:
DBG("FRAME FOUND\n");
frame_found = true;
break;
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index f46abcf..ef3e698 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1183,6 +1183,24 @@
pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
}
+ case HAL_PARAM_VENC_H264_VUI_TIMING_INFO:
+ {
+ struct hfi_h264_vui_timing_info *hfi;
+ struct hal_h264_vui_timing_info *timing_info = pdata;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
+
+ hfi = (struct hfi_h264_vui_timing_info *)&pkt->
+ rg_property_data[1];
+ hfi->enable = timing_info->enable;
+ hfi->fixed_frame_rate = timing_info->fixed_frame_rate;
+ hfi->time_scale = timing_info->time_scale;
+
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_h264_vui_timing_info);
+ break;
+ }
case HAL_CONFIG_VPE_DEINTERLACE:
break;
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
@@ -1213,6 +1231,7 @@
case HAL_PARAM_VENC_LOW_LATENCY:
default:
dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x", ptype);
+ rc = -ENOTSUPP;
break;
}
return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index eca8091..f458a0a 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -241,7 +241,7 @@
static u32 get_frame_size_compressed(int plane,
u32 height, u32 width)
{
- return (width * height * 3/2)/2;
+ return (width * height * 3/2)/4;
}
struct msm_vidc_format vdec_formats[] = {
@@ -1280,7 +1280,7 @@
break;
}
- if (property_id) {
+ if (!rc && property_id) {
dprintk(VIDC_DBG,
"Control: HAL property=%d,ctrl_id=%d,ctrl_value=%d\n",
property_id,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 160d450..da97c7a 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -131,7 +131,7 @@
.step = 1,
.menu_skip_mask = 0,
.qmenu = NULL,
- .cluster = 0,
+ .cluster = MSM_VENC_CTRL_CLUSTER_TIMING,
},
{
.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD,
@@ -209,7 +209,8 @@
(1 << V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR)
),
.qmenu = mpeg_video_rate_control,
- .cluster = MSM_VENC_CTRL_CLUSTER_BITRATE,
+ .cluster = MSM_VENC_CTRL_CLUSTER_BITRATE |
+ MSM_VENC_CTRL_CLUSTER_TIMING,
},
{
.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
@@ -630,6 +631,16 @@
.qmenu = mpeg_video_vidc_extradata,
.step = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO,
+ .name = "H264 VUI Timing Info",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED,
+ .default_value =
+ V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED,
+ .cluster = MSM_VENC_CTRL_CLUSTER_TIMING,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -1117,8 +1128,9 @@
struct hal_multi_slice_control multi_slice_control;
struct hal_h264_db_control h264_db_control;
struct hal_enable enable;
+ struct hal_h264_vui_timing_info vui_timing_info;
u32 property_id = 0, property_val = 0;
- void *pdata;
+ void *pdata = NULL;
struct v4l2_ctrl *temp_ctrl = NULL;
struct hfi_device *hdev;
@@ -1625,14 +1637,57 @@
pdata = &extra;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO:
+ {
+ struct v4l2_ctrl *rc_mode, *frame_rate;
+ bool cfr = false;
+
+ property_id = HAL_PARAM_VENC_H264_VUI_TIMING_INFO;
+ rc_mode = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
+ frame_rate = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE);
+
+ switch (rc_mode->val) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
+ cfr = true;
+ break;
+ default:
+ cfr = false;
+ break;
+ }
+
+ switch (ctrl->val) {
+ case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_DISABLED:
+ vui_timing_info.enable = 0;
+ break;
+ case V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED:
+ /* Only support this in CFR mode because we
+ * don't really know how to fill out vui_timing_info.
+ * time_scale in vfr mode. The assumed framerate
+ * might be incorrect. */
+ if (!cfr) {
+ dprintk(VIDC_ERR, "Can't set %x in VFR mode\n",
+ ctrl->id);
+ rc = -ENOTSUPP;
+ break;
+ }
+
+ vui_timing_info.enable = 1;
+ vui_timing_info.fixed_frame_rate = cfr;
+ vui_timing_info.time_scale = frame_rate->val;
+ }
+
+ pdata = &vui_timing_info;
+ break;
+ }
default:
rc = -ENOTSUPP;
break;
}
#undef TRY_GET_CTRL
- if (property_id) {
- dprintk(VIDC_DBG, "Control: HAL property=%d,ctrl_value=%d\n",
+ if (!rc && property_id) {
+ dprintk(VIDC_DBG, "Control: HAL property=%x,ctrl_value=%d\n",
property_id,
ctrl->val);
rc = call_hfi_op(hdev, session_set_property,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 3b82666..3729c3a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -167,6 +167,7 @@
HAL_PARAM_VDEC_SYNC_FRAME_DECODE,
HAL_PARAM_VENC_H264_ENTROPY_CABAC_MODEL,
HAL_CONFIG_VENC_MAX_BITRATE,
+ HAL_PARAM_VENC_H264_VUI_TIMING_INFO,
};
enum hal_domain {
@@ -765,6 +766,13 @@
u32 time_stamp_scale;
};
+
+struct hal_h264_vui_timing_info {
+ u32 enable;
+ u32 fixed_frame_rate;
+ u32 time_scale;
+};
+
enum vidc_resource_id {
VIDC_RESOURCE_OCMEM = 0x00000001,
VIDC_UNUSED_RESORUCE = 0x10000000,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index baf7bc4..2d0c3bd 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -294,9 +294,16 @@
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x019)
#define HFI_PROPERTY_PARAM_VENC_HIER_P_NUM_ENH_LAYER \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01A)
-
#define HFI_PROPERTY_PARAM_VENC_H264_NAL_SVC_EXT \
(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01B)
+#define HFI_PROPERTY_PARAM_VENC_H264_LTRMODE \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01C)
+#define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01D)
+#define HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01E)
+#define HFI_PROPERTY_PARAM_VENC_VC1_PERF_CFG \
+ (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01F)
#define HFI_PROPERTY_CONFIG_VENC_COMMON_START \
(HFI_DOMAIN_BASE_VENC + HFI_ARCH_COMMON_OFFSET + 0x6000)
@@ -500,6 +507,12 @@
u32 height;
};
+struct hfi_h264_vui_timing_info {
+ u32 enable;
+ u32 fixed_frame_rate;
+ u32 time_scale;
+};
+
#define HFI_COLOR_FORMAT_MONOCHROME (HFI_COMMON_BASE + 0x1)
#define HFI_COLOR_FORMAT_NV12 (HFI_COMMON_BASE + 0x2)
#define HFI_COLOR_FORMAT_NV21 (HFI_COMMON_BASE + 0x3)
@@ -883,5 +896,4 @@
u32 packet_type;
u32 trigger_type;
};
-
#endif
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index b719b3f..4f7fb44 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -28,6 +28,7 @@
#define BUF_TYPE_INPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
static struct ion_client *venc_ion_client;
+static long venc_secure(struct v4l2_subdev *sd);
struct index_bitmap {
unsigned long *bitmap;
@@ -321,8 +322,9 @@
goto venc_open_fail;
}
- inst->secure = false;
inst->vmops = *vmops;
+ inst->secure = vmops->secure; /* We need to inform vidc, but defer
+ until after s_fmt() */
INIT_LIST_HEAD(&inst->registered_output_bufs.list);
INIT_LIST_HEAD(&inst->registered_input_bufs.list);
init_completion(&inst->dq_complete);
@@ -903,6 +905,15 @@
WFD_MSG_ERR("Failed to format for input port\n");
goto venc_set_format_fail;
}
+
+ /* If the device was secured previously, we need to inform vidc _now_ */
+ if (inst->secure) {
+ rc = venc_secure(sd);
+ if (rc) {
+ WFD_MSG_ERR("Failed secure vidc\n");
+ goto venc_set_format_fail;
+ }
+ }
venc_set_format_fail:
return rc;
}
@@ -1329,12 +1340,6 @@
rc = -EEXIST;
}
- if (inst->secure) {
- /* Nothing to do! */
- rc = 0;
- goto secure_fail;
- }
-
ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_SECURE;
rc = msm_vidc_s_ctrl(inst->vidc_context, &ctrl);
if (rc) {
@@ -1342,7 +1347,6 @@
goto secure_fail;
}
- inst->secure = true;
secure_fail:
return rc;
}
@@ -1419,9 +1423,6 @@
case SET_FRAMERATE_MODE:
rc = venc_set_framerate_mode(sd, arg);
break;
- case ENC_SECURE:
- rc = venc_secure(sd);
- break;
default:
WFD_MSG_ERR("Unknown ioctl %d to enc-subdev\n", cmd);
rc = -ENOTSUPP;
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 16de0d4..55386b9 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -26,6 +26,8 @@
struct switch_dev sdev;
};
+static int mdp_secure(struct v4l2_subdev *sd, void *arg);
+
int mdp_init(struct v4l2_subdev *sd, u32 val)
{
return 0;
@@ -47,10 +49,6 @@
WFD_MSG_ERR("Invalid arguments\n");
rc = -EINVAL;
goto mdp_open_fail;
- } else if (mops->secure) {
- /* Deprecated API; use MDP_SECURE ioctl */
- WFD_MSG_ERR("Deprecated API for securing subdevice\n");
- return -ENOTSUPP;
}
fbi = msm_fb_get_writeback_fb();
@@ -66,12 +64,25 @@
WFD_MSG_ERR("WFD switch registration failed\n");
goto mdp_open_fail;
}
+
msm_fb_writeback_init(fbi);
+
inst->mdp = fbi;
inst->secure = mops->secure;
+ if (mops->secure) {
+ rc = mdp_secure(sd, inst);
+ if (rc) {
+ WFD_MSG_ERR("Couldn't secure MDP\n");
+ goto mdp_secure_fail;
+ }
+ }
+
mops->cookie = inst;
- return rc;
+ return 0;
+mdp_secure_fail:
+ switch_dev_unregister(&inst->sdev);
+ msm_fb_writeback_terminate(inst->mdp);
mdp_open_fail:
kfree(inst);
return rc;
@@ -118,7 +129,8 @@
}
return 0;
}
-int mdp_close(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_close(struct v4l2_subdev *sd, void *arg)
{
struct mdp_instance *inst = arg;
struct fb_info *fbi = NULL;
@@ -133,7 +145,8 @@
}
return 0;
}
-int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
{
int rc = 0;
struct mdp_buf_info *binfo = arg;
@@ -161,7 +174,8 @@
WFD_MSG_ERR("Failed to queue buffer\n");
return rc;
}
-int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
{
int rc = 0;
struct mdp_buf_info *obuf = arg;
@@ -184,7 +198,8 @@
obuf->cookie = (void *)fbdata.priv;
return rc;
}
-int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
+
+static int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
{
struct mdp_prop *prop = (struct mdp_prop *)arg;
struct mdp_instance *inst = prop->inst;
@@ -197,7 +212,7 @@
return 0;
}
-int mdp_mmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_mmap(struct v4l2_subdev *sd, void *arg)
{
int rc = 0, align = 0;
struct mem_region_map *mmap = arg;
@@ -250,7 +265,7 @@
return rc;
}
-int mdp_munmap(struct v4l2_subdev *sd, void *arg)
+static int mdp_munmap(struct v4l2_subdev *sd, void *arg)
{
struct mem_region_map *mmap = arg;
struct mem_region *mregion;
@@ -278,7 +293,7 @@
return 0;
}
-int mdp_secure(struct v4l2_subdev *sd, void *arg)
+static int mdp_secure(struct v4l2_subdev *sd, void *arg)
{
struct mdp_instance *inst = NULL;
int rc = 0;
@@ -331,9 +346,6 @@
case MDP_MUNMAP:
rc = mdp_munmap(sd, arg);
break;
- case MDP_SECURE:
- rc = mdp_secure(sd, arg);
- break;
default:
WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
rc = -EINVAL;
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 1d3c9f55..af3cd69 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -1040,30 +1040,9 @@
{
int rc = 0;
struct wfd_device *wfd_dev = video_drvdata(filp);
- struct wfd_inst *inst = file_to_inst(filp);
- switch (a->id) {
- case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
- ioctl, ENC_SECURE, NULL);
- if (rc) {
- WFD_MSG_ERR("Couldn't secure encoder");
- break;
- }
-
- rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core,
- ioctl, MDP_SECURE, (void *)inst->mdp_inst);
- if (rc) {
- WFD_MSG_ERR("Couldn't secure MDP");
- break;
- }
-
- wfd_dev->secure = true;
- break;
- default:
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
- ioctl, SET_PROP, a);
- }
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core,
+ ioctl, SET_PROP, a);
if (rc)
WFD_MSG_ERR("Failed to set encoder property\n");
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 188ac32..c02eecf 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -157,8 +157,6 @@
uint32_t user_virt_sb_base;
size_t sb_length;
struct ion_handle *ihandle; /* Retrieve phy addr */
- bool perf_enabled;
- bool fast_load_enabled;
};
struct qseecom_listener_handle {
@@ -177,6 +175,8 @@
int abort;
wait_queue_head_t abort_wq;
atomic_t ioctl_count;
+ bool perf_enabled;
+ bool fast_load_enabled;
};
enum qseecom_set_clear_key_flag {
@@ -1789,9 +1789,9 @@
pr_err("Unable to find the handle, exiting\n");
else
ret = qseecom_unload_app(data);
- if (data->client.fast_load_enabled == true)
+ if (data->fast_load_enabled == true)
qsee_disable_clock_vote(data, CLK_SFPB);
- if (data->client.perf_enabled == true)
+ if (data->perf_enabled == true)
qsee_disable_clock_vote(data, CLK_DFAB);
if (ret == 0) {
kzfree(data);
@@ -1972,11 +1972,11 @@
ret);
else {
qseecom.qsee_bw_count++;
- data->client.perf_enabled = true;
+ data->perf_enabled = true;
}
} else {
qseecom.qsee_bw_count++;
- data->client.perf_enabled = true;
+ data->perf_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -2004,11 +2004,11 @@
ret);
else {
qseecom.qsee_sfpb_bw_count++;
- data->client.fast_load_enabled = true;
+ data->fast_load_enabled = true;
}
} else {
qseecom.qsee_sfpb_bw_count++;
- data->client.fast_load_enabled = true;
+ data->fast_load_enabled = true;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -2053,11 +2053,11 @@
ret);
else {
qseecom.qsee_bw_count--;
- data->client.perf_enabled = false;
+ data->perf_enabled = false;
}
} else {
qseecom.qsee_bw_count--;
- data->client.perf_enabled = false;
+ data->perf_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -2083,11 +2083,11 @@
ret);
else {
qseecom.qsee_sfpb_bw_count--;
- data->client.fast_load_enabled = false;
+ data->fast_load_enabled = false;
}
} else {
qseecom.qsee_sfpb_bw_count--;
- data->client.fast_load_enabled = false;
+ data->fast_load_enabled = false;
}
mutex_unlock(&qsee_bw_mutex);
break;
@@ -2853,9 +2853,9 @@
}
}
- if (data->client.fast_load_enabled == true)
+ if (data->fast_load_enabled == true)
qsee_disable_clock_vote(data, CLK_SFPB);
- if (data->client.perf_enabled == true)
+ if (data->perf_enabled == true)
qsee_disable_clock_vote(data, CLK_DFAB);
if (qseecom.qseos_version == QSEOS_VERSION_13) {
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index b075435..5b7f08f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -646,6 +646,7 @@
mrq.cmd = &cmd;
+ mmc_rpm_hold(card->host, &card->dev);
mmc_claim_host(card->host);
err = mmc_blk_part_switch(card, md);
@@ -695,6 +696,7 @@
cmd_rel_host:
mmc_release_host(card->host);
+ mmc_rpm_release(card->host, &card->dev);
cmd_done:
mmc_blk_put(md);
@@ -775,6 +777,7 @@
goto idata_free;
}
+ mmc_rpm_hold(card->host, &card->dev);
mmc_claim_host(card->host);
err = mmc_blk_part_switch(card, md);
@@ -871,6 +874,7 @@
cmd_rel_host:
mmc_release_host(card->host);
+ mmc_rpm_release(card->host, &card->dev);
idata_free:
for (i = 0; i < MMC_IOC_MAX_RPMB_CMD; i++) {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d339d81..73a1b41 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -167,10 +167,12 @@
static inline void mmc_update_clk_scaling(struct mmc_host *host)
{
- if (host->clk_scaling.enable)
+ if (host->clk_scaling.enable) {
host->clk_scaling.busy_time_us +=
ktime_to_us(ktime_sub(ktime_get(),
host->clk_scaling.start_busy));
+ host->clk_scaling.start_busy = ktime_get();
+ }
}
/**
* mmc_request_done - finish processing an MMC request
@@ -811,6 +813,12 @@
context_info->is_urgent = false;
context_info->is_new_req = false;
if (mmc_should_stop_curr_req(host)) {
+ /*
+ * We are going to stop the ongoing request.
+ * Update stuff that we ought to do when the
+ * request actually completes.
+ */
+ mmc_update_clk_scaling(host);
err = mmc_stop_request(host);
if (err && !context_info->is_done_rcv) {
err = MMC_BLK_ABORT;
@@ -823,14 +831,6 @@
context_info->is_done_rcv = false;
break; /* return err */
} else {
- /*
- * We have stopped the ongoing request
- * and are sure that mmc_request_done()
- * is not going to get called. Update
- * stuff that we ought to do when the
- * request actually completes.
- */
- mmc_update_clk_scaling(host);
mmc_host_clk_release(host);
}
err = host->areq->update_interrupted_req(
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2038d3d..6b392b9 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2416,6 +2416,9 @@
goto out;
}
+ if (msm_host->msm_bus_vote.client_handle)
+ sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
+
return sdhci_msm_runtime_suspend(dev);
out:
return ret;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index d58379f..904c255 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1094,6 +1094,8 @@
cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
flags |= SDHCI_CMD_DATA;
+ if (cmd->data)
+ host->data_start_time = ktime_get();
sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}
@@ -2361,7 +2363,6 @@
sdhci_finish_command(host);
}
-#ifdef CONFIG_MMC_DEBUG
static void sdhci_show_adma_error(struct sdhci_host *host)
{
const char *name = mmc_hostname(host->mmc);
@@ -2377,7 +2378,7 @@
len = (__le16 *)(desc + 2);
attr = *desc;
- DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+ pr_info("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
name, desc, le32_to_cpu(*dma), le16_to_cpu(*len), attr);
desc += 8;
@@ -2386,9 +2387,6 @@
break;
}
}
-#else
-static void sdhci_show_adma_error(struct sdhci_host *host) { }
-#endif
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
@@ -2453,9 +2451,10 @@
pr_msg = true;
}
if (pr_msg) {
- pr_err("%s: data txfr (0x%08x) error: %d\n",
+ pr_err("%s: data txfr (0x%08x) error: %d after %lld ms\n",
mmc_hostname(host->mmc), intmask,
- host->data->error);
+ host->data->error, ktime_to_ms(ktime_sub(
+ ktime_get(), host->data_start_time)));
sdhci_dumpregs(host);
}
sdhci_finish_data(host);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 0158235..44465dc 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -91,9 +91,6 @@
#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
@@ -200,7 +197,6 @@
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,
@@ -334,10 +330,6 @@
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;
@@ -1191,20 +1183,11 @@
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/qpnp-pwm.c b/drivers/platform/msm/qpnp-pwm.c
index 1729b49..52c523e 100644
--- a/drivers/platform/msm/qpnp-pwm.c
+++ b/drivers/platform/msm/qpnp-pwm.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
@@ -463,7 +463,7 @@
int i, pwm_size, rc = 0;
int burst_size = SPMI_MAX_BUF_LEN;
int list_len = lut->list_len << 1;
- int offset = lut->lo_index << 1;
+ int offset = (lut->lo_index << 1) - 2;
pwm_size = QPNP_GET_PWM_SIZE(
chip->qpnp_lpg_registers[QPNP_LPG_PWM_SIZE_CLK]) &
@@ -1024,8 +1024,8 @@
raw_lut = 1;
lut_config->list_len = len;
- lut_config->lo_index = start_idx;
- lut_config->hi_index = start_idx + len - 1;
+ lut_config->lo_index = start_idx + 1;
+ lut_config->hi_index = start_idx + len;
rc = qpnp_lpg_change_table(pwm, duty_pct, raw_lut);
if (rc) {
@@ -1041,13 +1041,13 @@
QPNP_SET_PAUSE_CNT(lut_config->lut_pause_lo_cnt,
lut_params.lut_pause_lo, ramp_step_ms);
- if (lut_config->lut_pause_lo_cnt > PM_PWM_LUT_PAUSE_MAX)
- lut_config->lut_pause_lo_cnt = PM_PWM_LUT_PAUSE_MAX;
+ if (lut_config->lut_pause_lo_cnt > PM_PWM_MAX_PAUSE_CNT)
+ lut_config->lut_pause_lo_cnt = PM_PWM_MAX_PAUSE_CNT;
QPNP_SET_PAUSE_CNT(lut_config->lut_pause_hi_cnt,
lut_params.lut_pause_hi, ramp_step_ms);
- if (lut_config->lut_pause_hi_cnt > PM_PWM_LUT_PAUSE_MAX)
- lut_config->lut_pause_hi_cnt = PM_PWM_LUT_PAUSE_MAX;
+ if (lut_config->lut_pause_hi_cnt > PM_PWM_MAX_PAUSE_CNT)
+ lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT;
lut_config->ramp_step_ms = ramp_step_ms;
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 47108c6..6412fc0 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -886,6 +886,12 @@
(u32) base, status);
bam_output_register_content(base);
*cb_case = SPS_CALLBACK_BAM_HRESP_ERR_IRQ;
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ } else if (status & IRQ_STTS_BAM_TIMER_IRQ) {
+ SPS_DBG1("sps:bam 0x%x(va);receive BAM_TIMER_IRQ\n",
+ (u32) base);
+ *cb_case = SPS_CALLBACK_BAM_TIMER_IRQ;
+#endif
} else
SPS_INFO("sps:bam 0x%x(va);bam irq status="
"0x%x.", (u32) base, status);
@@ -1126,9 +1132,25 @@
void bam_pipe_timer_config(void *base, u32 pipe, enum bam_pipe_timer_mode mode,
u32 timeout_count)
{
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_MODE, mode);
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_TRSHLD,
- timeout_count);
+ u32 for_all_pipes = 0;
+
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ for_all_pipes = bam_read_reg_field(base, REVISION,
+ BAM_NUM_INACTIV_TMRS);
+#endif
+
+ if (for_all_pipes) {
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_MODE, mode);
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_TRSHLD,
+ timeout_count);
+#endif
+ } else {
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_MODE,
+ mode);
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_TRSHLD,
+ timeout_count);
+ }
}
/**
@@ -1137,10 +1159,26 @@
*/
void bam_pipe_timer_reset(void *base, u32 pipe)
{
- /* reset */
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 0);
- /* active */
- bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 1);
+ u32 for_all_pipes = 0;
+
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ for_all_pipes = bam_read_reg_field(base, REVISION,
+ BAM_NUM_INACTIV_TMRS);
+#endif
+
+ if (for_all_pipes) {
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ /* reset */
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_RST, 0);
+ /* active */
+ bam_write_reg_field(base, TIMER_CTRL, TIMER_RST, 1);
+#endif
+ } else {
+ /* reset */
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 0);
+ /* active */
+ bam_write_reg_field(base, P_TIMER_CTRL(pipe), P_TIMER_RST, 1);
+ }
}
/**
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index cda1717..23c346a 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2232,8 +2232,7 @@
SPS_ERR("sps:%s:timer_ctrl pointer is NULL.\n", __func__);
return SPS_ERROR;
} else if (timer_result == NULL) {
- SPS_ERR("sps:%s:result pointer is NULL.\n", __func__);
- return SPS_ERROR;
+ SPS_DBG("sps:%s:no result to return.\n", __func__);
}
bam = sps_bam_lock(pipe);
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index a84d99e..80056f5 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -24,7 +24,8 @@
#include "spsi.h"
/* All BAM global IRQ sources */
-#define BAM_IRQ_ALL (BAM_DEV_IRQ_HRESP_ERROR | BAM_DEV_IRQ_ERROR)
+#define BAM_IRQ_ALL (BAM_DEV_IRQ_HRESP_ERROR | BAM_DEV_IRQ_ERROR | \
+ BAM_DEV_IRQ_TIMER)
/* BAM device state flags */
#define BAM_STATE_INIT (1UL << 1)
@@ -145,7 +146,7 @@
BAM_ID(dev), source, mask);
if ((source & (1UL << 31)) && (dev->props.callback)) {
- SPS_INFO("sps:bam_isr:bam=0x%x;callback for case %d.\n",
+ SPS_DBG1("sps:bam_isr:bam=0x%x;callback for case %d.\n",
BAM_ID(dev), cb_case);
dev->props.callback(cb_case, dev->props.user);
}
@@ -2027,7 +2028,7 @@
BAM_PIPE_TIMER_ONESHOT :
BAM_PIPE_TIMER_PERIODIC;
bam_pipe_timer_config(dev->base, pipe_index, mode,
- timer_ctrl->timeout_msec * 10);
+ timer_ctrl->timeout_msec * 8);
break;
case SPS_TIMER_OP_RESET:
bam_pipe_timer_reset(dev->base, pipe_index);
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index bbc0373..dede487 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.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
@@ -32,6 +32,7 @@
BAM_DEV_IRQ_RDY_TO_SLEEP = 0x00000001,
BAM_DEV_IRQ_HRESP_ERROR = 0x00000002,
BAM_DEV_IRQ_ERROR = 0x00000004,
+ BAM_DEV_IRQ_TIMER = 0x00000010,
};
/* Pipe interrupt mask */
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index ee80975..9ba954a 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -1504,11 +1504,10 @@
},
};
-static int __init tsens_tm_init_driver(void)
+int __init tsens_tm_init_driver(void)
{
return platform_driver_register(&tsens_tm_driver);
}
-arch_initcall(tsens_tm_init_driver);
static int __init tsens_thermal_register(void)
{
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index 5aca48d..12ac3bc 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -23,17 +23,447 @@
#include <linux/msm_thermal.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
#include <mach/cpufreq.h>
+#include <mach/rpm-regulator.h>
+#include <mach/rpm-regulator-smd.h>
+#include <linux/regulator/consumer.h>
-static int enabled;
+#define MAX_RAILS 5
+
static struct msm_thermal_data msm_thermal_info;
static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT;
static struct delayed_work check_temp_work;
+static bool core_control_enabled;
+static uint32_t cpus_offlined;
+static DEFINE_MUTEX(core_control_mutex);
+static int enabled;
+static int rails_cnt;
+static int psm_rails_cnt;
static int limit_idx;
static int limit_idx_low;
static int limit_idx_high;
+static int max_tsens_num;
static struct cpufreq_frequency_table *table;
+static uint32_t usefreq;
+static int freq_table_get;
+static bool vdd_rstr_enabled;
+static bool vdd_rstr_nodes_called;
+static bool vdd_rstr_probed;
+static bool psm_enabled;
+static bool psm_nodes_called;
+static bool psm_probed;
+static DEFINE_MUTEX(vdd_rstr_mutex);
+static DEFINE_MUTEX(psm_mutex);
+
+struct rail {
+ const char *name;
+ uint32_t freq_req;
+ uint32_t min_level;
+ uint32_t num_levels;
+ uint32_t curr_level;
+ uint32_t levels[3];
+ struct kobj_attribute value_attr;
+ struct kobj_attribute level_attr;
+ struct regulator *reg;
+ struct attribute_group attr_gp;
+};
+
+struct psm_rail {
+ const char *name;
+ uint8_t init;
+ uint8_t mode;
+ struct kobj_attribute mode_attr;
+ struct rpm_regulator *reg;
+ struct attribute_group attr_gp;
+};
+
+static struct psm_rail *psm_rails;
+static struct rail *rails;
+
+struct vdd_rstr_enable {
+ struct kobj_attribute ko_attr;
+ uint32_t enabled;
+};
+
+/* For SMPS only*/
+enum PMIC_SW_MODE {
+ PMIC_AUTO_MODE = RPM_REGULATOR_MODE_AUTO,
+ PMIC_IPEAK_MODE = RPM_REGULATOR_MODE_IPEAK,
+ PMIC_PWM_MODE = RPM_REGULATOR_MODE_HPM,
+};
+
+#define VDD_RES_RO_ATTRIB(_rail, ko_attr, j, _name) \
+ ko_attr.attr.name = __stringify(_name); \
+ ko_attr.attr.mode = 444; \
+ ko_attr.show = vdd_rstr_reg_##_name##_show; \
+ ko_attr.store = NULL; \
+ _rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define VDD_RES_RW_ATTRIB(_rail, ko_attr, j, _name) \
+ ko_attr.attr.name = __stringify(_name); \
+ ko_attr.attr.mode = 644; \
+ ko_attr.show = vdd_rstr_reg_##_name##_show; \
+ ko_attr.store = vdd_rstr_reg_##_name##_store; \
+ _rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define VDD_RSTR_ENABLE_FROM_ATTRIBS(attr) \
+ (container_of(attr, struct vdd_rstr_enable, ko_attr));
+
+#define VDD_RSTR_REG_VALUE_FROM_ATTRIBS(attr) \
+ (container_of(attr, struct rail, value_attr));
+
+#define VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr) \
+ (container_of(attr, struct rail, level_attr));
+
+#define PSM_RW_ATTRIB(_rail, ko_attr, j, _name) \
+ ko_attr.attr.name = __stringify(_name); \
+ ko_attr.attr.mode = 644; \
+ ko_attr.show = psm_reg_##_name##_show; \
+ ko_attr.store = psm_reg_##_name##_store; \
+ _rail.attr_gp.attrs[j] = &ko_attr.attr;
+
+#define PSM_REG_MODE_FROM_ATTRIBS(attr) \
+ (container_of(attr, struct psm_rail, mode_attr));
+/* If freq table exists, then we can send freq request */
+static int check_freq_table(void)
+{
+ int ret = 0;
+ struct cpufreq_frequency_table *table = NULL;
+
+ table = cpufreq_frequency_get_table(0);
+ if (!table) {
+ pr_debug("%s: error reading cpufreq table\n", __func__);
+ return -EINVAL;
+ }
+ freq_table_get = 1;
+
+ return ret;
+}
+
+static int update_cpu_min_freq_all(uint32_t min)
+{
+ int cpu = 0;
+ int ret = 0;
+
+ if (!freq_table_get) {
+ ret = check_freq_table();
+ if (ret) {
+ pr_err("%s:Fail to get freq table\n", __func__);
+ return ret;
+ }
+ }
+ /* If min is larger than allowed max */
+ if (min != MSM_CPUFREQ_NO_LIMIT &&
+ min > table[limit_idx_high].frequency)
+ min = table[limit_idx_high].frequency;
+
+ for_each_possible_cpu(cpu) {
+ ret = msm_cpufreq_set_freq_limits(cpu, min, limited_max_freq);
+
+ if (ret) {
+ pr_err("%s:Fail to set limits for cpu%d\n",
+ __func__, cpu);
+ return ret;
+ }
+
+ if (cpufreq_update_policy(cpu))
+ pr_debug("%s: Cannot update policy for cpu%d\n",
+ __func__, cpu);
+ }
+
+ return ret;
+}
+
+static int vdd_restriction_apply_freq(struct rail *r, int level)
+{
+ int ret = 0;
+
+ /* level = -1: disable, level = 0,1,2..n: enable */
+ if (level == -1) {
+ ret = update_cpu_min_freq_all(r->min_level);
+ if (ret)
+ return ret;
+ else
+ r->curr_level = -1;
+ } else if (level >= 0 && level < (r->num_levels)) {
+ ret = update_cpu_min_freq_all(r->levels[level]);
+ if (ret)
+ return ret;
+ else
+ r->curr_level = level;
+ } else {
+ pr_err("level input:%d is not within range\n", level);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int vdd_restriction_apply_voltage(struct rail *r, int level)
+{
+ int ret = 0;
+
+ if (r->reg == NULL) {
+ pr_info("Do not have regulator handle:%s, can't apply vdd\n",
+ r->name);
+ return -EFAULT;
+ }
+ /* level = -1: disable, level = 0,1,2..n: enable */
+ if (level == -1) {
+ ret = regulator_set_voltage(r->reg, r->min_level,
+ r->levels[r->num_levels - 1]);
+ if (!ret)
+ r->curr_level = -1;
+ } else if (level >= 0 && level < (r->num_levels)) {
+ ret = regulator_set_voltage(r->reg, r->levels[level],
+ r->levels[r->num_levels - 1]);
+ if (!ret)
+ r->curr_level = level;
+ } else {
+ pr_err("level input:%d is not within range\n", level);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+/* 1:enable, 0:disable */
+static int vdd_restriction_apply_all(int en)
+{
+ int i = 0;
+ int fail_cnt = 0;
+ int ret = 0;
+
+ for (i = 0; i < rails_cnt; i++) {
+ if (rails[i].freq_req == 1 && freq_table_get)
+ ret = vdd_restriction_apply_freq(&rails[i],
+ en ? 0 : -1);
+ else
+ ret = vdd_restriction_apply_voltage(&rails[i],
+ en ? 0 : -1);
+ if (ret) {
+ pr_err("Cannot set voltage for %s", rails[i].name);
+ fail_cnt++;
+ }
+ }
+ /* Check fail_cnt again to make sure all of the rails are applied
+ * restriction successfully or not */
+ if (fail_cnt)
+ return -EFAULT;
+
+ return ret;
+}
+
+/* Setting all rails the same mode */
+static int psm_set_mode_all(int mode)
+{
+ int i = 0;
+ int fail_cnt = 0;
+ int ret = 0;
+
+ for (i = 0; i < psm_rails_cnt; i++) {
+ if (psm_rails[i].mode != mode) {
+ ret = rpm_regulator_set_mode(psm_rails[i].reg, mode);
+ if (ret) {
+ pr_err("Cannot set mode:%d for %s",
+ mode, psm_rails[i].name);
+ fail_cnt++;
+ } else
+ psm_rails[i].mode = mode;
+ }
+ }
+
+ return fail_cnt ? (-EFAULT) : ret;
+}
+
+static int vdd_rstr_en_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct vdd_rstr_enable *en = VDD_RSTR_ENABLE_FROM_ATTRIBS(attr);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", en->enabled);
+}
+
+static ssize_t vdd_rstr_en_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret = 0;
+ int i = 0;
+ uint8_t en_cnt = 0;
+ uint8_t dis_cnt = 0;
+ uint32_t val = 0;
+ struct kernel_param kp;
+ struct vdd_rstr_enable *en = VDD_RSTR_ENABLE_FROM_ATTRIBS(attr);
+
+ mutex_lock(&vdd_rstr_mutex);
+ kp.arg = &val;
+ ret = param_set_bool(buf, &kp);
+ if (ret) {
+ pr_err("Invalid input %s for enabled\n", buf);
+ goto done_vdd_rstr_en;
+ }
+
+ if ((val == 0) && (en->enabled == 0))
+ goto done_vdd_rstr_en;
+
+ for (i = 0; i < rails_cnt; i++) {
+ if (rails[i].freq_req == 1 && freq_table_get)
+ ret = vdd_restriction_apply_freq(&rails[i],
+ (val) ? 0 : -1);
+ else
+ ret = vdd_restriction_apply_voltage(&rails[i],
+ (val) ? 0 : -1);
+
+ /* Even if fail to set one rail, still try to set the
+ * others. Continue the loop */
+ if (ret)
+ pr_err("Set vdd restriction for %s failed\n",
+ rails[i].name);
+ else {
+ if (val)
+ en_cnt++;
+ else
+ dis_cnt++;
+ }
+ }
+ /* As long as one rail is enabled, vdd rstr is enabled */
+ if (val && en_cnt)
+ en->enabled = 1;
+ else if (!val && (dis_cnt == rails_cnt))
+ en->enabled = 0;
+
+done_vdd_rstr_en:
+ mutex_unlock(&vdd_rstr_mutex);
+ return count;
+}
+
+static struct vdd_rstr_enable vdd_rstr_en = {
+ .ko_attr.attr.name = __stringify(enabled),
+ .ko_attr.attr.mode = 644,
+ .ko_attr.show = vdd_rstr_en_show,
+ .ko_attr.store = vdd_rstr_en_store,
+ .enabled = 1,
+};
+
+static struct attribute *vdd_rstr_en_attribs[] = {
+ &vdd_rstr_en.ko_attr.attr,
+ NULL,
+};
+
+static struct attribute_group vdd_rstr_en_attribs_gp = {
+ .attrs = vdd_rstr_en_attribs,
+};
+
+static int vdd_rstr_reg_value_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int val = 0;
+ struct rail *reg = VDD_RSTR_REG_VALUE_FROM_ATTRIBS(attr);
+ /* -1:disabled, -2:fail to get regualtor handle */
+ if (reg->curr_level < 0)
+ val = reg->curr_level;
+ else
+ val = reg->levels[reg->curr_level];
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", reg->levels[reg->curr_level]);
+}
+
+static int vdd_rstr_reg_level_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct rail *reg = VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr);
+ return snprintf(buf, PAGE_SIZE, "%d\n", reg->curr_level);
+}
+
+static ssize_t vdd_rstr_reg_level_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret = 0;
+ int val = 0;
+
+ struct rail *reg = VDD_RSTR_REG_LEVEL_FROM_ATTRIBS(attr);
+
+ mutex_lock(&vdd_rstr_mutex);
+ if (vdd_rstr_en.enabled == 0)
+ goto done_store_level;
+
+ ret = kstrtoint(buf, 10, &val);
+ if (ret) {
+ pr_err("Invalid input %s for level\n", buf);
+ goto done_store_level;
+ }
+
+ if (val < 0 || val > reg->num_levels - 1) {
+ pr_err(" Invalid number %d for level\n", val);
+ goto done_store_level;
+ }
+
+ if (val != reg->curr_level) {
+ if (reg->freq_req == 1 && freq_table_get)
+ update_cpu_min_freq_all(reg->levels[val]);
+ else {
+ ret = vdd_restriction_apply_voltage(reg, val);
+ if (ret) {
+ pr_err( \
+ "Set vdd restriction for regulator %s failed\n",
+ reg->name);
+ goto done_store_level;
+ }
+ }
+ reg->curr_level = val;
+ }
+
+done_store_level:
+ mutex_unlock(&vdd_rstr_mutex);
+ return count;
+}
+
+static int psm_reg_mode_show(
+ struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct psm_rail *reg = PSM_REG_MODE_FROM_ATTRIBS(attr);
+ return snprintf(buf, PAGE_SIZE, "%d\n", reg->mode);
+}
+
+static ssize_t psm_reg_mode_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret = 0;
+ int val = 0;
+ struct psm_rail *reg = PSM_REG_MODE_FROM_ATTRIBS(attr);
+
+ mutex_lock(&psm_mutex);
+ ret = kstrtoint(buf, 10, &val);
+ if (ret) {
+ pr_err("Invalid input %s for mode\n", buf);
+ goto done_psm_store;
+ }
+
+ if ((val != PMIC_PWM_MODE) && (val != PMIC_AUTO_MODE)) {
+ pr_err(" Invalid number %d for mode\n", val);
+ goto done_psm_store;
+ }
+
+ if (val != reg->mode) {
+ ret = rpm_regulator_set_mode(reg->reg, val);
+ if (ret) {
+ pr_err( \
+ "Fail to set PMIC SW Mode:%d for %s\n",
+ val, reg->name);
+ goto done_psm_store;
+ }
+ reg->mode = val;
+ }
+
+done_psm_store:
+ mutex_unlock(&psm_mutex);
+ return count;
+}
static int msm_thermal_get_freq_table(void)
{
@@ -42,7 +472,7 @@
table = cpufreq_frequency_get_table(0);
if (table == NULL) {
- pr_debug("%s: error reading cpufreq table\n", __func__);
+ pr_debug("%s: error reading cpufreq table\n", KBUILD_MODNAME);
ret = -EINVAL;
goto fail;
}
@@ -67,17 +497,166 @@
limited_max_freq = max_freq;
if (max_freq != MSM_CPUFREQ_NO_LIMIT)
- pr_info("msm_thermal: Limiting cpu%d max frequency to %d\n",
- cpu, max_freq);
+ pr_info("%s: Limiting cpu%d max frequency to %d\n",
+ KBUILD_MODNAME, cpu, max_freq);
else
- pr_info("msm_thermal: Max frequency reset for cpu%d\n", cpu);
+ pr_info("%s: Max frequency reset for cpu%d\n",
+ KBUILD_MODNAME, cpu);
ret = cpufreq_update_policy(cpu);
return ret;
}
-static void check_temp(struct work_struct *work)
+static void __cpuinit do_core_control(long temp)
+{
+ int i = 0;
+ int ret = 0;
+
+ if (!core_control_enabled)
+ return;
+
+ mutex_lock(&core_control_mutex);
+ if (msm_thermal_info.core_control_mask &&
+ temp >= msm_thermal_info.core_limit_temp_degC) {
+ for (i = num_possible_cpus(); i > 0; i--) {
+ if (!(msm_thermal_info.core_control_mask & BIT(i)))
+ continue;
+ if (cpus_offlined & BIT(i) && !cpu_online(i))
+ continue;
+ pr_info("%s: Set Offline: CPU%d Temp: %ld\n",
+ KBUILD_MODNAME, i, temp);
+ ret = cpu_down(i);
+ if (ret)
+ pr_err("%s: Error %d offline core %d\n",
+ KBUILD_MODNAME, ret, i);
+ cpus_offlined |= BIT(i);
+ break;
+ }
+ } else if (msm_thermal_info.core_control_mask && cpus_offlined &&
+ temp <= (msm_thermal_info.core_limit_temp_degC -
+ msm_thermal_info.core_temp_hysteresis_degC)) {
+ for (i = 0; i < num_possible_cpus(); i++) {
+ if (!(cpus_offlined & BIT(i)))
+ continue;
+ cpus_offlined &= ~BIT(i);
+ pr_info("%s: Allow Online CPU%d Temp: %ld\n",
+ KBUILD_MODNAME, i, temp);
+ /* If this core is already online, then bring up the
+ * next offlined core.
+ */
+ if (cpu_online(i))
+ continue;
+ ret = cpu_up(i);
+ if (ret)
+ pr_err("%s: Error %d online core %d\n",
+ KBUILD_MODNAME, ret, i);
+ break;
+ }
+ }
+ mutex_unlock(&core_control_mutex);
+}
+
+static int do_vdd_restriction(void)
+{
+ struct tsens_device tsens_dev;
+ long temp = 0;
+ int ret = 0;
+ int i = 0;
+ int dis_cnt = 0;
+
+ if (!vdd_rstr_enabled)
+ return ret;
+
+ if (usefreq && !freq_table_get) {
+ if (check_freq_table())
+ return ret;
+ }
+
+ mutex_lock(&vdd_rstr_mutex);
+ for (i = 0; i < max_tsens_num; i++) {
+ tsens_dev.sensor_num = i;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (ret) {
+ pr_debug("%s: Unable to read TSENS sensor %d\n",
+ __func__, tsens_dev.sensor_num);
+ dis_cnt++;
+ continue;
+ }
+ if (temp <= msm_thermal_info.vdd_rstr_temp_hyst_degC &&
+ vdd_rstr_en.enabled == 0) {
+ ret = vdd_restriction_apply_all(1);
+ if (ret) {
+ pr_err( \
+ "Enable vdd rstr votlage for all failed\n");
+ goto exit;
+ }
+ vdd_rstr_en.enabled = 1;
+ goto exit;
+ } else if (temp > msm_thermal_info.vdd_rstr_temp_degC &&
+ vdd_rstr_en.enabled == 1)
+ dis_cnt++;
+ }
+ if (dis_cnt == max_tsens_num) {
+ ret = vdd_restriction_apply_all(0);
+ if (ret) {
+ pr_err("Disable vdd rstr votlage for all failed\n");
+ goto exit;
+ }
+ vdd_rstr_en.enabled = 0;
+ }
+exit:
+ mutex_unlock(&vdd_rstr_mutex);
+ return ret;
+}
+
+static int do_psm(void)
+{
+ struct tsens_device tsens_dev;
+ long temp = 0;
+ int ret = 0;
+ int i = 0;
+ int auto_cnt = 0;
+
+ mutex_lock(&psm_mutex);
+ for (i = 0; i < max_tsens_num; i++) {
+ tsens_dev.sensor_num = i;
+ ret = tsens_get_temp(&tsens_dev, &temp);
+ if (ret) {
+ pr_debug("%s: Unable to read TSENS sensor %d\n",
+ __func__, tsens_dev.sensor_num);
+ auto_cnt++;
+ continue;
+ }
+
+ /* As long as one sensor is above the threshold, set PWM mode
+ * on all rails, and loop stops. Set auto mode when all rails
+ * are below thershold */
+ if (temp > msm_thermal_info.psm_temp_degC) {
+ ret = psm_set_mode_all(PMIC_PWM_MODE);
+ if (ret) {
+ pr_err("Set pwm mode for all failed\n");
+ goto exit;
+ }
+ break;
+ } else if (temp <= msm_thermal_info.psm_temp_hyst_degC)
+ auto_cnt++;
+ }
+
+ if (auto_cnt == max_tsens_num) {
+ ret = psm_set_mode_all(PMIC_AUTO_MODE);
+ if (ret) {
+ pr_err("Set auto mode for all failed\n");
+ goto exit;
+ }
+ }
+
+exit:
+ mutex_unlock(&psm_mutex);
+ return ret;
+}
+
+static void __cpuinit check_temp(struct work_struct *work)
{
static int limit_init;
struct tsens_device tsens_dev;
@@ -85,12 +664,11 @@
uint32_t max_freq = limited_max_freq;
int cpu = 0;
int ret = 0;
-
tsens_dev.sensor_num = msm_thermal_info.sensor_id;
ret = tsens_get_temp(&tsens_dev, &temp);
if (ret) {
- pr_debug("msm_thermal: Unable to read TSENS sensor %d\n",
- tsens_dev.sensor_num);
+ pr_debug("%s: Unable to read TSENS sensor %d\n",
+ KBUILD_MODNAME, tsens_dev.sensor_num);
goto reschedule;
}
@@ -102,6 +680,10 @@
limit_init = 1;
}
+ do_core_control(temp);
+ do_vdd_restriction();
+ do_psm();
+
if (temp >= msm_thermal_info.limit_temp_degC) {
if (limit_idx == limit_idx_low)
goto reschedule;
@@ -129,8 +711,9 @@
for_each_possible_cpu(cpu) {
ret = update_cpu_max_freq(cpu, max_freq);
if (ret)
- pr_debug("Unable to limit cpu%d max freq to %d\n",
- cpu, max_freq);
+ pr_debug(
+ "%s: Unable to limit cpu%d max freq to %d\n",
+ KBUILD_MODNAME, cpu, max_freq);
}
reschedule:
@@ -139,7 +722,36 @@
msecs_to_jiffies(msm_thermal_info.poll_ms));
}
-static void disable_msm_thermal(void)
+static int __cpuinit msm_thermal_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ if (action == CPU_UP_PREPARE || action == CPU_UP_PREPARE_FROZEN) {
+ if (core_control_enabled &&
+ (msm_thermal_info.core_control_mask & BIT(cpu)) &&
+ (cpus_offlined & BIT(cpu))) {
+ pr_info(
+ "%s: Preventing cpu%d from coming online.\n",
+ KBUILD_MODNAME, cpu);
+ return NOTIFY_BAD;
+ }
+ }
+
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __refdata msm_thermal_cpu_notifier = {
+ .notifier_call = msm_thermal_cpu_callback,
+};
+
+/**
+ * We will reset the cpu frequencies limits here. The core online/offline
+ * status will be carried over to the process stopping the msm_thermal, as
+ * we dont want to online a core and bring in the thermal issues.
+ */
+static void __cpuinit disable_msm_thermal(void)
{
int cpu = 0;
@@ -155,7 +767,7 @@
}
}
-static int set_enabled(const char *val, const struct kernel_param *kp)
+static int __cpuinit set_enabled(const char *val, const struct kernel_param *kp)
{
int ret = 0;
@@ -163,9 +775,10 @@
if (!enabled)
disable_msm_thermal();
else
- pr_info("msm_thermal: no action for enabled = %d\n", enabled);
+ pr_info("%s: no action for enabled = %d\n",
+ KBUILD_MODNAME, enabled);
- pr_info("msm_thermal: enabled = %d\n", enabled);
+ pr_info("%s: enabled = %d\n", KBUILD_MODNAME, enabled);
return ret;
}
@@ -178,18 +791,561 @@
module_param_cb(enabled, &module_ops, &enabled, 0644);
MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu");
+
+/* Call with core_control_mutex locked */
+static int __cpuinit update_offline_cores(int val)
+{
+ int cpu = 0;
+ int ret = 0;
+
+ cpus_offlined = msm_thermal_info.core_control_mask & val;
+ if (!core_control_enabled)
+ return 0;
+
+ for_each_possible_cpu(cpu) {
+ if (!(cpus_offlined & BIT(cpu)))
+ continue;
+ if (!cpu_online(cpu))
+ continue;
+ ret = cpu_down(cpu);
+ if (ret)
+ pr_err("%s: Unable to offline cpu%d\n",
+ KBUILD_MODNAME, cpu);
+ }
+ return ret;
+}
+
+static ssize_t show_cc_enabled(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", core_control_enabled);
+}
+
+static ssize_t __cpuinit store_cc_enabled(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret = 0;
+ int val = 0;
+
+ mutex_lock(&core_control_mutex);
+ ret = kstrtoint(buf, 10, &val);
+ if (ret) {
+ pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
+ goto done_store_cc;
+ }
+
+ if (core_control_enabled == !!val)
+ goto done_store_cc;
+
+ core_control_enabled = !!val;
+ if (core_control_enabled) {
+ pr_info("%s: Core control enabled\n", KBUILD_MODNAME);
+ register_cpu_notifier(&msm_thermal_cpu_notifier);
+ update_offline_cores(cpus_offlined);
+ } else {
+ pr_info("%s: Core control disabled\n", KBUILD_MODNAME);
+ unregister_cpu_notifier(&msm_thermal_cpu_notifier);
+ }
+
+done_store_cc:
+ mutex_unlock(&core_control_mutex);
+ return count;
+}
+
+static ssize_t show_cpus_offlined(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", cpus_offlined);
+}
+
+static ssize_t __cpuinit store_cpus_offlined(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ int ret = 0;
+ uint32_t val = 0;
+
+ mutex_lock(&core_control_mutex);
+ ret = kstrtouint(buf, 10, &val);
+ if (ret) {
+ pr_err("%s: Invalid input %s\n", KBUILD_MODNAME, buf);
+ goto done_cc;
+ }
+
+ if (enabled) {
+ pr_err("%s: Ignoring request; polling thread is enabled.\n",
+ KBUILD_MODNAME);
+ goto done_cc;
+ }
+
+ if (cpus_offlined == val)
+ goto done_cc;
+
+ update_offline_cores(val);
+done_cc:
+ mutex_unlock(&core_control_mutex);
+ return count;
+}
+
+static __cpuinitdata struct kobj_attribute cc_enabled_attr =
+__ATTR(enabled, 0644, show_cc_enabled, store_cc_enabled);
+
+static __cpuinitdata struct kobj_attribute cpus_offlined_attr =
+__ATTR(cpus_offlined, 0644, show_cpus_offlined, store_cpus_offlined);
+
+static __cpuinitdata struct attribute *cc_attrs[] = {
+ &cc_enabled_attr.attr,
+ &cpus_offlined_attr.attr,
+ NULL,
+};
+
+static __cpuinitdata struct attribute_group cc_attr_group = {
+ .attrs = cc_attrs,
+};
+
+static __init int msm_thermal_add_cc_nodes(void)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *cc_kobj = NULL;
+ int ret = 0;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: cannot find kobject for module\n",
+ KBUILD_MODNAME);
+ ret = -ENOENT;
+ goto done_cc_nodes;
+ }
+
+ cc_kobj = kobject_create_and_add("core_control", module_kobj);
+ if (!cc_kobj) {
+ pr_err("%s: cannot create core control kobj\n",
+ KBUILD_MODNAME);
+ ret = -ENOMEM;
+ goto done_cc_nodes;
+ }
+
+ ret = sysfs_create_group(cc_kobj, &cc_attr_group);
+ if (ret) {
+ pr_err("%s: cannot create group\n", KBUILD_MODNAME);
+ goto done_cc_nodes;
+ }
+
+ return 0;
+
+done_cc_nodes:
+ if (cc_kobj)
+ kobject_del(cc_kobj);
+ return ret;
+}
+
int __devinit msm_thermal_init(struct msm_thermal_data *pdata)
{
int ret = 0;
BUG_ON(!pdata);
- BUG_ON(pdata->sensor_id >= TSENS_MAX_SENSORS);
+ tsens_get_max_sensor_num(&max_tsens_num);
+ BUG_ON(msm_thermal_info.sensor_id >= max_tsens_num);
memcpy(&msm_thermal_info, pdata, sizeof(struct msm_thermal_data));
enabled = 1;
+ core_control_enabled = 1;
INIT_DELAYED_WORK(&check_temp_work, check_temp);
schedule_delayed_work(&check_temp_work, 0);
+ register_cpu_notifier(&msm_thermal_cpu_notifier);
+
+ return ret;
+}
+
+static int vdd_restriction_reg_init(struct platform_device *pdev)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < rails_cnt; i++) {
+ if (rails[i].freq_req == 1) {
+ usefreq |= BIT(i);
+ check_freq_table();
+ /* Restrict frequency by default until we have made
+ * our first temp reading */
+ if (freq_table_get)
+ ret = vdd_restriction_apply_freq(&rails[i], 0);
+ else
+ pr_info("%s:Defer vdd rstr freq init\n",
+ __func__);
+ } else {
+ rails[i].reg = devm_regulator_get(&pdev->dev,
+ rails[i].name);
+ if (IS_ERR_OR_NULL(rails[i].reg)) {
+ ret = PTR_ERR(rails[i].reg);
+ if (ret != -EPROBE_DEFER) {
+ pr_err( \
+ "%s, could not get regulator: %s\n",
+ rails[i].name, __func__);
+ rails[i].reg = NULL;
+ rails[i].curr_level = -2;
+ return ret;
+ }
+ return ret;
+ }
+ /* Restrict votlage by default until we have made
+ * our first temp reading */
+ ret = vdd_restriction_apply_voltage(&rails[i], 0);
+ }
+ }
+
+ return ret;
+}
+
+static int psm_reg_init(struct platform_device *pdev)
+{
+ int ret = 0;
+ int i = 0;
+ int j = 0;
+
+ for (i = 0; i < psm_rails_cnt; i++) {
+ psm_rails[i].reg = rpm_regulator_get(&pdev->dev,
+ psm_rails[i].name);
+ if (IS_ERR_OR_NULL(psm_rails[i].reg)) {
+ ret = PTR_ERR(psm_rails[i].reg);
+ if (ret != -EPROBE_DEFER) {
+ pr_err("%s, could not get rpm regulator: %s\n",
+ psm_rails[i].name, __func__);
+ psm_rails[i].reg = NULL;
+ goto psm_reg_exit;
+ }
+ return ret;
+ }
+ /* Apps default vote for PWM mode */
+ psm_rails[i].init = PMIC_PWM_MODE;
+ ret = rpm_regulator_set_mode(psm_rails[i].reg,
+ psm_rails[i].init);
+ if (ret) {
+ pr_err("%s: Cannot set PMIC PWM mode\n", __func__);
+ return ret;
+ } else
+ psm_rails[i].mode = PMIC_PWM_MODE;
+ }
+
+ return ret;
+
+psm_reg_exit:
+ if (ret) {
+ for (j = 0; j < i; j++) {
+ if (psm_rails[j].reg != NULL)
+ rpm_regulator_put(psm_rails[j].reg);
+ }
+ }
+
+ return ret;
+}
+
+static int msm_thermal_add_vdd_rstr_nodes(void)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *vdd_rstr_kobj = NULL;
+ struct kobject *vdd_rstr_reg_kobj[MAX_RAILS] = {0};
+ int rc = 0;
+ int i = 0;
+
+ if (!vdd_rstr_probed) {
+ vdd_rstr_nodes_called = true;
+ return rc;
+ }
+
+ if (vdd_rstr_probed && rails_cnt == 0)
+ return rc;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: cannot find kobject for module %s\n",
+ __func__, KBUILD_MODNAME);
+ rc = -ENOENT;
+ goto thermal_sysfs_add_exit;
+ }
+
+ vdd_rstr_kobj = kobject_create_and_add("vdd_restriction", module_kobj);
+ if (!vdd_rstr_kobj) {
+ pr_err("%s: cannot create vdd_restriction kobject\n", __func__);
+ rc = -ENOMEM;
+ goto thermal_sysfs_add_exit;
+ }
+
+ rc = sysfs_create_group(vdd_rstr_kobj, &vdd_rstr_en_attribs_gp);
+ if (rc) {
+ pr_err("%s: cannot create kobject attribute group\n", __func__);
+ rc = -ENOMEM;
+ goto thermal_sysfs_add_exit;
+ }
+
+ for (i = 0; i < rails_cnt; i++) {
+ vdd_rstr_reg_kobj[i] = kobject_create_and_add(rails[i].name,
+ vdd_rstr_kobj);
+ if (!vdd_rstr_reg_kobj[i]) {
+ pr_err("%s: cannot create for kobject for %s\n",
+ __func__, rails[i].name);
+ rc = -ENOMEM;
+ goto thermal_sysfs_add_exit;
+ }
+
+ rails[i].attr_gp.attrs = kzalloc(sizeof(struct attribute *) * 3,
+ GFP_KERNEL);
+ if (!rails[i].attr_gp.attrs) {
+ rc = -ENOMEM;
+ goto thermal_sysfs_add_exit;
+ }
+
+ VDD_RES_RW_ATTRIB(rails[i], rails[i].level_attr, 0, level);
+ VDD_RES_RO_ATTRIB(rails[i], rails[i].value_attr, 1, value);
+ rails[i].attr_gp.attrs[2] = NULL;
+
+ rc = sysfs_create_group(vdd_rstr_reg_kobj[i],
+ &rails[i].attr_gp);
+ if (rc) {
+ pr_err("%s: cannot create attribute group for %s\n",
+ __func__, rails[i].name);
+ goto thermal_sysfs_add_exit;
+ }
+ }
+
+ return rc;
+
+thermal_sysfs_add_exit:
+ if (rc) {
+ for (i = 0; i < rails_cnt; i++) {
+ kobject_del(vdd_rstr_reg_kobj[i]);
+ kfree(rails[i].attr_gp.attrs);
+ }
+ if (vdd_rstr_kobj)
+ kobject_del(vdd_rstr_kobj);
+ }
+ return rc;
+}
+
+static int msm_thermal_add_psm_nodes(void)
+{
+ struct kobject *module_kobj = NULL;
+ struct kobject *psm_kobj = NULL;
+ struct kobject *psm_reg_kobj[MAX_RAILS] = {0};
+ int rc = 0;
+ int i = 0;
+
+ if (!psm_probed) {
+ psm_nodes_called = true;
+ return rc;
+ }
+
+ if (psm_probed && psm_rails_cnt == 0)
+ return rc;
+
+ module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
+ if (!module_kobj) {
+ pr_err("%s: cannot find kobject for module %s\n",
+ __func__, KBUILD_MODNAME);
+ rc = -ENOENT;
+ goto psm_node_exit;
+ }
+
+ psm_kobj = kobject_create_and_add("pmic_sw_mode", module_kobj);
+ if (!psm_kobj) {
+ pr_err("%s: cannot create psm kobject\n", KBUILD_MODNAME);
+ rc = -ENOMEM;
+ goto psm_node_exit;
+ }
+
+ for (i = 0; i < psm_rails_cnt; i++) {
+ psm_reg_kobj[i] = kobject_create_and_add(psm_rails[i].name,
+ psm_kobj);
+ if (!psm_reg_kobj[i]) {
+ pr_err("%s: cannot create for kobject for %s\n",
+ KBUILD_MODNAME, psm_rails[i].name);
+ rc = -ENOMEM;
+ goto psm_node_exit;
+ }
+ psm_rails[i].attr_gp.attrs = kzalloc( \
+ sizeof(struct attribute *) * 2, GFP_KERNEL);
+ if (!psm_rails[i].attr_gp.attrs) {
+ rc = -ENOMEM;
+ goto psm_node_exit;
+ }
+
+ PSM_RW_ATTRIB(psm_rails[i], psm_rails[i].mode_attr, 0, mode);
+ psm_rails[i].attr_gp.attrs[1] = NULL;
+
+ rc = sysfs_create_group(psm_reg_kobj[i], &psm_rails[i].attr_gp);
+ if (rc) {
+ pr_err("%s: cannot create attribute group for %s\n",
+ KBUILD_MODNAME, psm_rails[i].name);
+ goto psm_node_exit;
+ }
+ }
+
+ return rc;
+
+psm_node_exit:
+ if (rc) {
+ for (i = 0; i < psm_rails_cnt; i++) {
+ kobject_del(psm_reg_kobj[i]);
+ kfree(psm_rails[i].attr_gp.attrs);
+ }
+ if (psm_kobj)
+ kobject_del(psm_kobj);
+ }
+ return rc;
+}
+
+static int probe_vdd_rstr(struct device_node *node,
+ struct msm_thermal_data *data, struct platform_device *pdev)
+{
+ int ret = 0;
+ int i = 0;
+ int arr_size;
+ char *key = NULL;
+ struct device_node *child_node = NULL;
+
+ key = "qcom,vdd-restriction-temp";
+ ret = of_property_read_u32(node, key, &data->vdd_rstr_temp_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,vdd-restriction-temp-hysteresis";
+ ret = of_property_read_u32(node, key, &data->vdd_rstr_temp_hyst_degC);
+ if (ret)
+ goto read_node_fail;
+
+ for_each_child_of_node(node, child_node) {
+ rails_cnt++;
+ }
+
+ if (rails_cnt == 0)
+ goto read_node_fail;
+ if (rails_cnt >= MAX_RAILS) {
+ pr_err("%s: Too many rails.\n", __func__);
+ return -EFAULT;
+ }
+
+ rails = kzalloc(sizeof(struct rail) * rails_cnt,
+ GFP_KERNEL);
+ if (!rails) {
+ pr_err("%s: Fail to allocate memory for rails.\n", __func__);
+ return -ENOMEM;
+ }
+
+ i = 0;
+ for_each_child_of_node(node, child_node) {
+ key = "qcom,vdd-rstr-reg";
+ ret = of_property_read_string(child_node, key, &rails[i].name);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,levels";
+ if (!of_get_property(child_node, key, &arr_size))
+ goto read_node_fail;
+ rails[i].num_levels = arr_size/sizeof(__be32);
+ if (rails[i].num_levels >
+ sizeof(rails[i].levels)/sizeof(uint32_t)) {
+ pr_err("%s: Array size too large\n", __func__);
+ return -EFAULT;
+ }
+ ret = of_property_read_u32_array(child_node, key,
+ rails[i].levels, rails[i].num_levels);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,min-level";
+ ret = of_property_read_u32(child_node, key,
+ &rails[i].min_level);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,freq-req";
+ rails[i].freq_req = of_property_read_bool(child_node, key);
+
+ if (ret)
+ goto read_node_fail;
+ rails[i].curr_level = 0;
+ rails[i].reg = NULL;
+ i++;
+ }
+
+ if (rails_cnt) {
+ ret = vdd_restriction_reg_init(pdev);
+ if (ret) {
+ pr_info("%s:Failed to get regulators. KTM continues.\n",
+ __func__);
+ goto read_node_fail;
+ }
+ vdd_rstr_enabled = true;
+ }
+read_node_fail:
+ vdd_rstr_probed = true;
+ if (ret) {
+ dev_info(&pdev->dev,
+ "%s:Failed reading node=%s, key=%s. KTM continues\n",
+ __func__, node->full_name, key);
+ kfree(rails);
+ rails_cnt = 0;
+ }
+ if (ret == -EPROBE_DEFER)
+ vdd_rstr_probed = false;
+ return ret;
+}
+
+static int probe_psm(struct device_node *node, struct msm_thermal_data *data,
+ struct platform_device *pdev)
+{
+ int ret = 0;
+ int j = 0;
+ char *key = NULL;
+
+ key = "qcom,pmic-sw-mode-temp";
+ ret = of_property_read_u32(node, key, &data->psm_temp_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,pmic-sw-mode-temp-hysteresis";
+ ret = of_property_read_u32(node, key, &data->psm_temp_hyst_degC);
+ if (ret)
+ goto read_node_fail;
+
+ key = "qcom,pmic-sw-mode-regs";
+ psm_rails_cnt = of_property_count_strings(node, key);
+ psm_rails = kzalloc(sizeof(struct psm_rail) * psm_rails_cnt,
+ GFP_KERNEL);
+ if (!psm_rails) {
+ pr_err("%s: Fail to allocate memory for psm rails\n", __func__);
+ psm_rails_cnt = 0;
+ return -ENOMEM;
+ }
+
+ for (j = 0; j < psm_rails_cnt; j++) {
+ ret = of_property_read_string_index(node, key, j,
+ &psm_rails[j].name);
+ if (ret)
+ goto read_node_fail;
+ }
+
+ if (psm_rails_cnt) {
+ ret = psm_reg_init(pdev);
+ if (ret) {
+ pr_info("%s:Failed to get regulators. KTM continues.\n",
+ __func__);
+ goto read_node_fail;
+ }
+ psm_enabled = true;
+ }
+
+read_node_fail:
+ psm_probed = true;
+ if (ret) {
+ dev_info(&pdev->dev,
+ "%s:Failed reading node=%s, key=%s. KTM continues\n",
+ __func__, node->full_name, key);
+ kfree(psm_rails);
+ psm_rails_cnt = 0;
+ }
+ if (ret == -EPROBE_DEFER)
+ psm_probed = false;
return ret;
}
@@ -198,14 +1354,15 @@
int ret = 0;
char *key = NULL;
struct device_node *node = pdev->dev.of_node;
+
struct msm_thermal_data data;
memset(&data, 0, sizeof(struct msm_thermal_data));
+
key = "qcom,sensor-id";
ret = of_property_read_u32(node, key, &data.sensor_id);
if (ret)
goto fail;
- WARN_ON(data.sensor_id >= TSENS_MAX_SENSORS);
key = "qcom,poll-ms";
ret = of_property_read_u32(node, key, &data.poll_ms);
@@ -224,17 +1381,50 @@
key = "qcom,freq-step";
ret = of_property_read_u32(node, key, &data.freq_step);
+ if (ret)
+ goto fail;
+ key = "qcom,core-limit-temp";
+ ret = of_property_read_u32(node, key, &data.core_limit_temp_degC);
+
+ key = "qcom,core-temp-hysteresis";
+ ret = of_property_read_u32(node, key, &data.core_temp_hysteresis_degC);
+
+ key = "qcom,core-control-mask";
+ ret = of_property_read_u32(node, key, &data.core_control_mask);
+
+ /* Probe optional properties below. Call probe_psm before
+ * probe_vdd_rstr because rpm_regulator_get has to be called
+ * before devm_regulator_get*/
+ ret = probe_psm(node, &data, pdev);
+ if (ret == -EPROBE_DEFER)
+ goto fail;
+ ret = probe_vdd_rstr(node, &data, pdev);
+ if (ret == -EPROBE_DEFER)
+ goto fail;
+
+ /* In case sysfs add nodes get called before probe function.
+ * Need to make sure sysfs node is created again */
+ if (psm_nodes_called) {
+ msm_thermal_add_psm_nodes();
+ psm_nodes_called = false;
+ }
+ if (vdd_rstr_nodes_called) {
+ msm_thermal_add_vdd_rstr_nodes();
+ vdd_rstr_nodes_called = false;
+ }
+ ret = msm_thermal_init(&data);
+
+ return ret;
fail:
if (ret)
pr_err("%s: Failed reading node=%s, key=%s\n",
- __func__, node->full_name, key);
- else
- ret = msm_thermal_init(&data);
+ __func__, node->full_name, key);
return ret;
}
+
static struct of_device_id msm_thermal_match_table[] = {
{.compatible = "qcom,msm-thermal"},
{},
@@ -253,3 +1443,14 @@
{
return platform_driver_register(&msm_thermal_device_driver);
}
+
+int __init msm_thermal_late_init(void)
+{
+ msm_thermal_add_cc_nodes();
+ msm_thermal_add_psm_nodes();
+ msm_thermal_add_vdd_rstr_nodes();
+
+ return 0;
+}
+late_initcall(msm_thermal_late_init);
+
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 867e218..ad7c702 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -631,7 +631,7 @@
"pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
return ret;
}
- /* Register callback event for EOT (End of transfer) event. */
+ /* Register callback event for DESC_DONE event. */
ret = sps_register_event(sps_pipe_handle, sps_event);
if (ret) {
pr_err("msm_serial_hs: sps_connect() failed for rx!!\n"
@@ -964,7 +964,10 @@
*/
mb();
if (is_blsp_uart(msm_uport)) {
- sps_disconnect(sps_pipe_handle);
+ ret = sps_disconnect(sps_pipe_handle);
+ if (ret)
+ pr_err("%s(): sps_disconnect failed\n",
+ __func__);
msm_hs_spsconnect_rx(uport);
msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
} else {
@@ -1023,8 +1026,12 @@
disconnect_rx_endpoint);
struct msm_hs_rx *rx = &msm_uport->rx;
struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
+ int ret = 0;
- sps_disconnect(sps_pipe_handle);
+ ret = sps_disconnect(sps_pipe_handle);
+ if (ret)
+ pr_err("%s(): sps_disconnect failed\n", __func__);
+
wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
msm_uport->rx.flush = FLUSH_SHUTDOWN;
wake_up(&msm_uport->rx.wait);
@@ -1158,7 +1165,7 @@
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
struct msm_hs_rx *rx = &msm_uport->rx;
struct sps_pipe *sps_pipe_handle;
- u32 flags = SPS_IOVEC_FLAG_EOT;
+ u32 flags = SPS_IOVEC_FLAG_INT;
unsigned int buffer_pending = msm_uport->rx.buffer_pending;
unsigned int data;
@@ -1284,7 +1291,7 @@
struct sps_event_notify *notify;
struct msm_hs_rx *rx;
struct sps_pipe *sps_pipe_handle;
- u32 sps_flags = SPS_IOVEC_FLAG_EOT;
+ u32 sps_flags = SPS_IOVEC_FLAG_INT;
msm_uport = container_of((struct tasklet_struct *)tlet_ptr,
struct msm_hs_port, rx.tlet);
@@ -1699,8 +1706,6 @@
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);
@@ -1745,7 +1750,6 @@
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 */
@@ -2654,7 +2658,7 @@
sps_config->mode = SPS_MODE_SRC;
sps_config->src_pipe_index = msm_uport->bam_rx_ep_pipe_index;
sps_config->dest_pipe_index = 0;
- sps_config->options = SPS_O_EOT;
+ sps_config->options = SPS_O_DESC_DONE;
} else {
/* For UART consumer transfer, source is system memory
where as destination is UART peripheral */
@@ -2682,11 +2686,14 @@
memset(sps_config->desc.base, 0x00, sps_config->desc.size);
sps_event->mode = SPS_TRIGGER_CALLBACK;
- sps_event->options = SPS_O_EOT;
- if (is_producer)
+
+ if (is_producer) {
sps_event->callback = msm_hs_sps_rx_callback;
- else
+ sps_event->options = SPS_O_DESC_DONE;
+ } else {
sps_event->callback = msm_hs_sps_tx_callback;
+ sps_event->options = SPS_O_EOT;
+ }
sps_event->user = (void *)msm_uport;
@@ -3160,7 +3167,10 @@
pr_err("%s():HSUART TX Stalls.\n", __func__);
} else {
/* BAM Disconnect for TX */
- sps_disconnect(sps_pipe_handle);
+ ret = sps_disconnect(sps_pipe_handle);
+ if (ret)
+ pr_err("%s(): sps_disconnect failed\n",
+ __func__);
}
}
tasklet_kill(&msm_uport->tx.tlet);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f83794c..7a6765b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1254,50 +1254,11 @@
return ret;
}
-/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
-static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+/* Reinitialize SSPHY parameters by overriding using QSCRATCH CR interface */
+static void dwc3_msm_ss_phy_reg_init(struct dwc3_msm *msm)
{
u32 data = 0;
- /* SSPHY Initialization: Use ref_clk from pads and set its parameters */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
- msleep(30);
- /* Assert SSPHY reset */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
- usleep_range(2000, 2200);
- /* De-assert SSPHY reset - power and ref_clock must be ON */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
- usleep_range(2000, 2200);
- /* Ref clock must be stable now, enable ref clock for HS mode */
- dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
- usleep_range(2000, 2200);
- /*
- * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
- * and disable RETENTION (power-on default is ENABLED)
- */
- dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
- usleep_range(2000, 2200);
- /* Disable (bypass) VBUS and ID filters */
- dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
- /*
- * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
- * VBUS valid threshold, disconnect valid threshold, DC voltage level,
- * preempasis and rise/fall time.
- */
- if (override_phy_init)
- msm->hsphy_init_seq = override_phy_init;
- if (msm->hsphy_init_seq)
- dwc3_msm_write_readback(msm->base,
- PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
- msm->hsphy_init_seq & 0x03FFFFFF);
-
- /* Enable master clock for RAMs to allow BAM to access RAMs when
- * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
- * are seen where RAM clocks get turned OFF in SS mode
- */
- dwc3_msm_write_reg(msm->base, CGCTL_REG,
- dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
-
/*
* WORKAROUND: There is SSPHY suspend bug due to which USB enumerates
* in HS mode instead of SS mode. Workaround it by asserting
@@ -1344,6 +1305,51 @@
dwc3_msm_write_readback(msm->base, SS_PHY_PARAM_CTRL_1, 0x07, 0x5);
}
+/* Initialize QSCRATCH registers for HSPHY and SSPHY operation */
+static void dwc3_msm_qscratch_reg_init(struct dwc3_msm *msm)
+{
+ /* SSPHY Initialization: Use ref_clk from pads and set its parameters */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ msleep(30);
+ /* Assert SSPHY reset */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210082);
+ usleep_range(2000, 2200);
+ /* De-assert SSPHY reset - power and ref_clock must be ON */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210002);
+ usleep_range(2000, 2200);
+ /* Ref clock must be stable now, enable ref clock for HS mode */
+ dwc3_msm_write_reg(msm->base, SS_PHY_CTRL_REG, 0x10210102);
+ usleep_range(2000, 2200);
+ /*
+ * HSPHY Initialization: Enable UTMI clock and clamp enable HVINTs,
+ * and disable RETENTION (power-on default is ENABLED)
+ */
+ dwc3_msm_write_reg(msm->base, HS_PHY_CTRL_REG, 0x5220bb2);
+ usleep_range(2000, 2200);
+ /* Disable (bypass) VBUS and ID filters */
+ dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ /*
+ * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
+ * VBUS valid threshold, disconnect valid threshold, DC voltage level,
+ * preempasis and rise/fall time.
+ */
+ if (override_phy_init)
+ msm->hsphy_init_seq = override_phy_init;
+ if (msm->hsphy_init_seq)
+ dwc3_msm_write_readback(msm->base,
+ PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
+ msm->hsphy_init_seq & 0x03FFFFFF);
+
+ /* Enable master clock for RAMs to allow BAM to access RAMs when
+ * RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
+ * are seen where RAM clocks get turned OFF in SS mode
+ */
+ dwc3_msm_write_reg(msm->base, CGCTL_REG,
+ dwc3_msm_read_reg(msm->base, CGCTL_REG) | 0x18);
+
+ dwc3_msm_ss_phy_reg_init(msm);
+}
+
static void dwc3_msm_block_reset(bool core_reset)
{
@@ -1791,6 +1797,11 @@
udelay(10);
dwc3_msm_write_readback(mdwc->base, SS_PHY_CTRL_REG, (1 << 7), 0x0);
+ /*
+ * Reinitilize SSPHY parameters as SS_PHY RESET will reset
+ * the internal registers to default values.
+ */
+ dwc3_msm_ss_phy_reg_init(mdwc);
atomic_set(&mdwc->in_lpm, 0);
/* match disable_irq call from isr */
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f060718..c08a259 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2169,7 +2169,7 @@
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms);
WARN_ON_ONCE(ret);
dep->resource_index = 0;
-
+ dep->flags &= ~DWC3_EP_BUSY;
udelay(100);
}
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index c847ee6..763c7f6 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -135,6 +135,7 @@
irqreturn_t (*irq_handler)(int irq, void *ptr);
};
+int mdss_register_irq(struct mdss_hw *hw);
void mdss_enable_irq(struct mdss_hw *hw);
void mdss_disable_irq(struct mdss_hw *hw);
void mdss_disable_irq_nosync(struct mdss_hw *hw);
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 0b2a7c0..0918db1 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -286,6 +286,96 @@
return -ENODEV;
}
+
+static int mdss_debug_stat_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static int mdss_debug_stat_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int mdss_debug_stat_ctl_dump(struct mdss_mdp_ctl *ctl,
+ char *bp, int len)
+{
+ int tot = 0;
+
+ if (!ctl->ref_cnt)
+ return 0;
+
+ if (ctl->intf_num) {
+ tot = scnprintf(bp, len,
+ "intf%d: play: %08u \tvsync: %08u \tunderrun: %08u\n",
+ ctl->intf_num, ctl->play_cnt,
+ ctl->vsync_cnt, ctl->underrun_cnt);
+ } else {
+ tot = scnprintf(bp, len, "wb: \tmode=%x \tplay: %08u\n",
+ ctl->opmode, ctl->play_cnt);
+ }
+
+ return tot;
+}
+
+static ssize_t mdss_debug_stat_read(struct file *file, char __user *buff,
+ size_t count, loff_t *ppos)
+{
+ struct mdss_data_type *mdata = file->private_data;
+ struct mdss_mdp_pipe *pipe;
+ int i, len, tot;
+ char bp[512];
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = sizeof(bp);
+
+ tot = scnprintf(bp, len, "\nmdp:\n");
+
+ for (i = 0; i < mdata->nctl; i++)
+ tot += mdss_debug_stat_ctl_dump(mdata->ctl_off + i,
+ bp + tot, len - tot);
+ tot += scnprintf(bp + tot, len - tot, "\n");
+
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ pipe = mdata->vig_pipes + i;
+ tot += scnprintf(bp + tot, len - tot,
+ "VIG%d : %08u\t", i, pipe->play_cnt);
+ }
+ tot += scnprintf(bp + tot, len - tot, "\n");
+
+ for (i = 0; i < mdata->nrgb_pipes; i++) {
+ pipe = mdata->rgb_pipes + i;
+ tot += scnprintf(bp + tot, len - tot,
+ "RGB%d : %08u\t", i, pipe->play_cnt);
+ }
+ tot += scnprintf(bp + tot, len - tot, "\n");
+
+ for (i = 0; i < mdata->ndma_pipes; i++) {
+ pipe = mdata->dma_pipes + i;
+ tot += scnprintf(bp + tot, len - tot,
+ "DMA%d : %08u\t", i, pipe->play_cnt);
+ }
+ tot += scnprintf(bp + tot, len - tot, "\n");
+
+ if (copy_to_user(buff, bp, tot))
+ return -EFAULT;
+
+ *ppos += tot; /* increase offset */
+
+ return tot;
+}
+
+static const struct file_operations mdss_stat_fops = {
+ .open = mdss_debug_stat_open,
+ .release = mdss_debug_stat_release,
+ .read = mdss_debug_stat_read,
+};
+
static int mdss_debugfs_cleanup(struct mdss_debug_data *mdd)
{
struct mdss_debug_base *base, *tmp;
@@ -330,6 +420,7 @@
mdss_debugfs_cleanup(mdd);
return -ENODEV;
}
+ debugfs_create_file("stat", 0644, mdd->root, mdata, &mdss_stat_fops);
debugfs_create_u32("min_mdp_clk", 0644, mdd->root,
(u32 *)&mdata->min_mdp_clk);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index ccec0fc..22ff08c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -59,6 +59,9 @@
mdss_dsi1_hw.ptr = (void *)(ctrl);
ctrl->mdss_hw = &mdss_dsi1_hw;
}
+
+ if (!mdss_register_irq(ctrl->mdss_hw))
+ pr_err("%s: mdss_register_irq failed.\n", __func__);
}
void mdss_dsi_irq_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable, int isr)
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index e28a4e9..213fcff 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2734,6 +2734,10 @@
return rc;
}
+ rc = mdss_register_irq(&hdmi_tx_hw);
+ if (rc)
+ DEV_ERR("%s: mdss_register_irq failed.\n", __func__);
+
return rc;
} /* hdmi_tx_register_panel */
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 8be64b2..51776db 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -228,6 +228,27 @@
return IRQ_HANDLED;
}
+int mdss_register_irq(struct mdss_hw *hw)
+{
+ unsigned long irq_flags;
+ u32 ndx_bit;
+
+ if (!hw || hw->hw_ndx >= MDSS_MAX_HW_BLK)
+ return -EINVAL;
+
+ ndx_bit = BIT(hw->hw_ndx);
+
+ spin_lock_irqsave(&mdss_lock, irq_flags);
+ if (!mdss_irq_handlers[hw->hw_ndx])
+ mdss_irq_handlers[hw->hw_ndx] = hw;
+ else
+ pr_err("panel %d's irq at %p is already registered\n",
+ hw->hw_ndx, hw->irq_handler);
+ spin_unlock_irqrestore(&mdss_lock, irq_flags);
+
+ return 0;
+} /* mdss_regsiter_irq */
+EXPORT_SYMBOL(mdss_register_irq);
void mdss_enable_irq(struct mdss_hw *hw)
{
@@ -237,6 +258,11 @@
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
+ if (!mdss_irq_handlers[hw->hw_ndx]) {
+ pr_err("failed. First register the irq then enable it.\n");
+ return;
+ }
+
ndx_bit = BIT(hw->hw_ndx);
pr_debug("Enable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx,
@@ -247,7 +273,6 @@
pr_debug("MDSS HW ndx=%d is already set, mask=%x\n",
hw->hw_ndx, mdss_res->irq_mask);
} else {
- mdss_irq_handlers[hw->hw_ndx] = hw;
mdss_res->irq_mask |= ndx_bit;
if (!mdss_res->irq_ena) {
mdss_res->irq_ena = true;
@@ -277,7 +302,6 @@
hw->hw_ndx, mdss_res->mdp_irq_mask,
mdss_res->mdp_hist_irq_mask);
} else {
- mdss_irq_handlers[hw->hw_ndx] = NULL;
mdss_res->irq_mask &= ~ndx_bit;
if (mdss_res->irq_mask == 0) {
mdss_res->irq_ena = false;
@@ -1042,6 +1066,10 @@
if (rc)
pr_err("unable to register mdp instance\n");
+ rc = mdss_register_irq(&mdss_mdp_hw);
+ if (rc)
+ pr_err("mdss_register_irq failed.\n");
+
probe_done:
if (IS_ERR_VALUE(rc)) {
mdss_res = NULL;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 07b083a..25c5871 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 vsync_cnt;
u32 underrun_cnt;
u16 width;
@@ -217,6 +218,21 @@
struct mdss_mdp_img_data p[MAX_PLANES];
};
+struct pp_hist_col_info {
+ u32 col_state;
+ u32 col_en;
+ u32 read_request;
+ u32 hist_cnt_read;
+ u32 hist_cnt_sent;
+ u32 hist_cnt_time;
+ u32 frame_cnt;
+ u32 is_kick_ready;
+ struct completion comp;
+ u32 data[HIST_V_SIZE];
+ struct mutex hist_mutex;
+ spinlock_t hist_lock;
+};
+
struct pp_sts_type {
u32 pa_sts;
u32 pcc_sts;
@@ -233,6 +249,7 @@
struct mdss_pipe_pp_res {
u32 igc_c0_c1[IGC_LUT_ENTRIES];
u32 igc_c2[IGC_LUT_ENTRIES];
+ struct pp_hist_col_info hist;
struct pp_sts_type pp_sts;
};
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index fa53656..4e51100 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -294,6 +294,8 @@
ctl->stop_fnc = NULL;
ctl->prepare_fnc = NULL;
ctl->display_fnc = NULL;
+ ctl->wait_fnc = NULL;
+ ctl->set_vsync_handler = NULL;
mutex_unlock(&mdss_mdp_ctl_lock);
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index d6b0fb2..006a8dd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -180,6 +180,7 @@
pr_debug("%s: ctl=%d intf_num=%d\n", __func__, ctl->num, ctl->intf_num);
vsync_time = ktime_get();
+ ctl->vsync_cnt++;
spin_lock(&ctx->vsync_lock);
if (ctx->vsync_handler)
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 0426784..6e631e9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -282,8 +282,9 @@
}
vsync_time = ktime_get();
+ ctl->vsync_cnt++;
- pr_debug("intr ctl=%d\n", ctl->num);
+ pr_debug("intr ctl=%d vsync cnt=%u\n", ctl->num, ctl->vsync_cnt);
complete_all(&ctx->vsync_comp);
spin_lock(&ctx->vsync_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 2c0d5e0..2e20eb6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -88,18 +88,6 @@
HIST_READY,
};
-struct pp_hist_col_info {
- u32 col_state;
- u32 col_en;
- u32 read_request;
- u32 hist_cnt_read;
- u32 hist_cnt_sent;
- u32 frame_cnt;
- u32 is_kick_ready;
- struct completion comp;
- u32 data[HIST_V_SIZE];
-};
-
static u32 dither_matrix[16] = {
15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10};
static u32 dither_depth_map[9] = {
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 969b400..2f77d29 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -118,10 +118,10 @@
/* This needs to be modified manually now, when we add
a new RANGE of SSIDs to the msg_mask_tbl */
#define MSG_MASK_TBL_CNT 24
-#define EVENT_LAST_ID 0x09AB
+#define EVENT_LAST_ID 0x09B2
#define MSG_SSID_0 0
-#define MSG_SSID_0_LAST 94
+#define MSG_SSID_0_LAST 97
#define MSG_SSID_1 500
#define MSG_SSID_1_LAST 506
#define MSG_SSID_2 1000
@@ -287,6 +287,9 @@
MSG_LVL_LOW,
MSG_LVL_LOW,
MSG_LVL_HIGH,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL,
MSG_LVL_LOW
};
@@ -722,7 +725,7 @@
/* LOG CODES */
#define LOG_0 0x0
-#define LOG_1 0x1755
+#define LOG_1 0x17F4
#define LOG_2 0x0
#define LOG_3 0x0
#define LOG_4 0x4910
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 19face8..c2b35c8 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -108,7 +108,6 @@
#define DMX_CHECK_CRC 0x01
#define DMX_ONESHOT 0x02
#define DMX_IMMEDIATE_START 0x04
-#define DMX_ENABLE_INDEXING 0x08
#define DMX_KERNEL_CLIENT 0x8000
struct dmx_sct_filter_params
@@ -120,25 +119,39 @@
};
-/* Indexing: supported video standards */
-enum dmx_indexing_video_standard {
- DMX_INDEXING_MPEG2,
- DMX_INDEXING_H264,
- DMX_INDEXING_VC1
+enum dmx_video_codec {
+ DMX_VIDEO_CODEC_MPEG2,
+ DMX_VIDEO_CODEC_H264,
+ DMX_VIDEO_CODEC_VC1
};
-/* Indexing: Supported video profiles */
-enum dmx_indexing_video_profile {
- DMX_INDEXING_MPEG2_ANY,
- DMX_INDEXING_H264_ANY,
- DMX_INDEXING_VC1_ANY
-};
-
-/* Indexing: video configuration parameters */
-struct dmx_indexing_video_params {
- enum dmx_indexing_video_standard standard;
- enum dmx_indexing_video_profile profile;
-};
+/* Index entries types */
+#define DMX_IDX_RAI 0x00000001
+#define DMX_IDX_PUSI 0x00000002
+#define DMX_IDX_MPEG_SEQ_HEADER 0x00000004
+#define DMX_IDX_MPEG_GOP 0x00000008
+#define DMX_IDX_MPEG_FIRST_SEQ_FRAME_START 0x00000010
+#define DMX_IDX_MPEG_FIRST_SEQ_FRAME_END 0x00000020
+#define DMX_IDX_MPEG_I_FRAME_START 0x00000040
+#define DMX_IDX_MPEG_I_FRAME_END 0x00000080
+#define DMX_IDX_MPEG_P_FRAME_START 0x00000100
+#define DMX_IDX_MPEG_P_FRAME_END 0x00000200
+#define DMX_IDX_MPEG_B_FRAME_START 0x00000400
+#define DMX_IDX_MPEG_B_FRAME_END 0x00000800
+#define DMX_IDX_H264_SPS 0x00001000
+#define DMX_IDX_H264_PPS 0x00002000
+#define DMX_IDX_H264_FIRST_SPS_FRAME_START 0x00004000
+#define DMX_IDX_H264_FIRST_SPS_FRAME_END 0x00008000
+#define DMX_IDX_H264_IDR_START 0x00010000
+#define DMX_IDX_H264_IDR_END 0x00020000
+#define DMX_IDX_H264_NON_IDR_START 0x00040000
+#define DMX_IDX_H264_NON_IDR_END 0x00080000
+#define DMX_IDX_VC1_SEQ_HEADER 0x00100000
+#define DMX_IDX_VC1_ENTRY_POINT 0x00200000
+#define DMX_IDX_VC1_FIRST_SEQ_FRAME_START 0x00400000
+#define DMX_IDX_VC1_FIRST_SEQ_FRAME_END 0x00800000
+#define DMX_IDX_VC1_FRAME_START 0x01000000
+#define DMX_IDX_VC1_FRAME_END 0x02000000
struct dmx_pes_filter_params
{
@@ -160,7 +173,7 @@
*/
__u32 rec_chunk_size;
- struct dmx_indexing_video_params video_params;
+ enum dmx_video_codec video_codec;
};
struct dmx_buffer_status {
@@ -213,7 +226,10 @@
DMX_EVENT_NEW_ES_DATA = 0x00000080,
/* Data markers */
- DMX_EVENT_MARKER = 0x00000100
+ DMX_EVENT_MARKER = 0x00000100,
+
+ /* New indexing entry is ready */
+ DMX_EVENT_NEW_INDEX_ENTRY = 0x00000200
};
enum dmx_oob_cmd {
@@ -377,6 +393,34 @@
__u64 id;
};
+/* Indexing information associated with DMX_EVENT_NEW_INDEX_ENTRY event */
+struct dmx_index_event_info {
+ /* Index entry type, one of of DMX_IDX_* */
+ __u64 type;
+
+ /*
+ * The PID the index entry belongs to.
+ * In case of recording filter, multiple PIDs may exist in the same
+ * filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
+ */
+ __u16 pid;
+
+ /*
+ * The TS packet number in the recorded data at which
+ * the indexing event is found.
+ */
+ __u64 match_tsp_num;
+
+ /*
+ * The TS packet number in the recorded data preceeding
+ * match_tsp_num and has PUSI set.
+ */
+ __u64 last_pusi_tsp_num;
+
+ /* STC associated with match_tsp_num, in 27MHz */
+ __u64 stc;
+};
+
/*
* Filter's event returned through DMX_GET_EVENT.
* poll with POLLPRI would block until events are available.
@@ -391,6 +435,7 @@
struct dmx_pcr_event_info pcr;
struct dmx_es_data_event_info es_data;
struct dmx_marker_event_info marker;
+ struct dmx_index_event_info index;
} params;
};
@@ -642,6 +687,22 @@
__u32 wakeup_threshold;
};
+struct dmx_indexing_params {
+ /*
+ * PID to index. In case of recording filter, multiple PIDs
+ * may exist in the same filter through DMX_ADD_PID ioctl.
+ * It is assumed that the PID was already added using DMX_ADD_PID
+ * or an error will be reported.
+ */
+ __u16 pid;
+
+ /* enable or disable indexing, default is disabled */
+ int enable;
+
+ /* combination of DMX_IDX_* bits */
+ __u64 types;
+};
+
#define DMX_START _IO('o', 41)
#define DMX_STOP _IO('o', 42)
#define DMX_SET_FILTER _IOW('o', 43, struct dmx_sct_filter_params)
@@ -669,5 +730,6 @@
#define DMX_SET_EVENTS_MASK _IOW('o', 66, struct dmx_events_mask)
#define DMX_GET_EVENTS_MASK _IOR('o', 67, struct dmx_events_mask)
#define DMX_PUSH_OOB_COMMAND _IOW('o', 68, struct dmx_oob_command)
+#define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
#endif /*_DVBDMX_H_*/
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index a87246c..3bb38ad 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -45,14 +45,14 @@
struct list_head next_chunk; /* next chunk in pool */
atomic_t avail;
phys_addr_t phys_addr; /* physical starting address of memory chunk */
- unsigned long start_addr; /* starting address of memory chunk */
- unsigned long end_addr; /* ending address of memory chunk */
+ u64 start_addr; /* starting address of memory chunk */
+ u64 end_addr; /* ending address of memory chunk */
unsigned long bits[0]; /* bitmap for allocating memory chunk */
};
extern struct gen_pool *gen_pool_create(int, int);
-extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long);
-extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t,
+extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, u64);
+extern int gen_pool_add_virt(struct gen_pool *, u64, phys_addr_t,
size_t, int);
/**
* gen_pool_add - add a new chunk of special memory to the pool
@@ -66,19 +66,19 @@
*
* Returns 0 on success or a -ve errno on failure.
*/
-static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr,
+static inline int gen_pool_add(struct gen_pool *pool, u64 addr,
size_t size, int nid)
{
return gen_pool_add_virt(pool, addr, -1, size, nid);
}
extern void gen_pool_destroy(struct gen_pool *);
-extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
+extern void gen_pool_free(struct gen_pool *, u64, size_t);
extern void gen_pool_for_each_chunk(struct gen_pool *,
void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *);
extern size_t gen_pool_avail(struct gen_pool *);
extern size_t gen_pool_size(struct gen_pool *);
-unsigned long __must_check
+u64 __must_check
gen_pool_alloc_aligned(struct gen_pool *pool, size_t size,
unsigned alignment_order);
@@ -90,7 +90,7 @@
* Allocate the requested number of bytes from the specified pool.
* Uses a first-fit algorithm.
*/
-static inline unsigned long __must_check
+static inline u64 __must_check
gen_pool_alloc(struct gen_pool *pool, size_t size)
{
return gen_pool_alloc_aligned(pool, size, 0);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 3b5742e..9eef3a0 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -454,6 +454,12 @@
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
+ if (!host->sdio_irqs) {
+ pr_err("%s: SDIO interrupt recieved without function driver claiming an irq\n",
+ mmc_hostname(host));
+ return;
+ }
+
host->ops->enable_sdio_irq(host, 0);
host->sdio_irq_pending = true;
wake_up_process(host->sdio_irq_thread);
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 407a005..538185f 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -208,6 +208,7 @@
struct pm_qos_request pm_qos_req_dma;
struct sdhci_next next_data;
+ ktime_t data_start_time;
unsigned long private[0] ____cacheline_aligned;
};
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 396fcd8..20b7317 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -9,6 +9,7 @@
ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CP,
ION_HEAP_TYPE_SECURE_DMA,
+ ION_HEAP_TYPE_REMOVED,
};
/**
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 7e1a709..60567fa 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -289,14 +289,19 @@
#define MDP_PP_IGC_FLAG_ROM0 0x10
#define MDP_PP_IGC_FLAG_ROM1 0x20
-#define MDSS_PP_DSPP_CFG 0x0000
-#define MDSS_PP_SSPP_CFG 0x4000
-#define MDSS_PP_LM_CFG 0x8000
-#define MDSS_PP_WB_CFG 0xC000
+#define MDSS_PP_DSPP_CFG 0x000
+#define MDSS_PP_SSPP_CFG 0x100
+#define MDSS_PP_LM_CFG 0x200
+#define MDSS_PP_WB_CFG 0x300
-#define MDSS_PP_LOCATION_MASK 0xC000
-#define MDSS_PP_LOGICAL_MASK 0x3FFF
+#define MDSS_PP_ARG_MASK 0x3C00
+#define MDSS_PP_ARG_NUM 4
+#define MDSS_PP_ARG_SHIFT 8
+#define MDSS_PP_LOCATION_MASK 0x0300
+#define MDSS_PP_LOGICAL_MASK 0x00FF
+#define MDSS_PP_ADD_ARG(var, arg) ((var) | (0x1 << (MDSS_PP_ARG_SHIFT + (arg))))
+#define PP_ARG(x, var) ((var) & (0x1 << (MDSS_PP_ARG_SHIFT + (x))))
#define PP_LOCAT(var) ((var) & MDSS_PP_LOCATION_MASK)
#define PP_BLOCK(var) ((var) & MDSS_PP_LOGICAL_MASK)
@@ -326,6 +331,7 @@
#define MDP_OVERLAY_PP_PA_CFG 0x4
#define MDP_OVERLAY_PP_IGC_CFG 0x8
#define MDP_OVERLAY_PP_SHARP_CFG 0x10
+#define MDP_OVERLAY_PP_HIST_CFG 0x20
#define MDP_CSC_FLAG_ENABLE 0x1
#define MDP_CSC_FLAG_YUV_IN 0x2
@@ -361,6 +367,14 @@
uint32_t *c2_data;
};
+struct mdp_histogram_cfg {
+ uint32_t ops;
+ uint32_t block;
+ uint8_t frame_cnt;
+ uint8_t bit_mask;
+ uint16_t num_bins;
+};
+
struct mdp_overlay_pp_params {
uint32_t config_ops;
struct mdp_csc_cfg csc_cfg;
@@ -368,6 +382,7 @@
struct mdp_pa_cfg pa_cfg;
struct mdp_igc_lut_data igc_cfg;
struct mdp_sharp_cfg sharp_cfg;
+ struct mdp_histogram_cfg hist_cfg;
};
struct mdp_overlay {
@@ -433,7 +448,7 @@
MDP_BLOCK_DMA_S,
MDP_BLOCK_DMA_E,
MDP_BLOCK_OVERLAY_2,
- MDP_LOGICAL_BLOCK_DISP_0 = 0x1000,
+ MDP_LOGICAL_BLOCK_DISP_0 = 0x10,
MDP_LOGICAL_BLOCK_DISP_1,
MDP_LOGICAL_BLOCK_DISP_2,
MDP_BLOCK_MAX,
@@ -552,6 +567,65 @@
uint32_t data;
};
+#define MDSS_AD_MODE_AUTO_BL 0x0
+#define MDSS_AD_MODE_AUTO_STR 0x1
+#define MDSS_AD_MODE_TARG_STR 0x3
+#define MDSS_AD_MODE_MAN_STR 0x7
+
+#define MDP_PP_AD_INIT 0x10
+#define MDP_PP_AD_CFG 0x20
+
+struct mdss_ad_init {
+ uint32_t asym_lut[33];
+ uint32_t color_corr_lut[33];
+ uint8_t i_control[2];
+ uint16_t black_lvl;
+ uint16_t white_lvl;
+ uint8_t var;
+ uint8_t limit_ampl;
+ uint8_t i_dither;
+ uint8_t slope_max;
+ uint8_t slope_min;
+ uint8_t dither_ctl;
+ uint8_t format;
+ uint8_t auto_size;
+ uint16_t frame_w;
+ uint16_t frame_h;
+ uint8_t logo_v;
+ uint8_t logo_h;
+};
+
+struct mdss_ad_cfg {
+ uint32_t mode;
+ uint32_t al_calib_lut[33];
+ uint16_t backlight_min;
+ uint16_t backlight_max;
+ uint16_t backlight_scale;
+ uint16_t amb_light_min;
+ uint16_t filter[2];
+ uint16_t calib[4];
+ uint8_t strength_limit;
+ uint8_t t_filter_recursion;
+};
+
+/* ops uses standard MDP_PP_* flags */
+struct mdss_ad_init_cfg {
+ uint32_t ops;
+ union {
+ struct mdss_ad_init init;
+ struct mdss_ad_cfg cfg;
+ } params;
+};
+
+/* mode uses MDSS_AD_MODE_* flags */
+struct mdss_ad_input {
+ uint32_t mode;
+ union {
+ uint32_t amb_light;
+ uint32_t strength;
+ } in;
+};
+
enum {
mdp_op_pcc_cfg,
mdp_op_csc_cfg,
@@ -562,6 +636,8 @@
mdp_op_dither_cfg,
mdp_op_gamut_cfg,
mdp_op_calib_cfg,
+ mdp_op_ad_cfg,
+ mdp_op_ad_input,
mdp_op_max,
};
@@ -586,6 +662,8 @@
struct mdp_dither_cfg_data dither_cfg_data;
struct mdp_gamut_cfg_data gamut_cfg_data;
struct mdp_calib_config_data calib_cfg;
+ struct mdss_ad_init_cfg ad_init_cfg;
+ struct mdss_ad_input ad_input;
} data;
};
diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h
index 2c9a613..f14cc52 100644
--- a/include/linux/msm_thermal.h
+++ b/include/linux/msm_thermal.h
@@ -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
@@ -17,9 +17,16 @@
struct msm_thermal_data {
uint32_t sensor_id;
uint32_t poll_ms;
- uint32_t limit_temp_degC;
- uint32_t temp_hysteresis_degC;
+ int32_t limit_temp_degC;
+ int32_t temp_hysteresis_degC;
uint32_t freq_step;
+ int32_t core_limit_temp_degC;
+ int32_t core_temp_hysteresis_degC;
+ uint32_t core_control_mask;
+ int32_t vdd_rstr_temp_degC;
+ int32_t vdd_rstr_temp_hyst_degC;
+ int32_t psm_temp_degC;
+ int32_t psm_temp_hyst_degC;
};
#ifdef CONFIG_THERMAL_MONITOR
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 8aa7c17..757f1dc 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -41,6 +41,14 @@
int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
int msm_tsens_early_init(struct tsens_platform_data *pdata);
+
+#if defined(CONFIG_THERMAL_TSENS8974)
+int __init tsens_tm_init_driver(void);
+#else
+static inline int __init tsens_tm_init_driver(void)
+{ return -ENXIO; }
+#endif
+
#if defined(CONFIG_THERMAL_TSENS8974) || defined(CONFIG_THERMAL_TSENS8960)
int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
#else
diff --git a/include/linux/smsc3503.h b/include/linux/smsc3503.h
index d5df871..1e28a58 100644
--- a/include/linux/smsc3503.h
+++ b/include/linux/smsc3503.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 software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -42,9 +42,9 @@
#define OCSPINSEL (1<<5)
struct smsc_hub_platform_data {
- unsigned hub_reset;
- unsigned refclk_gpio;
- unsigned int_gpio;
+ int hub_reset;
+ int refclk_gpio;
+ int int_gpio;
};
#endif
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 9cf1b8b..604ee09 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -171,7 +171,7 @@
*
* Returns 0 on success or a -ve errno on failure.
*/
-int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phys,
+int gen_pool_add_virt(struct gen_pool *pool, u64 virt, phys_addr_t phys,
size_t size, int nid)
{
struct gen_pool_chunk *chunk;
@@ -208,7 +208,7 @@
*
* Returns the physical address on success, or -1 on error.
*/
-phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
+phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, u64 addr)
{
struct gen_pool_chunk *chunk;
phys_addr_t paddr = -1;
@@ -273,11 +273,11 @@
* Uses a first-fit algorithm. Can not be used in NMI handler on
* architectures without NMI-safe cmpxchg implementation.
*/
-unsigned long gen_pool_alloc_aligned(struct gen_pool *pool, size_t size,
+u64 gen_pool_alloc_aligned(struct gen_pool *pool, size_t size,
unsigned alignment_order)
{
struct gen_pool_chunk *chunk;
- unsigned long addr = 0, align_mask = 0;
+ u64 addr = 0, align_mask = 0;
int order = pool->min_alloc_order;
int nbits, start_bit = 0, remain;
@@ -314,7 +314,7 @@
goto retry;
}
- addr = chunk->start_addr + ((unsigned long)start_bit << order);
+ addr = chunk->start_addr + ((u64)start_bit << order);
size = nbits << pool->min_alloc_order;
atomic_sub(size, &chunk->avail);
break;
@@ -334,7 +334,7 @@
* pool. Can not be used in NMI handler on architectures without
* NMI-safe cmpxchg implementation.
*/
-void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
+void gen_pool_free(struct gen_pool *pool, u64 addr, size_t size)
{
struct gen_pool_chunk *chunk;
int order = pool->min_alloc_order;
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 866f524..f5f4e23 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -102,6 +102,12 @@
#define SITAR_MBHC_STATUS_REL_DETECTION 0x0C
#define SITAR_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 200
+#define CUT_OF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x01
+#define CF_MIN_3DB_150HZ 0x02
+
+
static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
@@ -194,6 +200,15 @@
0, /* AIF1_CAP */
};
+struct hpf_work {
+ struct sitar_priv *sitar;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
struct sitar_priv {
struct snd_soc_codec *codec;
u32 mclk_freq;
@@ -1755,6 +1770,8 @@
snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
break;
case SND_SOC_DAPM_POST_PMU:
+
+ usleep_range(20000, 20000);
if (sitar->mbhc_polling_active &&
sitar->mbhc_cfg.micbias == micb_line) {
SITAR_ACQUIRE_LOCK(sitar->codec_resource_lock);
@@ -1780,36 +1797,141 @@
return 0;
}
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct sitar_priv *sitar;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ sitar = hpf_work->sitar;
+ codec = hpf_work->sitar->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 8;
+
+ pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+ hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg,
+ CUT_OF_FREQ_MASK, hpf_cut_of_freq << 4);
+}
+
static int sitar_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u16 dec_reset_reg, gain_reg;
- u8 current_gain;
+ u16 dec_reset_reg, gain_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ unsigned int decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0;
+ u8 dec_hpf_cut_of_freq, current_gain;
pr_debug("%s %d\n", __func__, event);
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "1234"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
else {
pr_err("%s: Error, incorrect dec\n", __func__);
- return -EINVAL;
+ ret = EINVAL;
+ goto out;
}
+ tx_vol_ctl_reg = SITAR_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
+ tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ /* Enable TX Digital Mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1 << w->shift);
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+ dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq &
+ CUT_OF_FREQ_MASK) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+ /* Set cut off freq to CF_MIN_3DB_150HZ (0x01) */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg,
+ CUT_OF_FREQ_MASK, CF_MIN_3DB_150HZ << 4);
+ }
+
+ /* enable HPF */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x00);
+
break;
+
case SND_SOC_DAPM_POST_PMU:
+ /* Disable TX Digital Mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+
/* Reprogram the digital gain after power up of Decimator */
gain_reg = SITAR_A_CDC_TX1_VOL_CTL_GAIN + (8 * w->shift);
current_gain = snd_soc_read(codec, gain_reg);
snd_soc_write(codec, gain_reg, current_gain);
break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Enable Digital Mute, Cancel possibly scheduled work */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, CUT_OF_FREQ_MASK,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+ break;
+
}
- return 0;
+
+out:
+ kfree(widget_name);
+ return ret;
+
}
static int sitar_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
@@ -2278,16 +2400,23 @@
SND_SOC_DAPM_MUX_E("DEC1 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
&dec1_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC2 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
&dec2_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC3 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
&dec3_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MUX_E("DEC4 MUX", SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
&dec4_mux, sitar_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
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),
@@ -5316,6 +5445,14 @@
return -ENOMEM;
}
+ for (i = 0; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].sitar = sitar;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
+
+
/* Make sure mbhc micbias register addresses are zeroed out */
memset(&sitar->mbhc_bias_regs, 0,
sizeof(struct mbhc_micbias_regs));
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index fd3e0dc..a7069a6 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -193,6 +193,7 @@
s32 dmic_5_6_clk_cnt;
u32 anc_slot;
+ bool anc_func;
/*track tapan interface type*/
u8 intf_type;
@@ -348,6 +349,58 @@
return 0;
}
+static int tapan_get_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = (tapan->anc_func == true ? 1 : 0);
+ return 0;
+}
+
+static int tapan_put_anc_func(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ mutex_lock(&dapm->codec->mutex);
+ tapan->anc_func = (!ucontrol->value.integer.value[0] ? false : true);
+
+ dev_err(codec->dev, "%s: anc_func %x", __func__, tapan->anc_func);
+
+ if (tapan->anc_func == true) {
+ pr_info("enable anc virtual widgets");
+ 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 {
+ pr_info("disable anc virtual widgets");
+ 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_dapm_sync(dapm);
+ mutex_unlock(&dapm->codec->mutex);
+ return 0;
+}
+
static int tapan_pa_gain_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -713,6 +766,10 @@
SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
};
+static const char *const tapan_anc_func_text[] = {"OFF", "ON"};
+static const struct soc_enum tapan_anc_func_enum =
+ SOC_ENUM_SINGLE_EXT(2, tapan_anc_func_text);
+
/*cut of frequency for high pass filter*/
static const char * const cf_text[] = {
"MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
@@ -770,11 +827,11 @@
SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 7, 1,
line_gain),
- SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 13, 0, analog_gain),
- SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 13, 0, analog_gain),
- SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 13, 0, analog_gain),
- SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 13, 0, analog_gain),
- SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 13, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 19, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 19, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 19, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 19, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 19, 0, analog_gain),
SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
@@ -803,9 +860,10 @@
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
- SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, tapan_get_anc_slot,
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tapan_get_anc_slot,
tapan_put_anc_slot),
-
+ SOC_ENUM_EXT("ANC Function", tapan_anc_func_enum, tapan_get_anc_func,
+ tapan_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),
@@ -943,6 +1001,10 @@
"RSVD", "RSVD"
};
+static const char * const anc1_fb_mux_text[] = {
+ "ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
static const char * const iir1_inp1_text[] = {
"ZERO", "DEC1", "DEC2", "DEC3", "DEC4",
"RX1", "RX2", "RX3", "RX4", "RX5"
@@ -1031,6 +1093,9 @@
static const struct soc_enum anc2_mux_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B1_CTL, 4, 15, anc_mux_text);
+static const struct soc_enum anc1_fb_mux_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
+
static const struct soc_enum iir1_inp1_mux_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_EQ1_B1_CTL, 0, 10, iir1_inp1_text);
@@ -1200,6 +1265,9 @@
static const struct snd_kcontrol_new anc2_mux =
SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
+static const struct snd_kcontrol_new anc1_fb_mux =
+ SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
+
static const struct snd_kcontrol_new dac1_switch[] = {
SOC_DAPM_SINGLE("Switch", TAPAN_A_RX_EAR_EN, 5, 1, 0)
};
@@ -1322,11 +1390,11 @@
return 0;
}
break;
- default:
- dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
- mutex_unlock(&codec->mutex);
- return -EINVAL;
- }
+ default:
+ dev_err(codec->dev, "Unknown AIF %d\n", dai_id);
+ mutex_unlock(&codec->mutex);
+ return -EINVAL;
+ }
dev_dbg(codec->dev, "%s: name %s sname %s updated value %u shift %d\n",
__func__, widget->name, widget->sname,
widget->value, widget->shift);
@@ -1392,14 +1460,14 @@
break;
case 2:
if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
- &tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+ &tapan_p->dai[AIF2_PB].wcd9xxx_ch_list))
goto pr_err;
list_add_tail(&core->rx_chs[port_id].list,
&tapan_p->dai[AIF2_PB].wcd9xxx_ch_list);
break;
case 3:
if (wcd9xxx_rx_vport_validation(port_id + core->num_tx_port,
- &tapan_p->dai[AIF1_PB].wcd9xxx_ch_list))
+ &tapan_p->dai[AIF3_PB].wcd9xxx_ch_list))
goto pr_err;
list_add_tail(&core->rx_chs[port_id].list,
&tapan_p->dai[AIF3_PB].wcd9xxx_ch_list);
@@ -1668,9 +1736,11 @@
int anc_size_remaining;
u32 *anc_ptr;
u16 reg;
- u8 mask, val;
+ u8 mask, val, old_val;
dev_dbg(codec->dev, "%s %d\n", __func__, event);
+ if (tapan->anc_func == 0)
+ return 0;
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1737,14 +1807,21 @@
for (i = 0; i < anc_writes_size; i++) {
TAPAN_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
mask, val);
- snd_soc_write(codec, reg, 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:
- snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+ msleep(40);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_ANC1_B1_CTL, 0x01, 0x00);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_ANC2_B1_CTL, 0x02, 0x00);
+ msleep(20);
+ snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0x0F);
snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+ snd_soc_write(codec, TAPAN_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
break;
}
return 0;
@@ -2137,12 +2214,12 @@
dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
if (w->shift == 5) {
- 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_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_HPHR;
} else {
pr_err("%s: Invalid w->shift %d\n", __func__, w->shift);
@@ -2182,6 +2259,46 @@
return 0;
}
+static int tapan_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 = tapan_hph_pa_event(w, kcontrol, event);
+ if (w->shift == 4) {
+ ret |= tapan_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ if (w->shift == 4) {
+ snd_soc_update_bits(codec,
+ TAPAN_A_RX_HPH_CNP_EN, 0x30, 0x30);
+ msleep(30);
+ }
+ ret = tapan_hph_pa_event(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAPAN_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ msleep(40);
+ }
+ if (w->shift == 5) {
+ snd_soc_update_bits(codec,
+ TAPAN_A_TX_7_MBHC_EN, 0x80, 00);
+ ret |= tapan_codec_enable_anc(w, kcontrol, event);
+ }
+ case SND_SOC_DAPM_POST_PMD:
+ ret = tapan_hph_pa_event(w, kcontrol, event);
+ break;
+ }
+ return ret;
+}
+
static const struct snd_soc_dapm_widget tapan_dapm_i2s_widgets[] = {
SND_SOC_DAPM_SUPPLY("I2S_CLK", TAPAN_A_CDC_CLK_I2S_CTL,
4, 0, NULL, 0),
@@ -2296,6 +2413,11 @@
{"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"},
+
/* Headset (RX MIX1 and RX MIX2) */
{"HEADPHONE", NULL, "HPHL"},
{"HEADPHONE", NULL, "HPHR"},
@@ -2308,6 +2430,33 @@
{"HPHR_PA_MIXER", NULL, "HPHR DAC"},
{"HPHR DAC", NULL, "RX_BIAS"},
+ {"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", "ADC5", "ADC5"},
+ {"ANC1 MUX", "DMIC1", "DMIC1"},
+ {"ANC1 MUX", "DMIC2", "DMIC2"},
+ {"ANC1 MUX", "DMIC3", "DMIC3"},
+ {"ANC1 MUX", "DMIC4", "DMIC4"},
+ {"ANC2 MUX", "ADC1", "ADC1"},
+ {"ANC2 MUX", "ADC2", "ADC2"},
+ {"ANC2 MUX", "ADC3", "ADC3"},
+ {"ANC2 MUX", "ADC4", "ADC4"},
+ {"ANC2 MUX", "ADC5", "ADC5"},
+ {"ANC2 MUX", "DMIC1", "DMIC1"},
+ {"ANC2 MUX", "DMIC2", "DMIC2"},
+ {"ANC2 MUX", "DMIC3", "DMIC3"},
+ {"ANC2 MUX", "DMIC4", "DMIC4"},
+
+ {"ANC HPHR", NULL, "CDC_CONN"},
+
{"DAC1", "Switch", "CLASS_H_DSM MUX"},
{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
{"HPHR DAC", NULL, "RX2 CHAIN"},
@@ -2336,6 +2485,8 @@
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
{"CLASS_H_DSM MUX", "RX_HPHL", "RX1 CHAIN"},
+ {"RX1 MIX2", NULL, "ANC1 MUX"},
+ {"RX2 MIX2", NULL, "ANC2 MUX"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
@@ -2564,6 +2715,14 @@
(reg <= TAPAN_A_CDC_IIR2_COEF_B2_CTL))
return 1;
+ /* ANC filter registers are not cacheable */
+ if ((reg >= TAPAN_A_CDC_ANC1_IIR_B1_CTL) &&
+ (reg <= TAPAN_A_CDC_ANC1_LPF_B2_CTL))
+ return 1;
+ if ((reg >= TAPAN_A_CDC_ANC2_IIR_B1_CTL) &&
+ (reg <= TAPAN_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
*/
@@ -2850,7 +3009,7 @@
tapan->comp_fs[comp_rx_path[j]]
= compander_fs;
}
- if (j <= 2)
+ if (j <= 1)
rx_mix_1_reg_1 += 3;
else
rx_mix_1_reg_1 += 2;
@@ -3419,6 +3578,33 @@
return 0;
}
+static int tapan_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 = tapan_codec_enable_anc(w, kcontrol, event);
+ msleep(50);
+ snd_soc_update_bits(codec, TAPAN_A_RX_EAR_EN, 0x10, 0x10);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ ret = tapan_codec_enable_ear_pa(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, TAPAN_A_RX_EAR_EN, 0x10, 0x00);
+ msleep(40);
+ ret |= tapan_codec_enable_anc(w, kcontrol, event);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = tapan_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
@@ -3695,9 +3881,21 @@
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,
- tapan_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,
+ tapan_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,
+ tapan_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,
+ tapan_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"),
SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
@@ -4304,6 +4502,14 @@
(void) tapan_setup_irqs(tapan);
atomic_set(&kp_tapan_priv, (unsigned long)tapan);
+ 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/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index c5cb560..e74a0dd 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -93,6 +93,7 @@
static const DECLARE_TLV_DB_LINEAR(compressed3_rx_vol_gain, 0,
INT_RX_VOL_MAX_STEPS);
static int msm_route_ec_ref_rx;
+static int msm_route_ext_ec_ref;
/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
#define MAX_EQ_SESSIONS MSM_FRONTEND_DAI_CS_VOICE
@@ -1425,6 +1426,57 @@
msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put),
};
+static int msm_routing_ext_ec_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: ext_ec_ref_rx = %x\n", __func__, msm_route_ext_ec_ref);
+
+ mutex_lock(&routing_lock);
+ ucontrol->value.integer.value[0] = msm_route_ext_ec_ref;
+ mutex_unlock(&routing_lock);
+ return 0;
+}
+
+static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ int mux = ucontrol->value.enumerated.item[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int ret = 0;
+
+ pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n",
+ __func__, msm_route_ext_ec_ref,
+ ucontrol->value.integer.value[0]);
+
+ mutex_lock(&routing_lock);
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ msm_route_ext_ec_ref = MI2S_TX;
+ ret = voc_set_ext_ec_ref(msm_route_ext_ec_ref, true);
+ break;
+ default:
+ msm_route_ext_ec_ref = AFE_PORT_INVALID;
+ ret = voc_set_ext_ec_ref(msm_route_ext_ec_ref, false);
+ break;
+ }
+ snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+ mutex_unlock(&routing_lock);
+ return ret;
+}
+
+static const char * const ext_ec_ref_rx[] = {"NONE", "MI2S_TX"};
+
+static const struct soc_enum msm_route_ext_ec_ref_rx_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, ext_ec_ref_rx),
+};
+
+static const struct snd_kcontrol_new voc_ext_ec_mux =
+ SOC_DAPM_ENUM_EXT("VOC_EXT_EC MUX Mux", msm_route_ext_ec_ref_rx_enum[0],
+ msm_routing_ext_ec_get, msm_routing_ext_ec_put);
+
+
static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -2887,6 +2939,7 @@
/* Virtual Pins to force backends ON atm */
SND_SOC_DAPM_OUTPUT("BE_OUT"),
SND_SOC_DAPM_INPUT("BE_IN"),
+ SND_SOC_DAPM_MUX("VOC_EXT_EC MUX", SND_SOC_NOPM, 0, 0, &voc_ext_ec_mux),
};
@@ -3071,6 +3124,8 @@
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
{"HDMI", NULL, "HDMI_DL_HL"},
+ {"VOC_EXT_EC MUX", "MI2S_TX" , "MI2S_TX"},
+ {"CS-VOICE_UL1", NULL, "VOC_EXT_EC MUX"},
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "SEC_TX_Voice", "SEC_I2S_TX"},
{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 17f2d03..bb13695 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -73,6 +73,7 @@
static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv);
static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv);
static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv);
+static int voice_send_set_device_cmd_v2(struct voice_data *v);
static u16 voice_get_mvm_handle(struct voice_data *v)
{
@@ -1380,6 +1381,80 @@
return -EINVAL;
}
+static int voice_send_set_device_cmd_v2(struct voice_data *v)
+{
+ struct cvp_set_device_cmd_v2 cvp_setdev_cmd_v2;
+ int ret = 0;
+ void *apr_cvp;
+ u16 cvp_handle;
+
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+ apr_cvp = common.apr_q6_cvp;
+
+ if (!apr_cvp) {
+ pr_err("%s: apr_cvp is NULL.\n", __func__);
+ return -EINVAL;
+ }
+ cvp_handle = voice_get_cvp_handle(v);
+
+ /* set device and wait for response */
+ cvp_setdev_cmd_v2.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ cvp_setdev_cmd_v2.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(cvp_setdev_cmd_v2) - APR_HDR_SIZE);
+ cvp_setdev_cmd_v2.hdr.src_port = v->session_id;
+ cvp_setdev_cmd_v2.hdr.dest_port = cvp_handle;
+ cvp_setdev_cmd_v2.hdr.token = 0;
+ cvp_setdev_cmd_v2.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE_V2;
+
+ voc_get_tx_rx_topology(v,
+ &cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id,
+ &cvp_setdev_cmd_v2.cvp_set_device_v2.rx_topology_id);
+
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
+ if (common.ec_ref_ext == true) {
+ cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id =
+ common.ec_port_id;
+ } else {
+ cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id =
+ VSS_IVOCPROC_PORT_ID_NONE;
+ }
+ pr_debug("%s:topology=%d , tx_port_id=%d, rx_port_id=%d\n"
+ "ec_ref_port_id = %x\n", __func__,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id,
+ cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id);
+
+ v->cvp_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd_v2);
+ if (ret < 0) {
+ pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n");
+ goto fail;
+ }
+ pr_debug("wait for cvp create session event\n");
+ ret = wait_event_timeout(v->cvp_wait,
+ (v->cvp_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
static int voice_send_stop_voice_cmd(struct voice_data *v)
{
struct apr_hdr mvm_stop_voice_cmd;
@@ -2277,7 +2352,13 @@
pr_err("%s: wait_event timeout\n", __func__);
goto fail;
}
-
+ if (common.ec_ref_ext == true) {
+ ret = voice_send_set_device_cmd_v2(v);
+ if (ret < 0)
+ pr_err("%s: set device V2 failed rc =%x\n",
+ __func__, ret);
+ goto fail;
+ }
/* send cvs cal */
ret = voice_send_cvs_map_memory_cmd(v);
if (!ret)
@@ -3242,7 +3323,8 @@
voice_send_cvp_deregister_cal_cmd(v);
voice_get_cal_paddr_size(v, &paddr, NULL);
voice_send_cvp_unmap_memory_cmd(v, paddr);
-
+ if (common.ec_ref_ext == true)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
v->voc_state = VOC_CHANGE;
}
@@ -3268,10 +3350,19 @@
mutex_lock(&v->lock);
if (v->voc_state == VOC_CHANGE) {
- ret = voice_send_set_device_cmd(v);
- if (ret < 0) {
- pr_err("%s: set device failed\n", __func__);
- goto fail;
+ if (common.ec_ref_ext == true) {
+ ret = voice_send_set_device_cmd_v2(v);
+ if (ret < 0)
+ pr_err("%s: set device V2 failed\n"
+ "rc =%x\n", __func__, ret);
+ goto fail;
+ } else {
+ ret = voice_send_set_device_cmd(v);
+ if (ret < 0) {
+ pr_err("%s: set device failed rc=%x\n",
+ __func__, ret);
+ goto fail;
+ }
}
/* send cvp and vol cal */
if (!voice_get_cal_paddr_size(v, &cal_paddr, &cal_size) &&
@@ -3675,7 +3766,8 @@
if (ret < 0)
pr_err("%s: destroy voice failed\n", __func__);
voice_destroy_mvm_cvs_session(v);
-
+ if (common.ec_ref_ext == true)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
v->voc_state = VOC_RELEASE;
}
mutex_unlock(&v->lock);
@@ -3845,6 +3937,28 @@
return ret;
}
+int voc_set_ext_ec_ref(uint16_t port_id, bool state)
+{
+ int ret = 0;
+
+ mutex_lock(&common.common_lock);
+ if (state == true) {
+ if (port_id == AFE_PORT_INVALID) {
+ pr_err("%s: Invalid port id", __func__);
+ ret = -EINVAL;
+ goto fail;
+ }
+ common.ec_port_id = port_id;
+ common.ec_ref_ext = true;
+ } else {
+ common.ec_ref_ext = false;
+ common.ec_port_id = port_id;
+ }
+fail:
+ mutex_unlock(&common.common_lock);
+ return ret;
+}
+
void voc_register_mvs_cb(ul_cb_fn ul_cb,
dl_cb_fn dl_cb,
void *private_data)
@@ -4201,6 +4315,7 @@
v->cvp_state = CMD_STATUS_SUCCESS;
wake_up(&v->cvp_wait);
break;
+ case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
case VSS_IVOCPROC_CMD_SET_DEVICE:
case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX:
case VSS_IVOCPROC_CMD_ENABLE:
@@ -4517,6 +4632,7 @@
common.default_mute_val = 0; /* default is un-mute */
common.default_vol_val = 0;
common.default_sample_val = 8000;
+ common.ec_ref_ext = false;
/* Initialize MVS info. */
common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 0bae384..7463a5f 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -903,6 +903,8 @@
#define VSS_IVOCPROC_CMD_SET_DEVICE 0x000100C4
+#define VSS_IVOCPROC_CMD_SET_DEVICE_V2 0x000112C6
+
#define VSS_IVOCPROC_CMD_SET_VP3_DATA 0x000110EB
#define VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX 0x000110EE
@@ -958,6 +960,9 @@
#define VOICE_CMD_GET_PARAM 0x00011007
#define VOICE_EVT_GET_PARAM_ACK 0x00011008
+/* Default AFE port ID. Applicable to Tx and Rx. */
+#define VSS_IVOCPROC_PORT_ID_NONE 0xFFFF
+
struct vss_ivocproc_cmd_create_full_control_session_t {
uint16_t direction;
/*
@@ -1027,6 +1032,32 @@
*/
} __packed;
+/* Internal EC */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING 0x00010F7C
+
+/* External EC */
+#define VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING 0x00010F7D
+
+struct vss_ivocproc_cmd_set_device_v2_t {
+ uint16_t tx_port_id;
+ /* Tx device port ID to which the vocproc connects. */
+ uint32_t tx_topology_id;
+ /* Tx path topology ID. */
+ uint16_t rx_port_id;
+ /* Rx device port ID to which the vocproc connects. */
+ uint32_t rx_topology_id;
+ /* Rx path topology ID. */
+ uint32_t vocproc_mode;
+ /* Vocproc mode. The supported values:
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING - 0x00010F7C
+ * VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING - 0x00010F7D
+ */
+ uint16_t ec_ref_port_id;
+ /* Port ID to which the vocproc connects for receiving
+ * echo cancellation reference signal.
+ */
+} __packed;
+
struct vss_ivocproc_cmd_register_calibration_data_t {
uint32_t phys_addr;
/* Phsical address to be registered with vocproc. Calibration data
@@ -1076,6 +1107,11 @@
struct vss_ivocproc_cmd_set_device_t cvp_set_device;
} __packed;
+struct cvp_set_device_cmd_v2 {
+ struct apr_hdr hdr;
+ struct vss_ivocproc_cmd_set_device_v2_t cvp_set_device_v2;
+} __packed;
+
struct cvp_set_vp3_data_cmd {
struct apr_hdr hdr;
} __packed;
@@ -1227,6 +1263,8 @@
uint32_t default_mute_val;
uint32_t default_vol_val;
uint32_t default_sample_val;
+ bool ec_ref_ext;
+ uint16_t ec_port_id;
/* APR to MVM in the Q6 */
void *apr_q6_mvm;
@@ -1325,4 +1363,5 @@
int voc_start_playback(uint32_t set);
int voc_start_record(uint32_t port_id, uint32_t set);
+int voc_set_ext_ec_ref(uint16_t port_id, bool state);
#endif
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index c14cb74..ad96ae3 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -20,18 +20,58 @@
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include <linux/of_device.h>
+#include <linux/memory_alloc.h>
#include <asm/mach-types.h>
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#include <mach/ocmem.h>
+#include <mach/subsystem_notif.h>
+#include <mach/subsystem_restart.h>
+#include <mach/msm_memtypes.h>
+#include <mach/ramdump.h>
#include "q6core.h"
#include "audio_ocmem.h"
+
#define AUDIO_OCMEM_BUF_SIZE (512 * SZ_1K)
+/**
+ * Exercise OCMEM Dump if audio OCMEM state is
+ * one of the following. All other states indicate
+ * audio data is not mapped from DDR to OCMEM and
+ * therefore no need of dump.
+ */
+#define _DO_OCMEM_DUMP_BIT_MASK_\
+ ((1 << OCMEM_STATE_MAP_COMPL) |\
+ (1 << OCMEM_STATE_MAP_TRANSITION) |\
+ (1 << OCMEM_STATE_UNMAP_TRANSITION) |\
+ (1 << OCMEM_STATE_SHRINK) |\
+ (1 << OCMEM_STATE_GROW))
+
+/**
+ * Wait for OCMEM driver to process and respond for
+ * ongoing map/unmap request before calling OCMEM dump.
+ */
+#define _WAIT_BFR_DUMP_BIT_MASK_\
+ ((1 << OCMEM_STATE_MAP_COMPL) |\
+ (1 << OCMEM_STATE_UNMAP_COMPL) |\
+ (1 << OCMEM_STATE_MAP_FAIL) |\
+ (1 << OCMEM_STATE_UNMAP_FAIL))
+
+#define _MAP_RESPONSE_BIT_MASK_\
+ ((1 << OCMEM_STATE_MAP_COMPL) |\
+ (1 << OCMEM_STATE_MAP_FAIL))
+
+
+#define _UNMAP_RESPONSE_BIT_MASK_\
+ ((1 << OCMEM_STATE_UNMAP_COMPL) |\
+ (1 << OCMEM_STATE_UNMAP_FAIL))
+
#define _BIT_MASK_\
- ((1 << OCMEM_STATE_EXIT) |\
+ ((1 << OCMEM_STATE_SSR) |\
+ (1 << OCMEM_STATE_EXIT) |\
(1 << OCMEM_STATE_GROW) |\
(1 << OCMEM_STATE_SHRINK))
@@ -89,6 +129,10 @@
struct workqueue_struct *audio_ocmem_workqueue;
struct workqueue_struct *voice_ocmem_workqueue;
bool ocmem_en;
+ bool audio_ocmem_running;
+ void *ocmem_ramdump_dev;
+ struct ramdump_segment ocmem_ramdump_segment;
+ unsigned long ocmem_dump_addr;
};
static struct audio_ocmem_prv audio_ocmem_lcl;
@@ -114,7 +158,9 @@
break;
case OCMEM_MAP_FAIL:
pr_debug("%s: map fail\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_TRANSITION);
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
break;
case OCMEM_UNMAP_DONE:
pr_debug("%s: unmap done\n", __func__);
@@ -125,8 +171,10 @@
break;
case OCMEM_UNMAP_FAIL:
pr_debug("%s: unmap fail\n", __func__);
- atomic_set(&audio_ocmem_lcl.audio_state,
- OCMEM_STATE_UNMAP_FAIL);
+ clear_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_TRANSITION);
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_FAIL);
break;
case OCMEM_ALLOC_GROW:
rbuf = data;
@@ -170,6 +218,9 @@
} else if (test_bit_pos((*state), OCMEM_STATE_EXIT)) {
pr_debug("%s: returning exit state\n", __func__);
return OCMEM_STATE_EXIT;
+ } else if (test_bit_pos((*state), OCMEM_STATE_SSR)) {
+ pr_debug("%s: returning ssr state\n", __func__);
+ return OCMEM_STATE_SSR;
} else
return -EINVAL;
@@ -278,8 +329,8 @@
}
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- test_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_MAP_COMPL) != 0);
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _MAP_RESPONSE_BIT_MASK_) != 0);
atomic_set(&audio_ocmem_lcl.audio_cond, 1);
mutex_unlock(&audio_ocmem_lcl.protect_lock);
@@ -322,8 +373,9 @@
}
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- test_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_UNMAP_COMPL) != 0);
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _UNMAP_RESPONSE_BIT_MASK_)
+ != 0);
ret = ocmem_shrink(cid, audio_ocmem_lcl.buf, 0);
if (ret) {
pr_err("%s: ocmem_shrink failed, state[%d]\n",
@@ -353,8 +405,8 @@
goto fail_cmd;
}
wait_event_interruptible(audio_ocmem_lcl.audio_wait,
- test_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_MAP_COMPL) != 0);
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _MAP_RESPONSE_BIT_MASK_) != 0);
clear_bit_pos(audio_ocmem_lcl.audio_state,
OCMEM_STATE_GROW);
@@ -377,8 +429,8 @@
}
wait_event_interruptible(
audio_ocmem_lcl.audio_wait,
- test_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_UNMAP_COMPL) != 0);
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _UNMAP_RESPONSE_BIT_MASK_) != 0);
}
if (test_bit_pos(audio_ocmem_lcl.audio_state,
@@ -434,14 +486,15 @@
goto fail_cmd;
}
pr_debug("%s: ocmem_free success\n", __func__);
+ /* Fall through */
+ case OCMEM_STATE_SSR:
msm_bus_scale_client_update_request(
audio_ocmem_lcl.audio_ocmem_bus_client,
0);
set_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_DISABLE);
+ OCMEM_STATE_DISABLE);
break;
-
case -EINVAL:
pr_info("%s: audio_cond[%d] audio_state[0x%x]\n",
__func__,
@@ -453,6 +506,7 @@
ret = 0;
fail_cmd:
pr_debug("%s: exit\n", __func__);
+ audio_ocmem_lcl.audio_ocmem_running = false;
return ret;
}
@@ -470,8 +524,11 @@
pr_debug("%s: audio_cond[0x%x], audio_state[0x%x]\n", __func__,
atomic_read(&audio_ocmem_lcl.audio_cond),
atomic_read(&audio_ocmem_lcl.audio_state));
- set_bit_pos(audio_ocmem_lcl.audio_state,
- OCMEM_STATE_EXIT);
+ if (!test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_SSR))
+ set_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_EXIT);
+
wake_up(&audio_ocmem_lcl.audio_wait);
mutex_unlock(&audio_ocmem_lcl.protect_lock);
@@ -652,6 +709,7 @@
}
workdata->id = id;
workdata->en = enable;
+ audio_ocmem_lcl.audio_ocmem_running = true;
INIT_WORK(&workdata->work, audio_ocmem_process_workdata);
queue_work(audio_ocmem_lcl.audio_ocmem_workqueue,
@@ -684,12 +742,130 @@
return 0;
}
+
+static void do_ocmem_ramdump(void)
+{
+ int ret = 0;
+ void *virt = NULL;
+
+ virt = ioremap(audio_ocmem_lcl.ocmem_dump_addr, AUDIO_OCMEM_BUF_SIZE);
+ ret = ocmem_dump(OCMEM_LP_AUDIO,
+ audio_ocmem_lcl.buf,
+ (unsigned long)virt);
+ iounmap(virt);
+
+ if (ret)
+ pr_err("%s: ocmem_dump failed\n", __func__);
+
+ audio_ocmem_lcl.ocmem_ramdump_segment.address
+ = (unsigned long)audio_ocmem_lcl.ocmem_dump_addr;
+ audio_ocmem_lcl.ocmem_ramdump_segment.size
+ = AUDIO_OCMEM_BUF_SIZE;
+ ret = do_ramdump(audio_ocmem_lcl.ocmem_ramdump_dev,
+ &audio_ocmem_lcl.ocmem_ramdump_segment,
+ 1);
+ if (ret < 0)
+ pr_err("%s: do_ramdump failed\n", __func__);
+}
+
+static void process_ocmem_dump(void)
+{
+ int ret = 0;
+
+ set_bit_pos(audio_ocmem_lcl.audio_state, OCMEM_STATE_SSR);
+
+ if (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _DO_OCMEM_DUMP_BIT_MASK_) {
+
+ wait_event_interruptible(audio_ocmem_lcl.audio_wait,
+ (atomic_read(&audio_ocmem_lcl.audio_state) &
+ _WAIT_BFR_DUMP_BIT_MASK_) != 0);
+
+ if (test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_MAP_COMPL) ||
+ test_bit_pos(audio_ocmem_lcl.audio_state,
+ OCMEM_STATE_UNMAP_FAIL)) {
+
+ if (audio_ocmem_lcl.ocmem_dump_addr &&
+ audio_ocmem_lcl.ocmem_ramdump_dev)
+ do_ocmem_ramdump();
+ else
+ pr_err("%s: Error calling ocmem ramdump\n",
+ __func__);
+
+ ret = ocmem_drop(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf,
+ &audio_ocmem_lcl.mlist);
+ if (ret)
+ pr_err("%s: ocmem_drop failed\n", __func__);
+ }
+ }
+
+ ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
+ if (ret)
+ pr_err("%s: ocmem_free failed\n", __func__);
+}
+
+static int lpass_notifier_cb(struct notifier_block *this, unsigned long code,
+ void *_cmd)
+{
+ int ret = NOTIFY_DONE;
+
+ switch (code) {
+ case SUBSYS_BEFORE_SHUTDOWN:
+ pr_debug("AO-Notify: Shutdown started\n");
+ break;
+ case SUBSYS_AFTER_SHUTDOWN:
+ pr_debug("AO-Notify: Shutdown Completed\n");
+ break;
+ case SUBSYS_RAMDUMP_NOTIFICATION:
+ pr_debug("AO-Notify: OCMEM dump\n");
+ if (audio_ocmem_lcl.ocmem_en &&
+ audio_ocmem_lcl.audio_ocmem_running)
+ process_ocmem_dump();
+ pr_debug("AO-Notify: OCMEM dump done\n");
+ break;
+ case SUBSYS_BEFORE_POWERUP:
+ pr_debug("AO-Notify: Powerup started\n");
+ break;
+ case SUBSYS_AFTER_POWERUP:
+ pr_debug("AO-Notify: Powerup completed\n");
+ break;
+ default:
+ pr_err("AO-Notify: Generel: %lu\n", code);
+ break;
+ }
+ return ret;
+}
+
+static struct notifier_block anb = {
+ .notifier_call = lpass_notifier_cb,
+};
+
static int ocmem_audio_client_probe(struct platform_device *pdev)
{
int ret;
struct msm_bus_scale_pdata *audio_ocmem_bus_scale_pdata = NULL;
pr_debug("%s\n", __func__);
+
+ subsys_notif_register_notifier("adsp", &anb);
+
+ audio_ocmem_lcl.ocmem_dump_addr =
+ allocate_contiguous_memory_nomap(AUDIO_OCMEM_BUF_SIZE,
+ MEMTYPE_EBI1,
+ AUDIO_OCMEM_BUF_SIZE);
+
+ if (audio_ocmem_lcl.ocmem_dump_addr) {
+ audio_ocmem_lcl.ocmem_ramdump_dev =
+ create_ramdump_device("audio-ocmem", &pdev->dev);
+
+ if (!audio_ocmem_lcl.ocmem_ramdump_dev)
+ pr_err("%s: audio-ocmem ramdump device failed\n",
+ __func__);
+ } else {
+ pr_err("%s: ocmem dump memory alloc failed\n", __func__);
+ }
+
audio_ocmem_lcl.audio_ocmem_workqueue =
alloc_workqueue("ocmem_audio_client_driver_audio",
WQ_NON_REENTRANT | WQ_UNBOUND, 0);
@@ -715,6 +891,7 @@
spin_lock_init(&audio_ocmem_lcl.audio_lock);
mutex_init(&audio_ocmem_lcl.protect_lock);
audio_ocmem_lcl.ocmem_en = true;
+ audio_ocmem_lcl.audio_ocmem_running = false;
/* populate platform data */
ret = audio_ocmem_platform_data_populate(pdev);
@@ -753,6 +930,7 @@
msm_bus_cl_clear_pdata(audio_ocmem_bus_scale_pdata);
ocmem_notifier_unregister(audio_ocmem_lcl.audio_hdl,
&audio_ocmem_client_nb);
+ free_contiguous_memory_by_paddr(audio_ocmem_lcl.ocmem_dump_addr);
return 0;
}
static const struct of_device_id msm_ocmem_audio_dt_match[] = {
@@ -771,11 +949,9 @@
.remove = ocmem_audio_client_remove,
};
-
static int __init ocmem_audio_client_init(void)
{
int rc;
-
rc = platform_driver_register(&audio_ocmem_driver);
if (rc)
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 9d6896e..e79a0cf 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -56,6 +56,10 @@
#define TIMEOUT_MS 1000
#define Q6AFE_MAX_VOLUME 0x3FFF
+static int pcm_afe_instance[2];
+static int proxy_afe_instance[2];
+bool afe_close_done[2] = {true, true};
+
#define SIZEOF_CFG_CMD(y) \
(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
@@ -1061,11 +1065,30 @@
}
if ((port_id == RT_PROXY_DAI_001_RX) ||
- (port_id == RT_PROXY_DAI_002_TX))
- return 0;
- if ((port_id == RT_PROXY_DAI_002_RX) ||
- (port_id == RT_PROXY_DAI_001_TX))
+ (port_id == RT_PROXY_DAI_002_TX)) {
+ pr_debug("%s: before incrementing pcm_afe_instance %d"\
+ " port_id %d\n", __func__,
+ pcm_afe_instance[port_id & 0x1], port_id);
port_id = VIRTUAL_ID_TO_PORTID(port_id);
+ pcm_afe_instance[port_id & 0x1]++;
+ return 0;
+ }
+ if ((port_id == RT_PROXY_DAI_002_RX) ||
+ (port_id == RT_PROXY_DAI_001_TX)) {
+ pr_debug("%s: before incrementing proxy_afe_instance %d"\
+ " port_id %d\n", __func__,
+ proxy_afe_instance[port_id & 0x1], port_id);
+
+ if (!afe_close_done[port_id & 0x1]) {
+ /*close pcm dai corresponding to the proxy dai*/
+ afe_close(port_id - 0x10);
+ pcm_afe_instance[port_id & 0x1]++;
+ pr_debug("%s: reconfigure afe port again\n", __func__);
+ }
+ proxy_afe_instance[port_id & 0x1]++;
+ afe_close_done[port_id & 0x1] = false;
+ port_id = VIRTUAL_ID_TO_PORTID(port_id);
+ }
pr_debug("%s: port id: %#x\n", __func__, port_id);
@@ -2618,6 +2641,31 @@
goto fail_cmd;
}
pr_debug("%s: port_id=%d\n", __func__, port_id);
+ if ((port_id == RT_PROXY_DAI_001_RX) ||
+ (port_id == RT_PROXY_DAI_002_TX)) {
+ pr_debug("%s: before decrementing pcm_afe_instance %d\n",
+ __func__, pcm_afe_instance[port_id & 0x1]);
+ port_id = VIRTUAL_ID_TO_PORTID(port_id);
+ pcm_afe_instance[port_id & 0x1]--;
+ if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
+ proxy_afe_instance[port_id & 0x1] == 0))
+ return 0;
+ else
+ afe_close_done[port_id & 0x1] = true;
+ }
+
+ if ((port_id == RT_PROXY_DAI_002_RX) ||
+ (port_id == RT_PROXY_DAI_001_TX)) {
+ pr_debug("%s: before decrementing proxy_afe_instance %d\n",
+ __func__, proxy_afe_instance[port_id & 0x1]);
+ port_id = VIRTUAL_ID_TO_PORTID(port_id);
+ proxy_afe_instance[port_id & 0x1]--;
+ if (!(pcm_afe_instance[port_id & 0x1] == 0 &&
+ proxy_afe_instance[port_id & 0x1] == 0))
+ return 0;
+ else
+ afe_close_done[port_id & 0x1] = true;
+ }
port_id = q6audio_convert_virtual_to_portid(port_id);
index = q6audio_get_port_index(port_id);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2b824f..59d4de2 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -866,7 +866,6 @@
data->reset_proc,
this_mmap.apr);
apr_reset(this_mmap.apr);
- atomic_set(&this_mmap.ref_cnt, 0);
this_mmap.apr = NULL;
reset_custom_topology_flags();
set_custom_topology = 1;