Merge "ASoC: msm: qdsp6v2: Fix crash while unmap in NT mode encoders."
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 3a29004..203730f 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -47,6 +47,22 @@
3 (SUPER_TURBO voltage): 1275000 uV
- vdd-apc-supply: Regulator to supply VDD APC power
+
+Optional properties:
+- vdd-mx-supply: Regulator to supply memory power as dependency
+ of VDD APC.
+- qcom,vdd-mx-vmax: The maximum voltage in uV for vdd-mx-supply. This
+ is required when vdd-mx-supply is present.
+- qcom,vdd-mx-vmin-method: The method to determine the minimum voltage for
+ vdd-mx-supply, which can be one of following
+ choices compared with VDD APC:
+ 0 => equal to the voltage(vmin) of VDD APC
+ 1 => equal to PVS corner ceiling voltage
+ 2 => equal to slow speed corner ceiling
+ 3 => equal to qcom,vdd-mx-vmax
+ This is required when vdd-mx-supply is present.
+
+
Example:
apc_vreg_corner: regulator@f9018000 {
status = "okay";
@@ -65,5 +81,8 @@
qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
+ vdd-mx-supply = <&pm8226_l3_ao>;
+ qcom,vdd-mx-vmax = <1350000>;
+ qcom,vdd-mx-vmin-method = <1>;
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index b31ec30..d24139b 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -20,6 +20,7 @@
- synaptics,y-flip : modify orientation of the y axis
- synaptics,panel-x : panel x dimension
- synaptics,panel-y : panel y dimension
+ - synaptics,fw-image-name : name of firmware .img file in /etc/firmware
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index acd0ae3..383da0c 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -46,8 +46,8 @@
qcom,pil-self-auth;
/* GPIO inputs from mss */
- gpio_err_fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
/* GPIO output to mss */
- gpio_force_stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
diff --git a/Documentation/devicetree/bindings/power/qpnp-bms.txt b/Documentation/devicetree/bindings/power/qpnp-bms.txt
index 5b22752..e6c7290 100644
--- a/Documentation/devicetree/bindings/power/qpnp-bms.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-bms.txt
@@ -59,6 +59,14 @@
- qcom,batt-type: Type of battery used. This is an integer that corresponds
to the enum defined in
include/linux/mfd/pm8xxx/batterydata-lib.h
+- qcom,high-ocv-correction-limit-uv: how much the bms will correct OCV when
+ voltage is above the flat portion of the discharge
+ curve.
+- qcom,low-ocv-correction-limit-uv: how much the bms will correct OCV when
+ voltage is below the flat portion of the discharge
+ curve.
+- qcom,hold-soc-est: if the voltage-based estimated SoC is above this percent,
+ the BMS will clamp SoC to be at least 1.
Parent node optional properties:
- qcom,ignore-shutdown-soc: A boolean that controls whether BMS will
@@ -115,6 +123,9 @@
qcom,calculate-soc-ms = <20000>;
qcom,chg-term-ua = <100000>;
qcom,batt-type = <0>;
+ qcom,low-ocv-correction-limit-uv = <100>;
+ qcom,high-ocv-correction-limit-uv = <50>;
+ qcom,hold-soc-est = <3>;
qcom,bms-iadc@3800 {
reg = <0x3800 0x100>;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index a4c05d4..fe3d62f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -389,15 +389,25 @@
qcom,msm-cpudai-auxpcm-data = <0>, <0>;
qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
- qcom,msm-auxpcm-rx {
+ qcom,msm-prim-auxpcm-rx {
qcom,msm-auxpcm-dev-id = <4106>;
compatible = "qcom,msm-auxpcm-dev";
};
- qcom,msm-auxpcm-tx {
+ qcom,msm-prim-auxpcm-tx {
qcom,msm-auxpcm-dev-id = <4107>;
compatible = "qcom,msm-auxpcm-dev";
};
+
+ qcom,msm-sec-auxpcm-rx {
+ qcom,msm-auxpcm-dev-id = <4108>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
+
+ qcom,msm-sec-auxpcm-tx {
+ qcom,msm-auxpcm-dev-id = <4109>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
};
qcom,msm-pcm-hostless {
@@ -436,10 +446,14 @@
- taiko-mclk-clk : phandle to PMIC8941 clkdiv1 node.
- qcom,taiko-mclk-clk-freq : Taiko mclk Freq in Hz. currently only 9600000Hz
is supported.
-- prim-auxpcm-gpio-clk : GPIO on which AUXPCM clk signal is coming.
-- prim-auxpcm-gpio-sync : GPIO on which AUXPCM SYNC signal is coming.
-- prim-auxpcm-gpio-din : GPIO on which AUXPCM DIN signal is coming.
-- prim-auxpcm-gpio-dout : GPIO on which AUXPCM DOUT signal is coming.
+- qcom,prim-auxpcm-gpio-clk : GPIO on which Primary AUXPCM clk signal is coming.
+- qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
+- qcom,prim-auxpcm-gpio-din : GPIO on which Primary AUXPCM DIN signal is coming.
+- qcom,prim-auxpcm-gpio-dout : GPIO on which Primary AUXPCM DOUT signal is coming.
+- qcom,sec-auxpcm-gpio-clk : GPIO on which Secondary AUXPCM clk signal is coming.
+- qcom,sec-auxpcm-gpio-sync : GPIO on which Secondary AUXPCM SYNC signal is coming.
+- qcom,sec-auxpcm-gpio-din : GPIO on which Secondary AUXPCM DIN signal is coming.
+- qcom,sec-auxpcm-gpio-dout : GPIO on which Secondary AUXPCM DOUT signal is coming.
- qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
Optional properties:
@@ -487,10 +501,14 @@
qcom,hdmi-audio-rx;
- prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
- prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
- prim-auxpcm-gpio-din = <&msmgpio 67 0>;
- prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 67 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,sec-auxpcm-gpio-clk = <&msmgpio 79 0>;
+ qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+ qcom,sec-auxpcm-gpio-din = <&msmgpio 81 0>;
+ qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
};
* msm-dai-mi2s
@@ -608,7 +626,7 @@
* msm-adsp-loader
Required properties:
- - compatible : "msm-adsp-loader"
+ - compatible : "qcom,adsp-loader"
- qcom,adsp-state:
It is possible that some MSM use PIL to load the ADSP image. While
other MSM may use SBL to load the ADSP image at boot. Audio APR needs
@@ -623,3 +641,22 @@
compatible = "qcom,adsp-loader";
qcom,adsp-state = <2>;
};
+
+* msm-audio-ion
+
+Required properties:
+ - compatible : "qcom,msm-audio-ion"
+
+Optional properties:
+ - qcom,smmu-enabled:
+ It is possible that some MSM have SMMU in ADSP. While other MSM use
+ no SMMU. Audio lib introduce wrapper for ION APIs. The wrapper needs
+ presence of SMMU in ADSP to handle ION APIs differently.
+ Presence of this property means ADSP has SMMU in it.
+
+Example:
+
+qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion;
+ qcom,smmu-enabled;
+};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1fb2ba9..6ea9e62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -38,6 +38,9 @@
STROBE GPIO PAD.
- hsic,data-pad-offset : Offset of TLMM register for configuring HSIC
DATA GPIO PAD.
+- qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
+ SOFs. Software workarounds are required for the same.
+
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
below optional properties:
- qcom,msm_bus,name
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index d0886b0..c1d4a05 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -22,6 +22,10 @@
1 - PHY control
2 - PMIC control
3 - User control (via debugfs)
+- <supply-name>-supply: handle to the regulator device tree node
+ Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
+ "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
+ "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
Optional properties :
- qcom,hsusb-otg-disable-reset: If present then core is RESET only during
@@ -54,10 +58,8 @@
Used for allowing USB to respond for remote wakup.
- qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
after disconnect before entering low power mode.
-- <supply-name>-supply: handle to the regulator device tree node
- Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
- "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
- "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
+- <supply-name>-supply: handle to the regulator device tree node.
+ Optional "supply-name" is "vbus_otg" to supply vbus in host mode.
- qcom,vdd-voltage-level: This property must be a list of three integer
values (no, min, max) where each value represents either a voltage
in microvolts or a value corresponding to voltage corner.
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index 2825288..c52b7dd 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -23,7 +23,7 @@
qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
qcom,mdss-pan-underflow-clr = <0xff>;
qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 255>;
+ 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>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 72de900..60f8e7e 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -173,6 +173,9 @@
qcom,calculate-soc-ms = <20000>;
qcom,chg-term-ua = <100000>;
qcom,batt-type = <0>;
+ qcom,low-ocv-correction-limit-uv = <100>;
+ qcom,high-ocv-correction-limit-uv = <50>;
+ qcom,hold-soc-est = <3>;
qcom,bms-iadc@3800 {
reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 6042f23..9bab662 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -117,6 +117,9 @@
qcom,chg-term-ua = <100000>;
qcom,batt-type = <0>;
qcom,low-voltage-threshold = <3420000>;
+ qcom,low-ocv-correction-limit-uv = <100>;
+ qcom,high-ocv-correction-limit-uv = <50>;
+ qcom,hold-soc-est = <3>;
qcom,bms-iadc@3800 {
reg = <0x3800 0x100>;
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 52c591f..7b8dd59 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8226 CDP";
- compatible = "qcom,msm8226-cdp", "qcom,msm8226";
+ compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
qcom,msm-id = <145 1 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index af86922..02a0b0b 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -15,7 +15,7 @@
/ {
model = "Qualcomm MSM 8226 FLUID";
- compatible = "qcom,msm8226-fluid", "qcom,msm8226";
+ compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
qcom,msm-id = <145 3 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 68fa8ba..dab15ae 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8226 MTP";
- compatible = "qcom,msm8226-mtp", "qcom,msm8226";
+ compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
qcom,msm-id = <145 8 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 329439e..2613e11 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -368,6 +368,17 @@
qcom,use-sync-timer;
};
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
qcom,rpm-stats@0xfc19dbd0{
compatible = "qcom,rpm-stats";
reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index 618412a..4879691 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8226 QRD";
- compatible = "qcom,msm8226-qrd", "qcom,msm8226";
+ compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
qcom,msm-id = <145 11 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index f24cea1..70731d2 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -44,6 +44,9 @@
qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
vdd-apc-supply = <&pm8226_s2>;
+ vdd-mx-supply = <&pm8226_l3_ao>;
+ qcom,vdd-mx-vmax = <1350000>;
+ qcom,vdd-mx-vmin-method = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index b6590b3..a86dc48 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8226 Simulator";
- compatible = "qcom,msm8226-sim", "qcom,msm8226";
+ compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
qcom,msm-id = <145 16 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
new file mode 100644
index 0000000..50066f3
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -0,0 +1,978 @@
+/* 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.
+ */
+
+/ {
+ msm-mmss-noc@fc478000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc478000 0x00004000>;
+ cell-id = <2048>;
+ label = "msm_mmss_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-mdp-port0 {
+ cell-id = <22>;
+ label = "mas-mdp-port0";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,qport = <0>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <8>;
+ };
+
+ mas-vfe {
+ cell-id = <29>;
+ label = "mas-vfe";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <2>;
+ qcom,mas-hw-id = <11>;
+ };
+
+ mas-mdpe {
+ cell-id = <92>;
+ label = "mas-mdpe";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <7>;
+ qcom,mas-hw-id = <11>;
+ };
+
+ fab-bimc {
+ cell-id = <0>;
+ label = "fab-bimc";
+ qcom,gateway;
+ qcom,slavep = <16>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <16>;
+ };
+
+ slv-camera-cfg {
+ cell-id = <589>;
+ label = "slv-camera-cfg";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <3>;
+ };
+
+ slv-display-cfg {
+ cell-id = <590>;
+ label = "slv-display-cfg";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <4>;
+ };
+
+ slv-cpr-cfg {
+ cell-id = <592>;
+ label = "slv-cpr-cfg";
+ qcom,slavep = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <6>;
+ };
+
+ slv-cpr-xpu-cfg {
+ cell-id = <593>;
+ label = "slv-cpr-xpu-cfg";
+ qcom,slavep = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <7>;
+ };
+
+ slv-misc-cfg {
+ cell-id = <594>;
+ label = "slv-misc-cfg";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <8>;
+ };
+
+ slv-misc-xpu-cfg {
+ cell-id = <595>;
+ label = "slv-misc-xpu-cfg";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <9>;
+ };
+
+ slv-gfx3d-cfg {
+ cell-id = <598>;
+ label = "slv-gfx3d-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <11>;
+ };
+
+ slv-mmss-clk-cfg {
+ cell-id = <599>;
+ label = "slv-mmss-clk-cfg";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <12>;
+ };
+
+ slv-mmss-clk-xpu-cfg {
+ cell-id = <600>;
+ label = "slv-mmss-clk-xpu-cfg";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <13>;
+ };
+
+ slv-mnoc-mpu-cfg {
+ cell-id = <601>;
+ label = "slv-mnoc-mpu-cfg";
+ qcom,slavep = <13>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <14>;
+ };
+
+ slv-onoc-mpu-cfg {
+ cell-id = <602>;
+ label = "slv-onoc-mpu-cfg";
+ qcom,slavep = <14>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <15>;
+ };
+
+ slv-service-mnoc {
+ cell-id = <603>;
+ label = "slv-service-mnoc";
+ qcom,slavep = <18>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <17>;
+ };
+
+ slv-dsi-cfg {
+ cell-id = <649>;
+ label = "slv-dsi-cfg";
+ qcom,slavep = <19>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <19>;
+ };
+ };
+
+ msm-sys-noc@fc460000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc460000 0x00004000>;
+ cell-id = <1024>;
+ label = "msm_sys_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-lpass-ahb {
+ cell-id = <52>;
+ label = "mas-lpass-ahb";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <18>;
+ };
+
+ mas-qdss-bam {
+ cell-id = <53>;
+ label = "mas-qdss-bam";
+ qcom,masterp = <1>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <19>;
+ };
+
+ mas-snoc-cfg {
+ cell-id = <54>;
+ label = "mas-snoc-cfg";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <20>;
+ };
+
+ fab-bimc {
+ cell-id = <0>;
+ label= "fab-bimc";
+ qcom,gateway;
+ qcom,slavep = <7>;
+ qcom,masterp = <3>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <21>;
+ qcom,slv-hw-id = <24>;
+ };
+
+ fab-cnoc {
+ cell-id = <5120>;
+ label = "fab-cnoc";
+ qcom,gateway;
+ qcom,slavep = <8>;
+ qcom,masterp = <4>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <22>;
+ qcom,slv-hw-id = <25>;
+ };
+
+ fab-pnoc {
+ cell-id = <4096>;
+ label = "fab-pnoc";
+ qcom,gateway;
+ qcom,slavep = <10>;
+ qcom,masterp = <10>;
+ qcom,buswidth = <8>;
+ qcom,qport = <8>;
+ qcom,mas-hw-id = <29>;
+ qcom,slv-hw-id = <28>;
+ qcom,mode = "Fixed";
+ qcom,prio-rd = <2>;
+ qcom,prio-wr = <2>;
+ };
+
+ fab-ovnoc {
+ cell-id = <6144>;
+ label = "fab-ovnoc";
+ qcom,gateway;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <53>;
+ qcom,slv-hw-id = <77>;
+ };
+
+ mas-crypto-core0 {
+ cell-id = <55>;
+ label = "mas-crypto-core0";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <23>;
+ };
+
+ mas-mss {
+ cell-id = <38>;
+ label = "mas-mss";
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <26>;
+ };
+
+ mas-mss-nav {
+ cell-id = <57>;
+ label = "mas-mss-nav";
+ qcom,masterp = <8>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <27>;
+ };
+
+ mas-ocmem-dma {
+ cell-id = <58>;
+ label = "mas-ocmem-dma";
+ qcom,masterp = <9>;
+ qcom,tier = <2>;
+ qcom,mode = "Fixed";
+ qcom,qport = <7>;
+ qcom,mas-hw-id = <28>;
+ };
+
+ mas-wcss {
+ cell-id = <59>;
+ label = "mas-wcss";
+ qcom,masterp = <11>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <30>;
+ };
+
+ mas-qdss-etr {
+ cell-id = <60>;
+ label = "mas-qdss-etr";
+ qcom,masterp = <12>;
+ qcom,tier = <2>;
+ qcom,qport = <10>;
+ qcom,mode = "Fixed";
+ qcom,mas-hw-id = <31>;
+ };
+
+ slv-ocmem {
+ cell-id = <604>;
+ label = "slv-gmem";
+ qcom,slavep = <15>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <18>;
+ };
+
+ slv-ampss {
+ cell-id = <520>;
+ label = "slv-ampss";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <20>;
+ };
+
+ slv-lpass {
+ cell-id = <522>;
+ label = "slv-lpass";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <21>;
+ };
+
+ slv-wcss {
+ cell-id = <584>;
+ label = "slv-wcss";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <23>;
+ };
+
+ slv-ocimem {
+ cell-id = <585>;
+ label = "slv-ocimem";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <26>;
+ };
+
+ slv-service-snoc {
+ cell-id = <587>;
+ label = "slv-service-snoc";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <29>;
+ };
+
+ slv-qdss-stm {
+ cell-id = <588>;
+ label = "slv-qdss-stm";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <30>;
+ };
+
+ };
+
+ msm-periph-noc@fc468000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc468000 0x00004000>;
+ cell-id = <4096>;
+ label = "msm_periph_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-pnoc-cfg {
+ cell-id = <88>;
+ label = "mas-pnoc-cfg";
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <43>;
+ };
+
+ mas-sdcc-1 {
+ cell-id = <78>;
+ label = "mas-sdcc-1";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <33>;
+ };
+
+ mas-sdcc-2 {
+ cell-id = <81>;
+ label = "mas-sdcc-2";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <35>;
+ };
+
+ mas-blsp-1 {
+ cell-id = <86>;
+ label = "mas-blsp-1";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <41>;
+ };
+
+ mas-usb-hs {
+ cell-id = <87>;
+ label = "mas-usb-hs";
+ qcom,masterp = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <42>;
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <12>;
+ qcom,masterp = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <45>;
+ qcom,mas-hw-id = <44>;
+ };
+
+ slv-sdcc-1 {
+ cell-id = <606>;
+ label = "slv-sdcc-1";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <31>;
+ };
+
+ slv-sdcc-2 {
+ cell-id = <608>;
+ label = "slv-sdcc-2";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <33>;
+ };
+
+ slv-blsp-1 {
+ cell-id = <613>;
+ label = "slv-blsp-1";
+ qcom,slavep = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <39>;
+ };
+
+ slv-usb-hs {
+ cell-id = <614>;
+ label = "slv-usb-hs";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <40>;
+ };
+
+ slv-pdm {
+ cell-id = <615>;
+ label = "slv-pdm";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <41>;
+ };
+
+ slv-periph-apu-cfg {
+ cell-id = <616>;
+ label = "slv-periph-apu-cfg";
+ qcom,slavep = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <42>;
+ };
+
+ slv-pnoc-mpu-cfg {
+ cell-id = <617>;
+ label = "slv-pnoc-mpu-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <43>;
+ };
+
+ slv-prng {
+ cell-id = <618>;
+ label = "slv-prng";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <44>;
+ };
+
+ slv-service-pnoc {
+ cell-id = <619>;
+ label = "slv-service-pnoc";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <46>;
+ };
+
+ };
+
+ msm-config-noc@fc480000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc480000 0x00004000>;
+ cell-id = <5120>;
+ label = "msm_config_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-rpm-inst {
+ cell-id = <72>;
+ label = "mas-rpm-inst";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <45>;
+ };
+
+ mas-rpm-data {
+ cell-id = <73>;
+ label = "mas-rpm-data";
+ qcom,masterp = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <46>;
+ };
+
+ mas-rpm-sys {
+ cell-id = <74>;
+ label = "mas-rpm-sys";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <47>;
+ };
+
+ mas-dehr {
+ cell-id = <75>;
+ label = "mas-dehr";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <48>;
+ };
+
+ mas-qdss-dsp {
+ cell-id = <76>;
+ label = "mas-qdss-dap";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <49>;
+ };
+
+ mas-spdm {
+ cell-id = <36>;
+ label = "mas-spdm";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <50>;
+ };
+
+ mas-tic {
+ cell-id = <77>;
+ label = "mas-tic";
+ qcom,masterp = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <51>;
+ };
+
+ slv-clk-ctl {
+ cell-id = <620>;
+ label = "slv-clk-ctl";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <47>;
+ };
+
+ slv-cnoc-mss {
+ cell-id = <621>;
+ label = "slv-cnoc-mss";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <48>;
+ };
+
+ slv-security {
+ cell-id = <622>;
+ label = "slv-security";
+ qcom,slavep = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <49>;
+ };
+
+ slv-tcsr {
+ cell-id = <623>;
+ label = "slv-tcsr";
+ qcom,slavep = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <50>;
+ };
+
+ slv-tlmm {
+ cell-id = <624>;
+ label = "slv-tlmm";
+ qcom,slavep = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <51>;
+ };
+
+ slv-crypto-0-cfg {
+ cell-id = <625>;
+ label = "slv-crypto-0-cfg";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <52>;
+ };
+
+ slv-imem-cfg {
+ cell-id = <627>;
+ label = "slv-imem-cfg";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <54>;
+ };
+
+ slv-message-ram {
+ cell-id = <628>;
+ label = "slv-message-ram";
+ qcom,slavep = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <55>;
+ };
+
+ slv-bimc-cfg {
+ cell-id = <629>;
+ label = "slv-bimc-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <56>;
+ };
+
+ slv-boot-rom {
+ cell-id = <630>;
+ label = "slv-boot-rom";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <57>;
+ };
+
+ slv-pmic-arb {
+ cell-id = <632>;
+ label = "slv-pmic-arb";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <59>;
+ };
+
+ slv-spdm-wrapper {
+ cell-id = <633>;
+ label = "slv-spdm-wrapper";
+ qcom,slavep = <13>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <60>;
+ };
+
+ slv-dehr-cfg {
+ cell-id = <634>;
+ label = "slv-dehr-cfg";
+ qcom,slavep = <14>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <61>;
+ };
+
+ slv-mpm {
+ cell-id = <536>;
+ label = "slv-mpm";
+ qcom,slavep = <15>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <62>;
+ };
+
+ slv-qdss-cfg {
+ cell-id = <635>;
+ label = "slv-qdss-cfg";
+ qcom,slavep = <16>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <63>;
+ };
+
+ slv-rbcpr-cfg {
+ cell-id = <636>;
+ label = "slv-rbcpr-cfg";
+ qcom,slavep = <17>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <64>;
+ };
+
+ slv-rbcpr-qdss-apu-cfg {
+ cell-id = <637>;
+ label = "slv-rbcpr-qdss-apu-cfg";
+ qcom,slavep = <18>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <65>;
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <26>;
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <52>;
+ qcom,slv-hw-id = <75>;
+ };
+
+ slv-cnoc-mnoc-mmss-cfg {
+ cell-id = <631>;
+ label = "slv-cnoc-mnoc-mmss-cfg";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <58>;
+ };
+
+ slv-cnoc-mnoc-cfg {
+ cell-id = <640>;
+ label = "slv-cnoc-mnoc-cfg";
+ qcom,slavep = <19>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <66>;
+ };
+
+ slv-pnoc-cfg {
+ cell-id = <641>;
+ label = "slv-pnoc-cfg";
+ qcom,slavep = <21>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <69>;
+ };
+
+ slv-snoc-mpu-cfg {
+ cell-id = <638>;
+ label = "slv-snoc-mpu-cfg";
+ qcom,slavep = <20>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <67>;
+ };
+
+ slv-snoc-cfg {
+ cell-id = <642>;
+ label = "slv-snoc-cfg";
+ qcom,slavep = <22>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <70>;
+ };
+
+ slv-phy-apu-cfg {
+ cell-id = <644>;
+ label = "slv-phy-apu-cfg";
+ qcom,slavep = <23>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <72>;
+ };
+
+ slv-ebi1-phy-cfg {
+ cell-id = <645>;
+ label = "slv-ebi1-phy-cfg";
+ qcom,slavep = <24>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <73>;
+ };
+
+ slv-rpm {
+ cell-id = <534>;
+ label = "slv-rpm";
+ qcom,slavep = <25>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <74>;
+ };
+
+ slv-service-cnoc {
+ cell-id = <646>;
+ label = "slv-service-cnoc";
+ qcom,slavep = <27>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <76>;
+ };
+
+ };
+
+ msm-bimc@0xfc380000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc380000 0x0006A000>;
+ cell-id = <0>;
+ label = "msm_bimc";
+ qcom,fabclk-dual = "mem_clk";
+ qcom,fabclk-active = "mem_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "BIMC";
+ qcom,rpm-en;
+
+ mas-ampss-m0 {
+ cell-id = <1>;
+ label = "mas-ampss-m0";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "BIMC";
+ qcom,mode = "Fixed";
+ qcom,qport = <0>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <0>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ };
+
+ mas-mss-proc {
+ cell-id = <65>;
+ label = "mas-mss-proc";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "RPM";
+ qcom,mas-hw-id = <1>;
+ };
+
+ fab-mmss-noc {
+ cell-id = <2048>;
+ label = "fab_mmss_noc";
+ qcom,masterp = <1>;
+ qcom,qport = <1>;
+ qcom,buswidth = <8>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <2>;
+ qcom,hw-sel = "BIMC";
+ qcom,mode = "Bypass";
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <2>;
+ qcom,masterp = <2>;
+ qcom,qport = <2>;
+ qcom,buswidth = <8>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <3>;
+ qcom,slv-hw-id = <2>;
+ };
+
+ mas-lpass-proc {
+ cell-id = <11>;
+ label = "mas-lpass-proc";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,qport = <4>;
+ qcom,mas-hw-id = <25>;
+ qcom,mode = "Fixed";
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ };
+
+ mas-gfx3d {
+ cell-id = <26>;
+ label = "mas-gfx3d";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <5>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ qcom,mas-hw-id = <6>;
+ };
+
+
+ slv-ebi-ch0 {
+ cell-id = <512>;
+ label = "slv-ebi-ch0";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <0>;
+ };
+ };
+
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 390c02a..d523c67 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 CDP";
- compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
qcom,msm-id = <147 1 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 70ac0e8..f718d5e 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 MTP";
- compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
qcom,msm-id = <147 8 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index c3adb2c..08a3758 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -157,6 +157,8 @@
qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -165,22 +167,6 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = "retention";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
- qcom,latency-us = <75>;
- qcom,ss-power = <735>;
- qcom,energy-overhead = <77341>;
- qcom,time-overhead = <105>;
- };
-
-
- qcom,lpm-level@2 {
- reg = <0x2>;
qcom,mode = "standalone_pc";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
@@ -188,29 +174,33 @@
qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
- qcom,latency-us = <95>;
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <3000>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
- qcom,time-overhead = <130>;
+ qcom,time-overhead = <3130>;
};
- qcom,lpm-level@3 {
- reg = <0x3>;
+ qcom,lpm-level@2 {
+ reg = <0x2>;
qcom,mode = "pc";
qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_gdhs";
+ qcom,l2 = "l2_cache_retention";
qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
- qcom,latency-us = <2000>;
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <8000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <3200>;
+ qcom,time-overhead = <9200>;
};
- qcom,lpm-level@4 {
- reg = <0x4>;
+ qcom,lpm-level@3 {
+ reg = <0x3>;
qcom,mode = "pc";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_pc";
@@ -218,25 +208,42 @@
qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
- qcom,latency-us = <3000>;
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <9000>;
qcom,ss-power = <110>;
qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <3500>;
+ qcom,time-overhead = <9500>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = "pc";
+ qcom,xo = "xo_off";
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,latency-us = <16300>;
+ qcom,ss-power = <63>;
+ qcom,energy-overhead = <2128000>;
+ qcom,time-overhead = <24200>;
};
qcom,lpm-level@5 {
reg = <0x5>;
qcom,mode = "pc";
qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
- qcom,latency-us = <3000>;
- qcom,ss-power = <68>;
- qcom,energy-overhead = <1350200>;
- qcom,time-overhead = <4000>;
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
+ qcom,latency-us = <24000>;
+ qcom,ss-power = <10>;
+ qcom,energy-overhead = <3202600>;
+ qcom,time-overhead = <33000>;
};
qcom,lpm-level@6 {
@@ -244,44 +251,14 @@
qcom,mode = "pc";
qcom,xo = "xo_off";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
- qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
- qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
- qcom,latency-us = <10300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <18200>;
- };
-
- qcom,lpm-level@7 {
- reg = <0x7>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
- qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
- qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
- qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
- qcom,latency-us = <18000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <27000>;
- };
-
- qcom,lpm-level@8 {
- reg = <0x8>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
qcom,vdd-mem-upper-bound = <2>; /* SVS SOC */
qcom,vdd-mem-lower-bound = <0>; /* RETENTION */
qcom,vdd-dig-upper-bound = <2>; /* SVS SOC */
qcom,vdd-dig-lower-bound = <0>; /* RETENTION */
- qcom,latency-us = <20000>;
+ qcom,latency-us = <26000>;
qcom,ss-power = <2>;
qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <32000>;
+ qcom,time-overhead = <38000>;
};
};
@@ -393,6 +370,17 @@
qcom,use-sync-timer;
};
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
qcom,rpm-stats@0xfc19dbd0{
compatible = "qcom,rpm-stats";
reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index a4507e3..cab7560 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 Rumi";
- compatible = "qcom,msm8610-rumi", "qcom,msm8610";
+ compatible = "qcom,msm8610-rumi", "qcom,msm8610", "qcom,rumi";
qcom,msm-id = <147 15 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
index 2268daf..1838b94 100644
--- a/arch/arm/boot/dts/msm8610-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 Simulator";
- compatible = "qcom,msm8610-sim", "qcom,msm8610";
+ compatible = "qcom,msm8610-sim", "qcom,msm8610", "qcom,sim";
qcom,msm-id = <147 16 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 6469bf7..5967dfb 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -18,6 +18,7 @@
/include/ "msm8610-coresight.dtsi"
/include/ "msm8610-pm.dtsi"
/include/ "msm8610-smp2p.dtsi"
+/include/ "msm8610-bus.dtsi"
/ {
model = "Qualcomm MSM 8610";
@@ -488,6 +489,14 @@
qcom,tsens-local-init;
};
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <0>;
+ qcom,poll-ms = <250>;
+ qcom,limit-temp = <60>;
+ qcom,temp-hysteresis = <10>;
+ qcom,freq-step = <2>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 45bc4bb..4518fc4 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -4,7 +4,7 @@
/ {
model = "Qualcomm MSM8660 SURF";
- compatible = "qcom,msm8660-surf", "qcom,msm8660";
+ compatible = "qcom,msm8660-surf", "qcom,msm8660", "qcom,surf";
interrupt-parent = <&intc>;
intc: interrupt-controller@02080000 {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index a6a115c..df0db7e 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -20,6 +20,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e 0x0>;
@@ -61,6 +68,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs3>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c 0x0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index c9d1abc..f58c1e2 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -20,6 +20,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -62,6 +69,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs3>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index f9b89e1..5a97a11 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -21,6 +21,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -31,7 +38,7 @@
qcom,sensor-name = "s5k3l1yx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
cam_vaf-supply = <&pm8941_l23>;
qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
"cam_vaf";
@@ -58,6 +65,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <0>;
+ qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs2>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c>;
@@ -68,7 +113,7 @@
qcom,sensor-name = "ov2720";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
qcom,cam-vreg-type = <0 0 1>;
qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
@@ -103,7 +148,7 @@
qcom,sensor-name = "mt9m114";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
qcom,cam-vreg-type = <0 0 1>;
qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 3fb5b20..767a705 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -20,6 +20,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -65,11 +72,12 @@
qcom,camera@20 {
compatible = "qcom,imx135";
reg = <0x20>;
- qcom,slave-id = <0x20 0x0 0x1210>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index 046939e..ec8a459 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -354,6 +354,7 @@
&pm8941_chg {
status = "ok";
+ qcom,chg-charging-disabled;
qcom,chg-chgr@1000 {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 0090dfd..5970e6b 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -336,6 +336,7 @@
&pm8941_chg {
status = "ok";
+ qcom,chg-charging-disabled;
qcom,chg-chgr@1000 {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index 33bd1fb..cb58026 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 CDP";
- compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
qcom,msm-id = <126 1 0>;
};
@@ -25,3 +25,7 @@
status = "ok";
vbus-supply = <&usb2_otg_sw>;
};
+
+&hsic_host {
+ qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 9fb287c..0f762a8 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
qcom,msm-id = <126 3 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-liquid.dts b/arch/arm/boot/dts/msm8974-v1-liquid.dts
index 5c12569..ccbd82f 100644
--- a/arch/arm/boot/dts/msm8974-v1-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-liquid.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 LIQUID";
- compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
qcom,msm-id = <126 9 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 205ee24..6cb9f09 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
qcom,msm-id = <126 8 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-rumi.dts b/arch/arm/boot/dts/msm8974-v1-rumi.dts
index ebb37b7..caf89ee 100644
--- a/arch/arm/boot/dts/msm8974-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm8974-v1-rumi.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 RUMI";
- compatible = "qcom,msm8974-rumi", "qcom,msm8974";
+ compatible = "qcom,msm8974-rumi", "qcom,msm8974", "qcom,rumi";
qcom,msm-id = <126 15 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-sim.dts b/arch/arm/boot/dts/msm8974-v1-sim.dts
index 29add5d..c4b29c2 100644
--- a/arch/arm/boot/dts/msm8974-v1-sim.dts
+++ b/arch/arm/boot/dts/msm8974-v1-sim.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 Simulator";
- compatible = "qcom,msm8974-sim", "qcom,msm8974";
+ compatible = "qcom,msm8974-sim", "qcom,msm8974", "qcom,sim";
qcom,msm-id = <126 16 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index ae8cf83..62837a1 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -128,3 +128,7 @@
&ldrex_spinlock {
status = "ok";
};
+
+&usb_otg {
+ qcom,hsusb-otg-pnoc-errata-fix;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index d90abb5..4fa1f2a 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974v2 CDP";
- compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
qcom,msm-id = <126 1 0x20000>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index 0a09db1..c5779b1 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974v2 FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
qcom,msm-id = <126 3 0x20000>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index bbd5071..7132f43 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974v2 LIQUID";
- compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
qcom,msm-id = <126 9 0x20000>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index e74651e..d38e663 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974v2 MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
qcom,msm-id = <126 8 0x20000>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 61f2c4f..009b6df 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -67,6 +67,13 @@
qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
};
+&mdss_hdmi_tx {
+ reg = <0xfd922100 0x370>,
+ <0xfd922500 0x7C>,
+ <0xfc4b8000 0x60F0>;
+ reg-names = "core_physical", "phy_physical", "qfprom_physical";
+};
+
&msm_vidc {
qcom,vidc-ns-map = <0x40000000 0x40000000>;
qcom,load-freq-tbl = <979200 465000000>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 22c5d05..9a5a5d2 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -144,16 +144,16 @@
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0 0 140 0>;
interrupt-names = "core_irq", "async_irq";
- HSUSB_VDDCX-supply = <&pm8841_s2>;
+ HSUSB_VDDCX-supply = <&pm8841_s2_corner>;
HSUSB_1p8-supply = <&pm8941_l6>;
HSUSB_3p3-supply = <&pm8941_l24>;
+ qcom,vdd-voltage-level = <1 5 7>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-phy-init-seq = <0x63 0x81 0xffffffff>;
qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-disable-reset;
- qcom,hsusb-otg-pnoc-errata-fix;
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
@@ -629,10 +629,14 @@
qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
taiko-mclk-clk = <&pm8941_clkdiv1>;
qcom,taiko-mclk-clk-freq = <9600000>;
- prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
- prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
- prim-auxpcm-gpio-din = <&msmgpio 67 0>;
- prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 67 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,sec-auxpcm-gpio-clk = <&msmgpio 79 0>;
+ qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+ qcom,sec-auxpcm-gpio-din = <&msmgpio 81 0>;
+ qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
};
spmi_bus: qcom,spmi@fc4c0000 {
@@ -779,6 +783,10 @@
qcom,adsp-state = <0>;
};
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ };
+
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
qcom,msm-pcm-dsp-id = <0>;
@@ -955,15 +963,25 @@
qcom,msm-cpudai-auxpcm-data = <0>, <0>;
qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
- qcom,msm-auxpcm-rx {
+ qcom,msm-prim-auxpcm-rx {
qcom,msm-auxpcm-dev-id = <4106>;
compatible = "qcom,msm-auxpcm-dev";
};
- qcom,msm-auxpcm-tx {
+ qcom,msm-prim-auxpcm-tx {
qcom,msm-auxpcm-dev-id = <4107>;
compatible = "qcom,msm-auxpcm-dev";
};
+
+ qcom,msm-sec-auxpcm-rx {
+ qcom,msm-auxpcm-dev-id = <4108>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
+
+ qcom,msm-sec-auxpcm-tx {
+ qcom,msm-auxpcm-dev-id = <4109>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
};
qcom,msm-dai-mi2s {
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index cc7a758..cf17c69 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0>, <152 1 0>, <149 1 0>, <150 1 0>,
<151 1 0>, <148 1 0>, <173 1 0>, <174 1 0>,
<175 1 0>;
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index d78bb77..24aa3af 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0>, <152 7 0>, <149 7 0>, <150 7 0>,
<151 7 0>, <148 7 0>, <173 7 0>, <174 7 0>,
<175 7 0>;
@@ -97,11 +97,23 @@
};
mpp@a300 { /* MPP 4 */
+ /* VADC channel 19 */
+ qcom,mode = <4>;
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
mpp@a400 { /* MPP 5 */
};
mpp@a500 { /* MPP 6 */
+ /* VADC channel 21 */
+ qcom,mode = <4>;
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v1-rumi.dts b/arch/arm/boot/dts/msm9625-v1-rumi.dts
index a854947..ef00681 100644
--- a/arch/arm/boot/dts/msm9625-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm9625-v1-rumi.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 RUMI";
- compatible = "qcom,msm9625-rumi", "qcom,msm9625";
+ compatible = "qcom,msm9625-rumi", "qcom,msm9625", "qcom,rumi";
qcom,msm-id = <134 15 0>;
chosen{
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index 54aa02a..ad95601 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -57,3 +57,7 @@
&ldrex_spinlock {
status = "ok";
};
+
+&hsic_host {
+ qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
index 8702184..da07100 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2.1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
<150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
<173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
index 2dc040c..1e0f3c0 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2.1 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
<150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
<173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 94fe019..660bdbd 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -18,7 +18,7 @@
/ {
model = "Qualcomm MSM 9625V2 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0x20000>, <152 1 0x20000>, <149 1 0x20000>,
<150 1 0x20000>, <151 1 0x20000>, <148 1 0x20000>,
<173 1 0x20000>, <174 1 0x20000>, <175 1 0x20000>;
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 2840024..c9e54be 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0x20000>, <152 7 0x20000>, <149 7 0x20000>,
<150 7 0x20000>, <151 7 0x20000>, <148 7 0x20000>,
<173 7 0x20000>, <174 7 0x20000>, <175 7 0x20000>;
@@ -97,11 +97,23 @@
};
mpp@a300 { /* MPP 4 */
+ /* VADC channel 19 */
+ qcom,mode = <4>;
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
mpp@a400 { /* MPP 5 */
};
mpp@a500 { /* MPP 6 */
+ /* channel 21 */
+ qcom,mode = <4>;
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3dbc95d..fe81fa9 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -108,7 +108,7 @@
<87 512 40000 640000>;
};
- hsic@f9a15000 {
+ hsic_host: hsic@f9a15000 {
compatible = "qcom,hsic-host";
reg = <0xf9a15000 0x400>;
interrupts = <0 136 0>, <0 148 0>;
@@ -825,7 +825,7 @@
};
chan@33 {
- label = "pa_therm1";
+ label = "pa_therm0";
reg = <0x33>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -836,7 +836,7 @@
};
chan@34 {
- label = "pa_therm2";
+ label = "pa_therm1";
reg = <0x34>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -867,4 +867,26 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@13 {
+ label = "case_therm";
+ reg = <0x13>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@15 {
+ label = "ambient_therm";
+ reg = <0x15>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msmzinc-ion.dtsi b/arch/arm/boot/dts/msmzinc-ion.dtsi
index 4bf078a..aac4230 100644
--- a/arch/arm/boot/dts/msmzinc-ion.dtsi
+++ b/arch/arm/boot/dts/msmzinc-ion.dtsi
@@ -20,6 +20,10 @@
reg = <30>;
};
+ qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+ reg = <21>;
+ };
+
qcom,ion-heap@25 { /* IOMMU HEAP */
reg = <25>;
};
diff --git a/arch/arm/boot/dts/msmzinc-sim.dts b/arch/arm/boot/dts/msmzinc-sim.dts
index 48d7ef1..e410344 100644
--- a/arch/arm/boot/dts/msmzinc-sim.dts
+++ b/arch/arm/boot/dts/msmzinc-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM ZINC Simulator";
- compatible = "qcom,msmzinc-sim", "qcom,msmzinc";
+ compatible = "qcom,msmzinc-sim", "qcom,msmzinc", "qcom,sim";
qcom,msm-id = <178 0 0>;
aliases {
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index a429b3d..5e520f3 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -216,6 +216,7 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -231,6 +232,7 @@
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
CONFIG_SPMI=y
+CONFIG_MSM_BUS_SCALING=y
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP_INT=y
CONFIG_SLIMBUS_MSM_NGD=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index efca45a..f76f810 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -388,6 +388,7 @@
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index a226fe4..6112134 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -242,6 +242,7 @@
CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
+CONFIG_UID_STAT=y
CONFIG_TSPP=m
CONFIG_HAPTIC_ISA1200=y
CONFIG_QSEECOM=y
@@ -396,6 +397,7 @@
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index e8853b9..601fcfa 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -428,6 +428,8 @@
select MSM_SPM_REGULATOR
select MSM_JTAG_MM if CORESIGHT_ETM
select MSM_CPR_REGULATOR
+ select MSM_RPM_LOG
+ select MSM_RPM_STATS_LOG
config ARCH_MSM8226
bool "MSM8226"
@@ -466,6 +468,8 @@
select MSM_SPM_REGULATOR
select MSM_JTAG_MM if CORESIGHT_ETM
select MSM_CPR_REGULATOR
+ select MSM_RPM_LOG
+ select MSM_RPM_STATS_LOG
endmenu
choice
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 370be84..b673f93 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -260,241 +260,451 @@
static struct l2_level l2_freq_tbl_v2[] __initdata = {
[0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 950000, 0 },
[1] = { { 345600, HFPLL, 2, 36 }, LVL_LOW, 950000, 1 },
- [2] = { { 422400, HFPLL, 2, 44 }, LVL_LOW, 950000, 1 },
- [3] = { { 499200, HFPLL, 2, 52 }, LVL_LOW, 950000, 2 },
- [4] = { { 576000, HFPLL, 1, 30 }, LVL_LOW, 950000, 3 },
- [5] = { { 652800, HFPLL, 1, 34 }, LVL_NOM, 950000, 3 },
- [6] = { { 729600, HFPLL, 1, 38 }, LVL_NOM, 950000, 3 },
+ [2] = { { 422400, HFPLL, 2, 44 }, LVL_LOW, 950000, 2 },
+ [3] = { { 499200, HFPLL, 2, 52 }, LVL_LOW, 950000, 3 },
+ [4] = { { 576000, HFPLL, 1, 30 }, LVL_LOW, 950000, 4 },
+ [5] = { { 652800, HFPLL, 1, 34 }, LVL_NOM, 950000, 4 },
+ [6] = { { 729600, HFPLL, 1, 38 }, LVL_NOM, 950000, 4 },
[7] = { { 806400, HFPLL, 1, 42 }, LVL_NOM, 950000, 4 },
- [8] = { { 883200, HFPLL, 1, 46 }, LVL_NOM, 950000, 4 },
- [9] = { { 960000, HFPLL, 1, 50 }, LVL_NOM, 950000, 4 },
- [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 5 },
- [11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 5 },
+ [8] = { { 883200, HFPLL, 1, 46 }, LVL_NOM, 950000, 5 },
+ [9] = { { 960000, HFPLL, 1, 50 }, LVL_NOM, 950000, 5 },
+ [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 6 },
+ [11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 6 },
[12] = { { 1190400, HFPLL, 1, 62 }, LVL_HIGH, 1050000, 6 },
- [13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 6 },
+ [13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 7 },
[14] = { { 1344000, HFPLL, 1, 70 }, LVL_HIGH, 1050000, 7 },
[15] = { { 1420800, HFPLL, 1, 74 }, LVL_HIGH, 1050000, 7 },
[16] = { { 1497600, HFPLL, 1, 78 }, LVL_HIGH, 1050000, 7 },
- [17] = { { 1574400, HFPLL, 1, 82 }, LVL_HIGH, 1050000, 8 },
- [18] = { { 1651200, HFPLL, 1, 86 }, LVL_HIGH, 1050000, 8 },
+ [17] = { { 1574400, HFPLL, 1, 82 }, LVL_HIGH, 1050000, 7 },
+ [18] = { { 1651200, HFPLL, 1, 86 }, LVL_HIGH, 1050000, 7 },
[19] = { { 1728000, HFPLL, 1, 90 }, LVL_HIGH, 1050000, 8 },
{ }
};
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(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 835000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 845000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 855000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 865000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 875000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 890000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 900000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 915000, 3200000 },
+ { 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(12), 940000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 950000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 965000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 980000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 995000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 1010000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1025000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1040000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1055000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1070000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1085000, 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 },
{ 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(3), 810000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 820000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 830000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 840000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 850000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 860000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 875000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 885000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 895000, 3200000 },
+ { 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(12), 920000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 930000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 945000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 975000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1005000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1020000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1030000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1045000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1060000, 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 },
{ 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(3), 795000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 805000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 815000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 835000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 845000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 855000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 865000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 875000, 3200000 },
+ { 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(12), 900000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 910000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 925000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 940000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 955000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 980000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 995000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1005000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1020000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1035000, 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 },
{ 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(3), 780000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 790000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 810000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 820000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 830000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 840000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 850000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 3200000 },
+ { 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(12), 885000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 910000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 935000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 960000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 970000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 985000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 995000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1010000, 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 },
{ 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(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 780000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 790000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 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(12), 870000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 880000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 940000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 950000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 960000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 975000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 985000, 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 },
{ 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(3), 760000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 770000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 780000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 790000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 800000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 810000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 820000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 830000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 840000, 3200000 },
+ { 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(12), 860000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 870000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 880000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 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), 920000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 930000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 940000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 955000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 965000, 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 },
{ 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(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 760000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 770000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 780000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 790000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 800000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 810000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 820000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 830000, 3200000 },
+ { 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(12), 850000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 860000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 905000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 915000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 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 },
{ 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(3), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 805000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 815000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 835000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 845000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 855000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 865000, 3200000 },
+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 },
+ { 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(12), 890000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 900000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 940000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 965000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 980000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 995000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1010000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1025000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 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 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 75000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 75000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 75000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 75000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 75000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 76000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 77000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 78000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 79000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 80000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 81000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 82000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 83000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 84000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 85000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 86000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 87000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 87500, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 88500, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 89500, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 90500, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 91500, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 92000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 93000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 94000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 95000, 3200000 },
+ { 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 },
@@ -502,30 +712,30 @@
};
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(3), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 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(12), 875000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 885000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 945000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 960000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 975000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 990000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1005000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 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 },
@@ -533,30 +743,30 @@
};
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(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 785000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 795000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 805000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 815000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 3200000 },
+ { 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(12), 855000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 865000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 875000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 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), 955000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 970000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 980000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 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 },
@@ -564,30 +774,30 @@
};
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(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 780000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 790000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 800000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 810000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 820000, 3200000 },
+ { 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(12), 840000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 850000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 860000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 910000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 925000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 935000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 950000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 960000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 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 },
@@ -595,30 +805,30 @@
};
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(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 775000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 780000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 790000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 800000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 810000, 3200000 },
+ { 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(12), 830000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 840000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 850000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 860000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 870000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 895000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 910000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 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 },
@@ -626,30 +836,30 @@
};
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(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 760000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 770000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 780000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 790000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 800000, 3200000 },
+ { 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(12), 820000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 830000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 840000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 850000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 860000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 880000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 890000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 900000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 910000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 920000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 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 },
@@ -657,30 +867,30 @@
};
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(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 750000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 760000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 770000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 780000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 790000, 3200000 },
+ { 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(12), 810000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 820000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 830000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 840000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 850000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 870000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 875000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 885000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 895000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 905000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 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 },
@@ -716,6 +926,17 @@
[1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
[1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
[1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+
+ /* 8974v2 2.0GHz Parts */
+ [2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
+ [2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
+ [2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
+ [2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
+ [2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
+ [2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
+ [2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ [2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index cbb9e37..92be927 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -434,8 +434,7 @@
list_add_tail(&info->list_node, &bam_rx_pool);
rx_len_cached = ++bam_rx_pool_len;
ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
- BUFFER_SIZE, info,
- SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ BUFFER_SIZE, info, 0);
if (ret) {
list_del(&info->list_node);
rx_len_cached = --bam_rx_pool_len;
@@ -657,7 +656,7 @@
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
- pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ pkt, SPS_IOVEC_FLAG_EOT);
if (rc) {
DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
__func__, rc);
@@ -830,7 +829,7 @@
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
- pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ pkt, SPS_IOVEC_FLAG_EOT);
if (rc) {
DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
__func__, rc);
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index dd3f346..e2b62be 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -84,4 +84,5 @@
.pc_sf_lut = &desay_5200_pc_sf,
.default_rbatt_mohm = 156,
.rbatt_capacitive_mohm = 50,
+ .flat_ocv_threshold_uv = 3800000,
};
diff --git a/arch/arm/mach-msm/bms-batterydata-oem.c b/arch/arm/mach-msm/bms-batterydata-oem.c
index 036bf88..e4c42d7 100644
--- a/arch/arm/mach-msm/bms-batterydata-oem.c
+++ b/arch/arm/mach-msm/bms-batterydata-oem.c
@@ -105,4 +105,5 @@
.pc_temp_ocv_lut = &pc_temp_ocv,
.rbatt_sf_lut = &rbatt_sf,
.default_rbatt_mohm = 236,
+ .flat_ocv_threshold_uv = 3800000,
};
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 0c39df6..dc98c57 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -106,4 +106,5 @@
.rbatt_sf_lut = &rbatt_sf,
.default_rbatt_mohm = 236,
.rbatt_capacitive_mohm = 50,
+ .flat_ocv_threshold_uv = 3800000,
};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 42bde8f..e36884e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -675,6 +675,7 @@
static struct msm_hsic_host_platform_data msm_hsic_pdata = {
.strobe = 88,
.data = 89,
+ .phy_sof_workaround = true,
.bus_scale_table = &hsic_bus_scale_pdata,
};
#else
@@ -3804,6 +3805,8 @@
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
pr_err("meminfo_init() failed!\n");
+ msm_thermal_pdata.limit_temp_degC = 80;
+
apq8064_common_init();
ethernet_init();
fsm8064_ep_pcie_init();
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 872fabe..6371b9d 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -108,7 +108,7 @@
msm_spm_device_init();
rpm_regulator_smd_driver_init();
qpnp_regulator_init();
- if (machine_is_msm8226_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8226_rumi_clock_init_data);
else
msm_clock_init(&msm8226_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 5f5366f..9495b72 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -103,7 +103,7 @@
qpnp_regulator_init();
msm_thermal_device_init();
- if (machine_is_msm8610_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8610_rumi_clock_init_data);
else
msm_clock_init(&msm8610_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7ef6fed..f3d8a2f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1459,8 +1459,9 @@
#ifdef CONFIG_USB_EHCI_MSM_HSIC
#define HSIC_HUB_RESET_GPIO 91
static struct msm_hsic_host_platform_data msm_hsic_pdata = {
- .strobe = 150,
- .data = 151,
+ .strobe = 150,
+ .data = 151,
+ .phy_sof_workaround = true,
};
static struct smsc_hub_platform_data hsic_hub_pdata = {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 688c6f7..e30d0ba 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -100,6 +100,18 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting ath_gpio_active_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ath_gpio_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting gpio_i2c_config = {
.func = GPIOMUX_FUNC_3,
/*
@@ -718,14 +730,14 @@
},
};
-static struct gpiomux_setting pri_auxpcm_act_cfg = {
+static struct gpiomux_setting auxpcm_act_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting pri_auxpcm_sus_cfg = {
+static struct gpiomux_setting auxpcm_sus_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
@@ -735,29 +747,60 @@
{
.gpio = 65,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 66,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 67,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 68,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8974_sec_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 79,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 81,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 82,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
};
@@ -800,6 +843,24 @@
},
};
+
+static struct msm_gpiomux_config ath_gpio_configs[] = {
+ {
+ .gpio = 51,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &ath_gpio_active_cfg,
+ [GPIOMUX_SUSPENDED] = &ath_gpio_suspend_cfg,
+ },
+ },
+ {
+ .gpio = 79,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &ath_gpio_active_cfg,
+ [GPIOMUX_SUSPENDED] = &ath_gpio_suspend_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm_taiko_config[] __initdata = {
{
.gpio = 63, /* SYS_RST_N */
@@ -1003,7 +1064,8 @@
ARRAY_SIZE(msm_blsp2_uart7_configs));
msm_gpiomux_install(wcnss_5wire_interface,
ARRAY_SIZE(wcnss_5wire_interface));
-
+ msm_gpiomux_install_nowrite(ath_gpio_configs,
+ ARRAY_SIZE(ath_gpio_configs));
msm_gpiomux_install(msm8974_slimbus_config,
ARRAY_SIZE(msm8974_slimbus_config));
@@ -1024,17 +1086,19 @@
ARRAY_SIZE(msm_hsic_hub_configs));
msm_gpiomux_install(msm_hdmi_configs, ARRAY_SIZE(msm_hdmi_configs));
- if (machine_is_msm8974_fluid())
+ if (of_board_is_fluid())
msm_gpiomux_install(msm_mhl_configs,
ARRAY_SIZE(msm_mhl_configs));
msm_gpiomux_install(msm8974_pri_auxpcm_configs,
ARRAY_SIZE(msm8974_pri_auxpcm_configs));
+ msm_gpiomux_install(msm8974_sec_auxpcm_configs,
+ ARRAY_SIZE(msm8974_sec_auxpcm_configs));
msm_gpiomux_install_nowrite(msm_lcd_configs,
ARRAY_SIZE(msm_lcd_configs));
- if (machine_is_msm8974_rumi())
+ if (of_board_is_rumi())
msm_gpiomux_install(msm_rumi_blsp_configs,
ARRAY_SIZE(msm_rumi_blsp_configs));
}
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index e624e3f..9b69c8f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -97,7 +97,7 @@
rpm_regulator_smd_driver_init();
msm_spm_device_init();
krait_power_init();
- if (machine_is_msm8974_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8974_rumi_clock_init_data);
else
msm_clock_init(&msm8974_clock_init_data);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 50f4fd7..b77a3b9 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -841,6 +841,10 @@
.prv_data = &msm_hsic_peripheral_pdata_private,
};
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+ .phy_sof_workaround = true,
+};
+
#define PID_MAGIC_ID 0x71432909
#define SERIAL_NUM_MAGIC_ID 0x61945374
#define SERIAL_NUMBER_LENGTH 127
@@ -1073,6 +1077,7 @@
&msm_peripheral_pdata;
msm_device_hsic_peripheral.dev.platform_data =
&msm_hsic_peripheral_pdata;
+ msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm9615_pm8xxx_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index d63d722..768efe7 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2781,6 +2781,16 @@
CLK_LOOKUP("measure_clk", apc2_m_clk, ""),
CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
CLK_LOOKUP("measure_clk", l2_m_clk, ""),
+
+ 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("iface_clk", dsi_ahb_clk.c, "fdd00000.qcom,mdss_dsi"),
+ CLK_LOOKUP("core_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"),
};
static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index ecd25fc..9b34465 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -419,10 +419,21 @@
int clk_set_parent(struct clk *clk, struct clk *parent)
{
- if (!clk->ops->set_parent)
- return 0;
+ int rc = 0;
- return clk->ops->set_parent(clk, parent);
+ if (!clk->ops->set_parent)
+ return -ENOSYS;
+
+ mutex_lock(&clk->prepare_lock);
+ if (clk->parent == parent)
+ goto out;
+ rc = clk->ops->set_parent(clk, parent);
+ if (!rc)
+ clk->parent = parent;
+out:
+ mutex_unlock(&clk->prepare_lock);
+
+ return rc;
}
EXPORT_SYMBOL(clk_set_parent);
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 4e95e4e..08923e4 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -43,10 +43,16 @@
/* Process voltage variables */
u32 pvs_bin;
u32 pvs_process;
- u32 *process_vmax;
+ u32 *corner_ceiling;
/* APC voltage regulator */
struct regulator *vdd_apc;
+
+ /* Dependency parameters */
+ struct regulator *vdd_mx;
+ int vdd_mx_vmax;
+ int vdd_mx_vmin_method;
+ int vdd_mx_vmin;
};
static int cpr_regulator_is_enabled(struct regulator_dev *rdev)
@@ -59,11 +65,23 @@
static int cpr_regulator_enable(struct regulator_dev *rdev)
{
struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
- int rc;
+ int rc = 0;
+
+ /* Enable dependency power before vdd_apc */
+ if (cpr_vreg->vdd_mx) {
+ rc = regulator_enable(cpr_vreg->vdd_mx);
+ if (rc) {
+ pr_err("regulator_enable: vdd_mx: rc=%d\n", rc);
+ return rc;
+ }
+ }
rc = regulator_enable(cpr_vreg->vdd_apc);
if (!rc)
cpr_vreg->enabled = true;
+ else
+ pr_err("regulator_enable: vdd_apc: rc=%d\n", rc);
+
return rc;
}
@@ -73,8 +91,18 @@
int rc;
rc = regulator_disable(cpr_vreg->vdd_apc);
- if (!rc)
- cpr_vreg->enabled = false;
+ if (!rc) {
+ if (cpr_vreg->vdd_mx)
+ rc = regulator_disable(cpr_vreg->vdd_mx);
+
+ if (rc)
+ pr_err("regulator_disable: vdd_mx: rc=%d\n", rc);
+ else
+ cpr_vreg->enabled = false;
+ } else {
+ pr_err("regulator_disable: vdd_apc: rc=%d\n", rc);
+ }
+
return rc;
}
@@ -83,14 +111,84 @@
{
struct cpr_regulator *cpr_vreg = rdev_get_drvdata(rdev);
int rc;
- int vdd_apc_min, vdd_apc_max;
+ int vdd_apc_min, vdd_apc_max, vdd_mx_vmin = 0;
+ int change_dir = 0;
- vdd_apc_min = cpr_vreg->process_vmax[min_uV];
- vdd_apc_max = cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO];
+ if (cpr_vreg->vdd_mx) {
+ if (min_uV > cpr_vreg->corner)
+ change_dir = 1;
+ else if (min_uV < cpr_vreg->corner)
+ change_dir = -1;
+ }
+
+ vdd_apc_min = cpr_vreg->corner_ceiling[min_uV];
+ vdd_apc_max = cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO];
+
+ if (change_dir) {
+ /* Determine the vdd_mx voltage */
+ switch (cpr_vreg->vdd_mx_vmin_method) {
+ case VDD_MX_VMIN_APC:
+ vdd_mx_vmin = vdd_apc_min;
+ break;
+ case VDD_MX_VMIN_APC_CORNER_CEILING:
+ vdd_mx_vmin = vdd_apc_min;
+ break;
+ case VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
+ vdd_mx_vmin = cpr_vreg->pvs_corner_ceiling
+ [APC_PVS_SLOW][min_uV];
+ break;
+ case VDD_MX_VMIN_MX_VMAX:
+ default:
+ vdd_mx_vmin = cpr_vreg->vdd_mx_vmax;
+ break;
+ }
+ }
+
+ if (change_dir > 0) {
+ if (vdd_mx_vmin < cpr_vreg->vdd_mx_vmin) {
+ /* Check and report the value in case */
+ pr_err("Up: but new %d < old %d uV\n", vdd_mx_vmin,
+ cpr_vreg->vdd_mx_vmin);
+ }
+
+ rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
+ cpr_vreg->vdd_mx_vmax);
+ if (!rc) {
+ cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
+ } else {
+ pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
+ min_uV, vdd_mx_vmin, rc);
+ return rc;
+ }
+ }
+
rc = regulator_set_voltage(cpr_vreg->vdd_apc,
vdd_apc_min, vdd_apc_max);
- if (!rc)
+ if (!rc) {
cpr_vreg->corner = min_uV;
+ } else {
+ pr_err("set: vdd_apc [%d] = %d uV: rc=%d\n",
+ min_uV, vdd_apc_min, rc);
+ return rc;
+ }
+
+ if (change_dir < 0) {
+ if (vdd_mx_vmin > cpr_vreg->vdd_mx_vmin) {
+ /* Check and report the value in case */
+ pr_err("Down: but new %d >= old %d uV\n", vdd_mx_vmin,
+ cpr_vreg->vdd_mx_vmin);
+ }
+
+ rc = regulator_set_voltage(cpr_vreg->vdd_mx, vdd_mx_vmin,
+ cpr_vreg->vdd_mx_vmax);
+ if (!rc) {
+ cpr_vreg->vdd_mx_vmin = vdd_mx_vmin;
+ } else {
+ pr_err("set: vdd_mx [%d] = %d uV: rc=%d\n",
+ min_uV, vdd_mx_vmin, rc);
+ return rc;
+ }
+ }
pr_debug("set [corner:%d] = %d uV: rc=%d\n", min_uV, vdd_apc_min, rc);
return rc;
@@ -146,7 +244,7 @@
= cpr_vreg->pvs_corner_ceiling[APC_PVS_SLOW]
[CPR_CORNER_SUPER_TURBO];
- cpr_vreg->process_vmax =
+ cpr_vreg->corner_ceiling =
cpr_vreg->pvs_corner_ceiling[cpr_vreg->pvs_process];
iounmap(efuse_base);
@@ -162,19 +260,62 @@
static int __init cpr_regulator_apc_init(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
+ struct device_node *of_node = pdev->dev.of_node;
+ int rc;
+
cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev, "vdd-apc");
if (IS_ERR_OR_NULL(cpr_vreg->vdd_apc)) {
- pr_err("devm_regulator_get: rc=%d\n",
- (int)PTR_ERR(cpr_vreg->vdd_apc));
+ rc = PTR_RET(cpr_vreg->vdd_apc);
+ if (rc != -EPROBE_DEFER)
+ pr_err("devm_regulator_get: rc=%d\n", rc);
+ return rc;
}
- return PTR_RET(cpr_vreg->vdd_apc);
+ /* Check dependencies */
+ if (of_property_read_bool(of_node, "vdd-mx-supply")) {
+ cpr_vreg->vdd_mx = devm_regulator_get(&pdev->dev, "vdd-mx");
+ if (IS_ERR_OR_NULL(cpr_vreg->vdd_mx)) {
+ rc = PTR_RET(cpr_vreg->vdd_mx);
+ if (rc != -EPROBE_DEFER)
+ pr_err("devm_regulator_get: vdd-mx: rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ /* Parse dependency parameters */
+ if (cpr_vreg->vdd_mx) {
+ rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmax",
+ &cpr_vreg->vdd_mx_vmax);
+ if (rc < 0) {
+ pr_err("vdd-mx-vmax missing: rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmin-method",
+ &cpr_vreg->vdd_mx_vmin_method);
+ if (rc < 0) {
+ pr_err("vdd-mx-vmin-method missing: rc=%d\n", rc);
+ return rc;
+ }
+ if (cpr_vreg->vdd_mx_vmin_method > VDD_MX_VMIN_MX_VMAX) {
+ pr_err("Invalid vdd-mx-vmin-method(%d)\n",
+ cpr_vreg->vdd_mx_vmin_method);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
}
static void cpr_regulator_apc_exit(struct cpr_regulator *cpr_vreg)
{
- if (cpr_vreg->enabled)
+ if (cpr_vreg->enabled) {
regulator_disable(cpr_vreg->vdd_apc);
+
+ if (cpr_vreg->vdd_mx)
+ regulator_disable(cpr_vreg->vdd_mx);
+ }
}
static int __init cpr_regulator_parse_dt(struct platform_device *pdev,
@@ -323,10 +464,10 @@
platform_set_drvdata(pdev, cpr_vreg);
pr_info("PVS [%d %d %d %d] uV\n",
- cpr_vreg->process_vmax[CPR_CORNER_SVS],
- cpr_vreg->process_vmax[CPR_CORNER_NORMAL],
- cpr_vreg->process_vmax[CPR_CORNER_TURBO],
- cpr_vreg->process_vmax[CPR_CORNER_SUPER_TURBO]);
+ cpr_vreg->corner_ceiling[CPR_CORNER_SVS],
+ cpr_vreg->corner_ceiling[CPR_CORNER_NORMAL],
+ cpr_vreg->corner_ceiling[CPR_CORNER_TURBO],
+ cpr_vreg->corner_ceiling[CPR_CORNER_SUPER_TURBO]);
return 0;
}
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index 049cf02..ebc43da 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -112,6 +112,8 @@
#endif
#if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING)
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node);
struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
#else
@@ -121,6 +123,12 @@
return NULL;
}
+static inline struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node)
+{
+ return NULL;
+}
+
static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
{
}
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
index ea345fb..91e4ef1 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
@@ -53,10 +53,19 @@
uint8_t model_ID[128];
};
+#define ADSP_CMD_SET_DOLBY_MANUFACTURER_ID 0x00012918
+
+struct adsp_dolby_manufacturer_id {
+ struct apr_hdr hdr;
+ int manufacturer_id;
+};
+
int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps);
uint32_t core_get_adsp_version(void);
uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id);
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id);
+
#endif /* __Q6CORE_H__ */
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index ea02425..20dc851 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -16,6 +16,8 @@
#include <linux/qseecom.h>
+#define QSEECOM_KEY_ID_SIZE 32
+
enum qseecom_command_scm_resp_type {
QSEOS_APP_ID = 0xEE01,
QSEOS_LISTENER_ID
@@ -141,5 +143,45 @@
unsigned int rsp_len; /* in/out */
};
+/* Key Management requests */
+enum qseecom_qceos_key_gen_cmd_id {
+ QSEOS_GENERATE_KEY = 0x02,
+ QSEOS_SET_KEY,
+ QSEOS_DELETE_KEY,
+ QSEOS_MAX_KEY_COUNT,
+ QSEOS_KEY_CMD_MAX = 0xEFFFFFFF
+};
+
+__packed struct qseecom_key_generate_ireq {
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_select_ireq {
+ uint32_t ce;
+ uint32_t pipe;
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+ unsigned char hash[QSEECOM_HASH_SIZE];
+};
+
+__packed struct qseecom_key_delete_ireq {
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_max_count_query_ireq {
+ uint32_t flags;
+};
+
+__packed struct qseecom_key_max_count_query_irsp {
+ uint32_t max_key_count;
+};
+
+struct key_id_info {
+ uint32_t ce_hw;
+ uint32_t pipe;
+ bool flags;
+};
#endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 0cc7bbf..4258dbd 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -22,6 +22,7 @@
#define SCM_SVC_FUSE 0x8
#define SCM_SVC_PWR 0x9
#define SCM_SVC_MP 0xC
+#define SCM_SVC_CRYPTO 0xA
#define SCM_SVC_DCVS 0xD
#define SCM_SVC_TZSCHEDULER 0xFC
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 45f2646..b898fe8 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,77 +32,36 @@
#define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
#ifdef CONFIG_OF
-#define early_machine_is_msm8974() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8974")
-#define machine_is_msm8974() \
- of_machine_is_compatible("qcom,msm8974")
-#define machine_is_msm8974_sim() \
- of_machine_is_compatible("qcom,msm8974-sim")
-#define machine_is_msm8974_rumi() \
- of_machine_is_compatible("qcom,msm8974-rumi")
-#define machine_is_msm8974_fluid() \
- of_machine_is_compatible("qcom,msm8974-fluid")
-#define early_machine_is_msm9625() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm9625")
-#define machine_is_msm9625() \
- of_machine_is_compatible("qcom,msm9625")
-#define early_machine_is_mpq8092() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
-#define machine_is_mpq8092_sim() \
- of_machine_is_compatible("qcom,mpq8092-sim")
-#define early_machine_is_msm8226() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8226")
-#define machine_is_msm8226() \
- of_machine_is_compatible("qcom,msm8226")
-#define machine_is_msm8226_sim() \
- of_machine_is_compatible("qcom,msm8226-sim")
-#define machine_is_msm8226_rumi() \
- of_machine_is_compatible("qcom,msm8226-rumi")
-#define machine_is_msm8226_cdp() \
- of_machine_is_compatible("qcom,msm8226-cdp")
-#define machine_is_msm8226_fluid() \
- of_machine_is_compatible("qcom,msm8226-fluid")
-#define machine_is_msm8226_mtp() \
- of_machine_is_compatible("qcom,msm8226-mtp")
-#define machine_is_msm8226_qrd() \
- of_machine_is_compatible("qcom,msm8226-qrd")
+#define of_board_is_sim() of_machine_is_compatible("qcom,sim")
+#define of_board_is_rumi() of_machine_is_compatible("qcom,rumi")
+#define of_board_is_fluid() of_machine_is_compatible("qcom,fluid")
+#define of_board_is_liquid() of_machine_is_compatible("qcom,liquid")
+
+#define machine_is_msm8974() of_machine_is_compatible("qcom,msm8974")
+#define machine_is_msm9625() of_machine_is_compatible("qcom,msm9625")
+#define machine_is_msm8610() of_machine_is_compatible("qcom,msm8610")
+#define machine_is_msm8226() of_machine_is_compatible("qcom,msm8226")
+
#define early_machine_is_msm8610() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
-#define machine_is_msm8610() \
- of_machine_is_compatible("qcom,msm8610")
-#define machine_is_msm8610_sim() \
- of_machine_is_compatible("qcom,msm8610-sim")
-#define machine_is_msm8610_rumi() \
- of_machine_is_compatible("qcom,msm8610-rumi")
-#define machine_is_msm8610_mtp() \
- of_machine_is_compatible("qcom,msm8610-mtp")
-#define machine_is_msm8610_cdp() \
- of_machine_is_compatible("qcom,msm8610-cdp")
+#define early_machine_is_mpq8092() \
+ 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 machine_is_msmzinc_sim() \
- of_machine_is_compatible("qcom,msmzinc-sim")
#else
-#define early_machine_is_msm8974() 0
-#define machine_is_msm8974() 0
-#define machine_is_msm8974_sim() 0
-#define machine_is_msm8974_rumi() 0
-#define machine_is_msm8974_fluid() 0
-#define early_machine_is_msm9625() 0
-#define machine_is_msm9625() 0
-#define early_machine_is_mpq8092() 0
-#define machine_is_mpq8092_sim() 0
-#define early_machine_is_msm8226() 0
-#define machine_is_msm8226() 0
-#define machine_is_msm8226_sim() 0
-#define machine_is_msm8226_rumi() 0
-#define early_machine_is_msm8610() 0
-#define machine_is_msm8610() 0
-#define machine_is_msm8610_sim() 0
-#define machine_is_msm8610_rumi() 0
-#define early_machine_is_msmzinc() 0
-#define machine_is_msmzinc_sim() 0
+#define of_board_is_sim() 0
+#define of_board_is_rumi() 0
+#define of_board_is_fluid() 0
+#define of_board_is_liquid() 0
+#define machine_is_msm8974() 0
+#define machine_is_msm9625() 0
+#define machine_is_msm8610() 0
+#define machine_is_msm8226() 0
+
+#define early_machine_is_msm8610() 0
+#define early_machine_is_mpq8092() 0
+#define early_machine_is_msmzinc() 0
#endif
#define PLATFORM_SUBTYPE_SGLTE 6
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index c20576a..662655b 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -146,6 +146,8 @@
SPS_O_WRITE_NWD = 0x00040000,
/* Options to enable software features */
+ /* Do not disable a pipe during disconnection */
+ SPS_O_NO_DISABLE = 0x00800000,
/* Transfer operation should be polled */
SPS_O_POLL = 0x01000000,
/* Disable queuing of transfer events for the connection end point */
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index f40bd5d..c0422a1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -194,7 +194,7 @@
static int msm_ipc_router_extract_msg(struct msghdr *m,
struct sk_buff_head *msg_head)
{
- struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)m->msg_name;
+ struct sockaddr_msm_ipc *addr;
struct rr_header *hdr;
struct sk_buff *temp;
int offset = 0, data_len = 0, copy_len;
@@ -203,10 +203,11 @@
pr_err("%s: Invalid pointers passed\n", __func__);
return -EINVAL;
}
+ addr = (struct sockaddr_msm_ipc *)m->msg_name;
temp = skb_peek(msg_head);
hdr = (struct rr_header *)(temp->data);
- if (addr || (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
+ if (addr && (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
addr->address.addr.port_addr.node_id = hdr->src_node_id;
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 489eb5c..b9a553a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -42,20 +42,9 @@
return -EINVAL;
}
-/**
- * msm_bus_cl_get_pdata() - Generate bus client data from device tree
- * provided by clients.
- *
- * of_node: Device tree node to extract information from
- *
- * The function returns a valid pointer to the allocated bus-scale-pdata
- * if the vectors were correctly read from the client's device node.
- * Any error in reading or parsing the device node will return NULL
- * to the caller.
- */
-struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev,
+ struct device_node *of_node)
{
- struct device_node *of_node;
struct msm_bus_scale_pdata *pdata = NULL;
struct msm_bus_paths *usecase = NULL;
int i = 0, j, ret, num_usecases = 0, num_paths, len;
@@ -67,7 +56,6 @@
return NULL;
}
- of_node = pdev->dev.of_node;
pdata = devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_scale_pdata),
GFP_KERNEL);
if (!pdata) {
@@ -154,9 +142,81 @@
return NULL;
}
+
+/**
+ * msm_bus_cl_get_pdata() - Generate bus client data from device tree
+ * provided by clients.
+ *
+ * of_node: Device tree node to extract information from
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+{
+ struct device_node *of_node;
+ struct msm_bus_scale_pdata *pdata = NULL;
+
+ if (!pdev) {
+ pr_err("Error: Null Platform device\n");
+ return NULL;
+ }
+
+ of_node = pdev->dev.of_node;
+ pdata = get_pdata(pdev, of_node);
+ if (!pdata) {
+ pr_err("Error getting bus pdata!\n");
+ return NULL;
+ }
+
+ return pdata;
+}
EXPORT_SYMBOL(msm_bus_cl_get_pdata);
/**
+ * msm_bus_cl_pdata_from_node() - Generate bus client data from device tree
+ * node provided by clients. This function should be used when a client
+ * driver needs to register multiple bus-clients from a single device-tree
+ * node associated with the platform-device.
+ *
+ * of_node: The subnode containing information about the bus scaling
+ * data
+ *
+ * pdev: Platform device associated with the device-tree node
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node)
+{
+ struct msm_bus_scale_pdata *pdata = NULL;
+
+ if (!pdev) {
+ pr_err("Error: Null Platform device\n");
+ return NULL;
+ }
+
+ if (!of_node) {
+ pr_err("Error: Null of_node passed to bus driver\n");
+ return NULL;
+ }
+
+ pdata = get_pdata(pdev, of_node);
+ if (!pdata) {
+ pr_err("Error getting bus pdata!\n");
+ return NULL;
+ }
+
+ return pdata;
+}
+EXPORT_SYMBOL(msm_bus_pdata_from_node);
+
+/**
* msm_bus_cl_clear_pdata() - Clear pdata allocated from device-tree
* of_node: Device tree node to extract information from
*/
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index bc40130..f4ca4e3 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -282,10 +282,9 @@
pr_debug("Starting secondary CPU %d\n", cpu);
if (per_cpu(cold_boot_done, cpu) == false) {
- if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
+ if (of_board_is_sim())
release_secondary_sim(0xf9088000, cpu);
- else if (!machine_is_msm8974_rumi() &&
- !machine_is_msmzinc_sim())
+ else if (!of_board_is_rumi())
msm8974_release_secondary(0xf9088000, cpu);
per_cpu(cold_boot_done, cpu) = true;
@@ -298,9 +297,9 @@
pr_debug("Starting secondary CPU %d\n", cpu);
if (per_cpu(cold_boot_done, cpu) == false) {
- if (machine_is_msm8226_sim() || machine_is_msm8610_sim())
+ if (of_board_is_sim())
release_secondary_sim(0xf9088000, cpu);
- else if (!machine_is_msm8610_rumi())
+ else if (!of_board_is_rumi())
arm_release_secondary(0xf9088000, cpu);
per_cpu(cold_boot_done, cpu) = true;
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 88de98b..88e2894 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -23,7 +23,7 @@
obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o msm_audio_ion.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index e6b9549..5d744a1 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -24,6 +24,7 @@
#include <linux/atomic.h>
#include <asm/ioctls.h>
#include <linux/debugfs.h>
+#include <linux/msm_audio_ion.h>
#include "audio_utils_aio.h"
#ifdef CONFIG_USE_DEV_CTRL_VOLUME
#include <mach/qdsp6v2/audio_dev_ctl.h>
@@ -374,8 +375,7 @@
list_for_each_safe(ptr, next, &audio->ion_region_queue) {
region = list_entry(ptr, struct audio_aio_ion_region, list);
list_del(®ion->list);
- ion_unmap_kernel(audio->client, region->handle);
- ion_free(audio->client, region->handle);
+ msm_audio_ion_free_legacy(audio->client, region->handle);
kfree(region);
}
@@ -557,7 +557,7 @@
audio_aio_disable(audio);
audio_aio_unmap_ion_region(audio);
audio_aio_reset_ion_region(audio);
- ion_client_destroy(audio->client);
+ msm_audio_ion_client_destroy(audio->client);
audio->event_abort = 1;
wake_up(&audio->event_wait);
audio_aio_reset_event_queue(audio);
@@ -771,12 +771,11 @@
{
ion_phys_addr_t paddr;
size_t len;
- unsigned long kvaddr;
struct audio_aio_ion_region *region;
int rc = -EINVAL;
struct ion_handle *handle;
unsigned long ionflag;
- void *temp_ptr;
+ void *kvaddr;
pr_debug("%s[%p]:\n", __func__, audio);
region = kmalloc(sizeof(*region), GFP_KERNEL);
@@ -786,31 +785,14 @@
goto end;
}
- handle = ion_import_dma_buf(audio->client, info->fd);
- if (IS_ERR_OR_NULL(handle)) {
- pr_err("%s: could not get handle of the given fd\n", __func__);
+ rc = msm_audio_ion_import_legacy("Audio_Dec_Client", audio->client,
+ &handle, info->fd, &ionflag,
+ 0, &paddr, &len, &kvaddr);
+ if (rc) {
+ pr_err("%s: msm audio ion alloc failed\n", __func__);
goto import_error;
}
- rc = ion_handle_get_flags(audio->client, handle, &ionflag);
- if (rc) {
- pr_err("%s: could not get flags for the handle\n", __func__);
- goto flag_error;
- }
-
- temp_ptr = ion_map_kernel(audio->client, handle);
- if (IS_ERR_OR_NULL(temp_ptr)) {
- pr_err("%s: could not get virtual address\n", __func__);
- goto map_error;
- }
- kvaddr = (unsigned long)temp_ptr;
-
- rc = ion_phys(audio->client, handle, &paddr, &len);
- if (rc) {
- pr_err("%s: could not get physical address\n", __func__);
- goto ion_error;
- }
-
rc = audio_aio_ion_check(audio, info->vaddr, len);
if (rc < 0) {
pr_err("%s: audio_aio_ion_check failed\n", __func__);
@@ -821,7 +803,7 @@
region->vaddr = info->vaddr;
region->fd = info->fd;
region->paddr = paddr;
- region->kvaddr = kvaddr;
+ region->kvaddr = (unsigned long)kvaddr;
region->len = len;
region->ref_cnt = 0;
pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
@@ -839,10 +821,7 @@
mmap_error:
list_del(®ion->list);
ion_error:
- ion_unmap_kernel(audio->client, handle);
-map_error:
-flag_error:
- ion_free(audio->client, handle);
+ msm_audio_ion_free_legacy(audio->client, handle);
import_error:
kfree(region);
end:
@@ -879,8 +858,8 @@
__func__, audio);
list_del(®ion->list);
- ion_unmap_kernel(audio->client, region->handle);
- ion_free(audio->client, region->handle);
+ msm_audio_ion_free_legacy(audio->client,
+ region->handle);
kfree(region);
rc = 0;
break;
@@ -1167,7 +1146,8 @@
break;
}
}
- audio->client = msm_ion_client_create(UINT_MAX, "Audio_Dec_Client");
+ audio->client = msm_audio_ion_client_create(UINT_MAX,
+ "Audio_Dec_Client");
if (IS_ERR_OR_NULL(audio->client)) {
pr_err("Unable to create ION client\n");
rc = -EACCES;
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
new file mode 100644
index 0000000..c9bc3d7
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <mach/subsystem_restart.h>
+#include <mach/qdsp6v2/apr.h>
+#include <linux/of_device.h>
+#include <linux/msm_audio_ion.h>
+
+struct msm_audio_ion_private {
+ bool smmu_enabled;
+ /*u32 group_id;*/
+ /*u32 domain_id;*/
+};
+
+static struct msm_audio_ion_private msm_audio_ion_data = {0,};
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+ struct ion_handle *handle,
+ ion_phys_addr_t *addr, size_t *len);
+
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+ struct ion_handle **handle, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+
+ *client = msm_audio_ion_client_create(UINT_MAX, name);
+ if (IS_ERR_OR_NULL((void *)(*client))) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto err;
+ }
+
+ *handle = ion_alloc(*client, bufsz, SZ_4K, (0x1<<ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ION memory allocation for AUDIO failed\n",
+ __func__);
+ goto err_ion_client;
+ }
+
+ rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(*client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(*client, *handle);
+err_ion_client:
+ msm_audio_ion_client_destroy(*client);
+err:
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+
+ *client = msm_audio_ion_client_create(UINT_MAX, name);
+ if (IS_ERR_OR_NULL((void *)(*client))) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto err;
+ }
+
+ /* name should be audio_acdb_client or Audio_Dec_Client,
+ bufsz should be 0 and fd shouldn't be 0 as of now
+ */
+ *handle = ion_import_dma_buf(*client, fd);
+ pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+ name, fd, *handle);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ion import dma buffer failed\n",
+ __func__);
+ goto err_ion_handle;
+ }
+
+ if (ionflag != NULL) {
+ rc = ion_handle_get_flags(*client, *handle, ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n",
+ __func__);
+ goto err_ion_handle;
+ }
+ }
+
+ rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(*client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(*client, *handle);
+ msm_audio_ion_client_destroy(*client);
+err:
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
+{
+ /* add condition for SMMU enabled */
+ ion_unmap_kernel(client, handle);
+
+ ion_free(client, handle);
+ msm_audio_ion_client_destroy(client);
+ return 0;
+}
+
+
+bool msm_audio_ion_is_smmu_available(void)
+{
+ return msm_audio_ion_data.smmu_enabled;
+}
+
+/* move to static section again */
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name)
+{
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+
+ return msm_ion_client_create(heap_mask, name);
+}
+
+
+void msm_audio_ion_client_destroy(struct ion_client *client)
+{
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+ ion_client_destroy(client);
+}
+
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+ /* client is already created for legacy and given*/
+ /* name should be audio_acdb_client or Audio_Dec_Client,
+ bufsz should be 0 and fd shouldn't be 0 as of now
+ */
+ *handle = ion_import_dma_buf(client, fd);
+ pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+ name, fd, *handle);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ion import dma buffer failed\n",
+ __func__);
+ goto err_ion_handle;
+ }
+
+ if (ionflag != NULL) {
+ rc = ion_handle_get_flags(client, *handle, ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n",
+ __func__);
+ goto err_ion_handle;
+ }
+ }
+
+ rc = msm_audio_ion_get_phys(client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(client, *handle);
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle)
+{
+ /* To add condition for SMMU enabled */
+ ion_unmap_kernel(client, handle);
+
+ ion_free(client, handle);
+ /* no client_destrody in legacy*/
+ return 0;
+}
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+ struct ion_handle *handle,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ int rc = 0;
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+ if (msm_audio_ion_data.smmu_enabled) {
+ /* SMMU enabled case ion_map_iommu()*/
+ } else {
+ /* SMMU is disabled*/
+ rc = ion_phys(client, handle, addr, len);
+ }
+ pr_debug("%s: addr= 0x%p, len= %d\n", __func__, addr, *len);
+ return rc;
+}
+
+
+
+
+static int msm_audio_ion_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ const char *msm_audio_ion_dt = "qcom,smmu-enabled";
+ bool smmu_enabled;
+
+ if (pdev->dev.of_node == NULL) {
+ pr_err("%s: device tree is not found\n", __func__);
+ msm_audio_ion_data.smmu_enabled = 0;
+ return 0;
+ }
+
+ smmu_enabled = of_property_read_bool(pdev->dev.of_node,
+ msm_audio_ion_dt);
+ msm_audio_ion_data.smmu_enabled = smmu_enabled;
+
+ pr_debug("%s: SMMU-Enabled = %d\n", __func__, smmu_enabled);
+ return rc;
+}
+
+static int msm_audio_ion_remove(struct platform_device *pdev)
+{
+ pr_debug("%s: msm audio ion is unloaded\n", __func__);
+
+ return 0;
+}
+
+static const struct of_device_id msm_audio_ion_dt_match[] = {
+ { .compatible = "qcom,msm-audio-ion" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
+
+static struct platform_driver msm_audio_ion_driver = {
+ .driver = {
+ .name = "msm-audio-ion",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_audio_ion_dt_match,
+ },
+ .probe = msm_audio_ion_probe,
+ .remove = __devexit_p(msm_audio_ion_remove),
+};
+
+static int __init msm_audio_ion_init(void)
+{
+ return platform_driver_register(&msm_audio_ion_driver);
+}
+module_init(msm_audio_ion_init);
+
+static void __exit msm_audio_ion_exit(void)
+{
+ platform_driver_unregister(&msm_audio_ion_driver);
+}
+module_exit(msm_audio_ion_exit);
+
+MODULE_DESCRIPTION("MSM Audio ION module");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index f23ba67..6594b08 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -413,6 +413,32 @@
return rc;
}
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
+{
+ struct adsp_dolby_manufacturer_id payload;
+ int rc = 0;
+ pr_debug("%s manufacturer_id :%d\n", __func__, manufacturer_id);
+ core_open();
+ if (core_handle_q) {
+ payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ payload.hdr.pkt_size =
+ sizeof(struct adsp_dolby_manufacturer_id);
+ payload.hdr.src_port = 0;
+ payload.hdr.dest_port = 0;
+ payload.hdr.token = 0;
+ payload.hdr.opcode = ADSP_CMD_SET_DOLBY_MANUFACTURER_ID;
+ payload.manufacturer_id = manufacturer_id;
+ pr_debug("Send Dolby security opcode=%x manufacturer ID = %d\n",
+ payload.hdr.opcode, payload.manufacturer_id);
+ rc = apr_send_pkt(core_handle_q, (uint32_t *)&payload);
+ if (rc < 0)
+ pr_err("%s: SET_DOLBY_MANUFACTURER_ID failed op[0x%x]rc[%d]\n",
+ __func__, payload.hdr.opcode, rc);
+ }
+ return rc;
+}
+
static const struct file_operations apr_debug_fops = {
.write = apr_debug_write,
.open = apr_debug_open,
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 8a2c23f..0b270b7 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -63,7 +63,6 @@
struct tty_port port;
struct device *device_ptr;
struct wake_lock wake_lock;
- int open_count;
struct tasklet_struct tty_tsklt;
struct timer_list buf_req_timer;
struct completion ch_allocated;
@@ -333,112 +332,106 @@
mutex_lock(&smd_tty_lock);
tty->driver_data = info;
- if (info->open_count++ == 0) {
- peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
- if (peripheral) {
- info->pil = subsystem_get(peripheral);
- if (IS_ERR(info->pil)) {
- SMD_TTY_INFO(
- "%s failed on smd_tty device :%s subsystem_get failed for %s",
- __func__, smd_tty[n].smd->port_name,
- peripheral);
- /*
- * Sleep, inorder to reduce the frequency of
- * retry by user-space modules and to avoid
- * possible watchdog bite.
- */
- msleep((smd_tty[n].open_wait * 1000));
- res = PTR_ERR(info->pil);
- goto out;
- }
-
- /* Wait for the modem SMSM to be inited for the SMD
- * Loopback channel to be allocated at the modem. Since
- * the wait need to be done atmost once, using msleep
- * doesn't degrade the performance.
- */
- if (n == LOOPBACK_IDX) {
- if (!is_modem_smsm_inited())
- msleep(5000);
- smsm_change_state(SMSM_APPS_STATE,
- 0, SMSM_SMD_LOOPBACK);
- msleep(100);
- }
-
+ peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
+ if (peripheral) {
+ info->pil = subsystem_get(peripheral);
+ if (IS_ERR(info->pil)) {
+ SMD_TTY_INFO(
+ "%s failed on smd_tty device :%s subsystem_get failed for %s",
+ __func__, smd_tty[n].smd->port_name,
+ peripheral);
/*
- * Wait for a channel to be allocated so we know
- * the modem is ready enough.
+ * Sleep, inorder to reduce the frequency of
+ * retry by user-space modules and to avoid
+ * possible watchdog bite.
*/
- if (smd_tty[n].open_wait) {
- res = wait_for_completion_interruptible_timeout(
+ msleep((smd_tty[n].open_wait * 1000));
+ res = PTR_ERR(info->pil);
+ goto out;
+ }
+
+ /* Wait for the modem SMSM to be inited for the SMD
+ * Loopback channel to be allocated at the modem. Since
+ * the wait need to be done atmost once, using msleep
+ * doesn't degrade the performance.
+ */
+ if (n == LOOPBACK_IDX) {
+ if (!is_modem_smsm_inited())
+ msleep(5000);
+ smsm_change_state(SMSM_APPS_STATE,
+ 0, SMSM_SMD_LOOPBACK);
+ msleep(100);
+ }
+
+ /*
+ * Wait for a channel to be allocated so we know
+ * the modem is ready enough.
+ */
+ if (smd_tty[n].open_wait) {
+ res = wait_for_completion_interruptible_timeout(
&info->ch_allocated,
msecs_to_jiffies(smd_tty[n].open_wait *
1000));
- if (res == 0) {
- SMD_TTY_INFO(
- "Timed out waiting for SMD channel %s",
- smd_tty[n].smd->port_name);
- res = -ETIMEDOUT;
- goto release_pil;
- } else if (res < 0) {
- SMD_TTY_INFO(
- "Error waiting for SMD channel %s : %d\n",
- smd_tty[n].smd->port_name, res);
- goto release_pil;
- }
-
- res = 0;
- }
- }
-
- tasklet_init(&info->tty_tsklt, smd_tty_read,
- (unsigned long)info);
- wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
- smd_tty[n].smd->port_name);
- scnprintf(info->ra_wake_lock_name,
- MAX_RA_WAKE_LOCK_NAME_LEN,
- "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
- wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
- info->ra_wake_lock_name);
- if (!info->ch) {
- res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
- smd_tty[n].smd->edge,
- &info->ch, info,
- smd_tty_notify);
- if (res < 0) {
+ if (res == 0) {
SMD_TTY_INFO(
- "%s: %s open failed %d\n",
- __func__, smd_tty[n].smd->port_name,
- res);
- goto release_pil;
- }
-
- res = wait_event_interruptible_timeout(
- info->ch_opened_wait_queue,
- info->is_open, (2 * HZ));
- if (res == 0)
+ "Timed out waiting for SMD channel %s",
+ smd_tty[n].smd->port_name);
res = -ETIMEDOUT;
- if (res < 0) {
+ goto release_pil;
+ } else if (res < 0) {
SMD_TTY_INFO(
- "%s: wait for %s smd_open failed %d\n",
- __func__, smd_tty[n].smd->port_name,
- res);
+ "Error waiting for SMD channel %s : %d\n",
+ smd_tty[n].smd->port_name, res);
goto release_pil;
}
- res = 0;
- SMD_TTY_INFO("%s with PID %u opened port %s",
- current->comm, current->pid,
- smd_tty[n].smd->port_name);
}
}
+ tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
+ wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
+ smd_tty[n].smd->port_name);
+ scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
+ "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
+ wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
+ info->ra_wake_lock_name);
+
+ res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
+ smd_tty[n].smd->edge, &info->ch, info,
+ smd_tty_notify);
+ if (res < 0) {
+ SMD_TTY_INFO("%s: %s open failed %d\n",
+ __func__, smd_tty[n].smd->port_name, res);
+ goto release_wl_tl;
+ }
+
+ res = wait_event_interruptible_timeout(info->ch_opened_wait_queue,
+ info->is_open, (2 * HZ));
+ if (res == 0)
+ res = -ETIMEDOUT;
+ if (res < 0) {
+ SMD_TTY_INFO("%s: wait for %s smd_open failed %d\n",
+ __func__, smd_tty[n].smd->port_name, res);
+ goto close_ch;
+ }
+ SMD_TTY_INFO("%s with PID %u opened port %s",
+ current->comm, current->pid, smd_tty[n].smd->port_name);
+ smd_disable_read_intr(info->ch);
+ mutex_unlock(&smd_tty_lock);
+ return 0;
+
+close_ch:
+ smd_close(info->ch);
+ info->ch = NULL;
+
+release_wl_tl:
+ tasklet_kill(&info->tty_tsklt);
+ wake_lock_destroy(&info->wake_lock);
+ wake_lock_destroy(&info->ra_wake_lock);
+
release_pil:
- if (res < 0)
- subsystem_put(info->pil);
- else
- smd_disable_read_intr(info->ch);
+ subsystem_put(info->pil);
out:
mutex_unlock(&smd_tty_lock);
@@ -458,26 +451,25 @@
}
mutex_lock(&smd_tty_lock);
- if (--info->open_count == 0) {
- spin_lock_irqsave(&info->reset_lock, flags);
- info->is_open = 0;
- spin_unlock_irqrestore(&info->reset_lock, flags);
- if (tty) {
- tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
- }
- SMD_TTY_INFO("%s with PID %u closed port %s",
- current->comm, current->pid,
- info->smd->port_name);
- tty->driver_data = 0;
- del_timer(&info->buf_req_timer);
- if (info->ch) {
- smd_close(info->ch);
- info->ch = 0;
- subsystem_put(info->pil);
- }
- }
+
+ spin_lock_irqsave(&info->reset_lock, flags);
+ info->is_open = 0;
+ spin_unlock_irqrestore(&info->reset_lock, flags);
+
+ tasklet_kill(&info->tty_tsklt);
+ wake_lock_destroy(&info->wake_lock);
+ wake_lock_destroy(&info->ra_wake_lock);
+
+ SMD_TTY_INFO("%s with PID %u closed port %s",
+ current->comm, current->pid,
+ info->smd->port_name);
+ tty->driver_data = NULL;
+ del_timer(&info->buf_req_timer);
+
+ smd_close(info->ch);
+ info->ch = NULL;
+ subsystem_put(info->pil);
+
mutex_unlock(&smd_tty_lock);
tty_kref_put(tty);
}
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 1f0fa85..ee6dfbf 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -845,25 +845,7 @@
static void * __init setup_dummy_socinfo(void)
{
- if (machine_is_msm8960_cdp())
- dummy_socinfo.id = 87;
- else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
- dummy_socinfo.id = 104;
- else if (early_machine_is_msm8974()) {
- dummy_socinfo.id = 126;
- strlcpy(dummy_socinfo.build_id, "msm8974 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (early_machine_is_msm9625()) {
- dummy_socinfo.id = 134;
- strlcpy(dummy_socinfo.build_id, "msm9625 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (early_machine_is_msm8226()) {
- dummy_socinfo.id = 145;
- strlcpy(dummy_socinfo.build_id, "msm8226 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (machine_is_msm8625_rumi3())
- dummy_socinfo.id = 127;
- else if (early_machine_is_mpq8092()) {
+ if (early_machine_is_mpq8092()) {
dummy_socinfo.id = 146;
strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
sizeof(dummy_socinfo.build_id));
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 66567bb..26b92d4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -361,7 +361,7 @@
BUG_ON(!arm_memblock_steal_permitted);
- phys = memblock_alloc(size, align);
+ phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size);
memblock_remove(phys, size);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 8545a5c..ba0fd7c 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -40,7 +40,6 @@
#define CRYPTO_CONFIG_RESET 0xE001F
#define QCE_MAX_NUM_DSCR 0x400
-#define QCE_SIZE_BAM_DSCR 0x08
#define QCE_SECTOR_SIZE 0x200
static DEFINE_MUTEX(bam_register_cnt);
@@ -1095,7 +1094,8 @@
* descriptor memory (256 bytes + 8 bytes). But in order to be
* in power of 2, we are allocating 512 bytes of memory.
*/
- sps_connect_info->desc.size = QCE_MAX_NUM_DSCR * QCE_SIZE_BAM_DSCR;
+ sps_connect_info->desc.size = QCE_MAX_NUM_DSCR *
+ sizeof(struct sps_iovec);
sps_connect_info->desc.base = dma_alloc_coherent(pce_dev->pdev,
sps_connect_info->desc.size,
&sps_connect_info->desc.phys_base,
@@ -2216,12 +2216,12 @@
pce_dev->ce_sps.in_transfer.iovec = (struct sps_iovec *)vaddr;
pce_dev->ce_sps.in_transfer.iovec_phys =
(uint32_t)GET_PHYS_ADDR(vaddr);
- vaddr += MAX_BAM_DESCRIPTORS * 8;
+ vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
pce_dev->ce_sps.out_transfer.iovec = (struct sps_iovec *)vaddr;
pce_dev->ce_sps.out_transfer.iovec_phys =
(uint32_t)GET_PHYS_ADDR(vaddr);
- vaddr += MAX_BAM_DESCRIPTORS * 8;
+ vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
qce_setup_cmdlistptrs(pce_dev, &vaddr);
vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index dc4ccf7..f5123df 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -17,7 +17,6 @@
/* MAX Data xfer block size between BAM and CE */
#define MAX_CE_BAM_BURST_SIZE 0x40
#define QCEBAM_BURST_SIZE MAX_CE_BAM_BURST_SIZE
-#define MAX_BAM_DESCRIPTORS (0x40 - 1)
#define GET_VIRT_ADDR(x) \
((uint32_t)pce_dev->coh_vmem + \
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index ce25bfd..d3434d8 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -456,7 +456,7 @@
struct ion_handle *handle;
struct ion_device *dev = client->dev;
struct ion_buffer *buffer = NULL;
- unsigned long secure_allocation = flags & ION_SECURE;
+ unsigned long secure_allocation = flags & ION_FLAG_SECURE;
const unsigned int MAX_DBG_STR_LEN = 64;
char dbg_str[MAX_DBG_STR_LEN];
unsigned int dbg_str_idx = 0;
diff --git a/drivers/gpu/ion/ion_cma_secure_heap.c b/drivers/gpu/ion/ion_cma_secure_heap.c
index d7a5920..0fbcfbf 100644
--- a/drivers/gpu/ion/ion_cma_secure_heap.c
+++ b/drivers/gpu/ion/ion_cma_secure_heap.c
@@ -117,7 +117,7 @@
unsigned long len, unsigned long align,
unsigned long flags)
{
- unsigned long secure_allocation = flags & ION_SECURE;
+ unsigned long secure_allocation = flags & ION_FLAG_SECURE;
struct ion_secure_cma_buffer_info *buf = NULL;
if (!secure_allocation) {
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 7bcae01..88addab 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -289,8 +289,8 @@
unsigned long flags)
{
unsigned long offset;
- unsigned long secure_allocation = flags & ION_SECURE;
- unsigned long force_contig = flags & ION_FORCE_CONTIGUOUS;
+ unsigned long secure_allocation = flags & ION_FLAG_SECURE;
+ unsigned long force_contig = flags & ION_FLAG_FORCE_CONTIGUOUS;
struct ion_cp_heap *cp_heap =
container_of(heap, struct ion_cp_heap, heap);
@@ -460,7 +460,7 @@
buf->want_delayed_unsecure = 0;
atomic_set(&buf->secure_cnt, 0);
mutex_init(&buf->lock);
- buf->is_secure = flags & ION_SECURE ? 1 : 0;
+ buf->is_secure = flags & ION_FLAG_SECURE ? 1 : 0;
buffer->priv_virt = buf;
return 0;
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 46fefb5..510b9ce 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -18,13 +18,12 @@
#include <linux/err.h>
#include <linux/ion.h>
#include "ion_priv.h"
-#include <linux/msm_ion.h>
struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
{
struct ion_heap *heap = NULL;
- switch ((int) heap_data->type) {
+ switch (heap_data->type) {
case ION_HEAP_TYPE_SYSTEM_CONTIG:
heap = ion_system_contig_heap_create(heap_data);
break;
@@ -34,21 +33,6 @@
case ION_HEAP_TYPE_CARVEOUT:
heap = ion_carveout_heap_create(heap_data);
break;
- case ION_HEAP_TYPE_IOMMU:
- heap = ion_iommu_heap_create(heap_data);
- break;
- case ION_HEAP_TYPE_CP:
- heap = ion_cp_heap_create(heap_data);
- break;
-#ifdef CONFIG_CMA
- case ION_HEAP_TYPE_DMA:
- heap = ion_cma_heap_create(heap_data);
- break;
-
- case ION_HEAP_TYPE_SECURE_DMA:
- heap = ion_secure_cma_heap_create(heap_data);
- break;
-#endif
default:
pr_err("%s: Invalid heap type %d\n", __func__,
heap_data->type);
@@ -73,7 +57,7 @@
if (!heap)
return;
- switch ((int) heap->type) {
+ switch (heap->type) {
case ION_HEAP_TYPE_SYSTEM_CONTIG:
ion_system_contig_heap_destroy(heap);
break;
@@ -83,20 +67,6 @@
case ION_HEAP_TYPE_CARVEOUT:
ion_carveout_heap_destroy(heap);
break;
- case ION_HEAP_TYPE_IOMMU:
- ion_iommu_heap_destroy(heap);
- break;
- case ION_HEAP_TYPE_CP:
- ion_cp_heap_destroy(heap);
- break;
-#ifdef CONFIG_CMA
- case ION_HEAP_TYPE_DMA:
- ion_cma_heap_destroy(heap);
- break;
- case ION_HEAP_TYPE_SECURE_DMA:
- ion_secure_cma_heap_destroy(heap);
- break;
-#endif
default:
pr_err("%s: Invalid heap type %d\n", __func__,
heap->type);
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 33e6fed..4b55875 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -750,6 +750,68 @@
return 0;
}
+static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_heap *heap = NULL;
+
+ switch ((int)heap_data->type) {
+ case ION_HEAP_TYPE_IOMMU:
+ heap = ion_iommu_heap_create(heap_data);
+ break;
+ case ION_HEAP_TYPE_CP:
+ heap = ion_cp_heap_create(heap_data);
+ break;
+#ifdef CONFIG_CMA
+ case ION_HEAP_TYPE_DMA:
+ heap = ion_cma_heap_create(heap_data);
+ break;
+
+ case ION_HEAP_TYPE_SECURE_DMA:
+ heap = ion_secure_cma_heap_create(heap_data);
+ break;
+#endif
+ default:
+ heap = ion_heap_create(heap_data);
+ }
+
+ if (IS_ERR_OR_NULL(heap)) {
+ pr_err("%s: error creating heap %s type %d base %pa size %u\n",
+ __func__, heap_data->name, heap_data->type,
+ &heap_data->base, heap_data->size);
+ return ERR_PTR(-EINVAL);
+ }
+
+ heap->name = heap_data->name;
+ heap->id = heap_data->id;
+ heap->priv = heap_data->priv;
+ return heap;
+}
+
+static void msm_ion_heap_destroy(struct ion_heap *heap)
+{
+ if (!heap)
+ return;
+
+ switch ((int)heap->type) {
+ case ION_HEAP_TYPE_IOMMU:
+ ion_iommu_heap_destroy(heap);
+ break;
+ case ION_HEAP_TYPE_CP:
+ ion_cp_heap_destroy(heap);
+ break;
+#ifdef CONFIG_CMA
+ case ION_HEAP_TYPE_DMA:
+ ion_cma_heap_destroy(heap);
+ break;
+ case ION_HEAP_TYPE_SECURE_DMA:
+ ion_secure_cma_heap_destroy(heap);
+ break;
+#endif
+ default:
+ ion_heap_destroy(heap);
+ }
+}
+
static int msm_ion_probe(struct platform_device *pdev)
{
struct ion_platform_data *pdata;
@@ -791,7 +853,7 @@
msm_ion_allocate(heap_data);
heap_data->has_outer_cache = pdata->has_outer_cache;
- heaps[i] = ion_heap_create(heap_data);
+ heaps[i] = msm_ion_heap_create(heap_data);
if (IS_ERR_OR_NULL(heaps[i])) {
heaps[i] = 0;
continue;
@@ -829,7 +891,7 @@
int i;
for (i = 0; i < num_heaps; i++)
- ion_heap_destroy(heaps[i]);
+ msm_ion_heap_destroy(heaps[i]);
ion_device_destroy(idev);
kfree(heaps);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 2377397..62b6a71 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1772,6 +1772,8 @@
start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
size);
kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (KGSL_CMD_IDENTIFIER == val1) {
if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
start_ptr = adreno_ringbuffer_dec_wrapped(
@@ -1809,6 +1811,8 @@
temp_rb_rptr, size);
kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
temp_rb_rptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (check && ((inc && val[i] == global_eop) ||
(!inc && (val[i] ==
@@ -1873,6 +1877,8 @@
while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (check && val[i] == ib1) {
/* decrement i, i.e i = (i - 1 + 2) % 2 */
@@ -1939,6 +1945,9 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
+ /* Ensure context id and global eop ts read complete */
+ rmb();
+
ft_data->rb_buffer = vmalloc(rb->buffer_desc.size);
if (!ft_data->rb_buffer) {
KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
@@ -2016,6 +2025,8 @@
&curr_global_ts,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
+ /* Ensure above read is finished before long ib check */
+ rmb();
/* Mark long ib as handled */
adreno_dev->long_ib = 0;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 3f31e36..dd9bdc3 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1840,14 +1840,14 @@
static unsigned int a2xx_irq_pending(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = &adreno_dev->dev;
- unsigned int rbbm, cp, mh;
+ unsigned int status;
- adreno_regread(device, REG_RBBM_INT_CNTL, &rbbm);
- adreno_regread(device, REG_CP_INT_CNTL, &cp);
- adreno_regread(device, MH_INTERRUPT_MASK, &mh);
+ adreno_regread(device, REG_MASTER_INT_SIGNAL, &status);
- return ((rbbm & RBBM_INT_MASK) || (cp & CP_INT_MASK) ||
- (mh & kgsl_mmu_get_int_mask())) ? 1 : 0;
+ return (status &
+ (MASTER_INT_SIGNAL__MH_INT_STAT |
+ MASTER_INT_SIGNAL__CP_INT_STAT |
+ MASTER_INT_SIGNAL__RBBM_INT_STAT)) ? 1 : 0;
}
static int a2xx_rb_init(struct adreno_device *adreno_dev,
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 296de11..4c9c744 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -106,7 +106,12 @@
{
struct kgsl_snapshot_linux_context *header = _ctxtptr;
struct kgsl_context *context = ptr;
- struct kgsl_device *device = context->dev_priv->device;
+ struct kgsl_device *device;
+
+ if (context)
+ device = context->dev_priv->device;
+ else
+ device = (struct kgsl_device *)data;
header->id = id;
@@ -141,6 +146,9 @@
idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
+ /* Increment ctxcount for the global memstore */
+ ctxtcount++;
+
size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
/* Make sure there is enough room for the data */
@@ -186,8 +194,10 @@
header->ctxtcount = ctxtcount;
- /* append information for each context */
_ctxtptr = snapshot + sizeof(*header);
+ /* append information for the global context */
+ snapshot_context_info(KGSL_MEMSTORE_GLOBAL, NULL, device);
+ /* append information for each context */
idr_for_each(&device->context_idr, snapshot_context_info, NULL);
/* Return the size of the data segment */
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index 268aac3..1be0870 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -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
@@ -29,7 +29,7 @@
#define Z180_DEFAULT_PWRSCALE_POLICY NULL
/* Wait a maximum of 10 seconds when trying to idle the core */
-#define Z180_IDLE_TIMEOUT (10 * 1000)
+#define Z180_IDLE_TIMEOUT (20 * 1000)
struct z180_ringbuffer {
unsigned int prevctx;
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index a4937d7..0b02a34 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -115,7 +115,7 @@
#define QPNP_ADC_GAIN_NV 17857
#define QPNP_OFFSET_CALIBRATION_SHORT_CADC_LEADS_IDEAL 0
#define QPNP_IADC_INTERNAL_RSENSE_N_OHMS_FACTOR 10000000
-#define QPNP_IADC_NANO_VOLTS_FACTOR 1000000000
+#define QPNP_IADC_NANO_VOLTS_FACTOR 1000000
#define QPNP_IADC_CALIB_SECONDS 300000
#define QPNP_IADC_RSENSE_LSB_N_OHMS_PER_BIT 15625
#define QPNP_IADC_DIE_TEMP_CALIB_OFFSET 5000
@@ -345,6 +345,8 @@
return rc;
}
+ INIT_COMPLETION(iadc->adc->adc_rslt_completion);
+
rc = qpnp_iadc_enable(true);
if (rc)
return rc;
@@ -591,6 +593,7 @@
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
int32_t rc, rsense_n_ohms, sign = 0, num, mode_sel = 0;
+ int32_t rsense_u_ohms = 0;
int64_t result_current;
uint16_t raw_data;
@@ -616,7 +619,7 @@
rc = qpnp_iadc_get_rsense(&rsense_n_ohms);
pr_debug("current raw:0%x and rsense:%d\n",
raw_data, rsense_n_ohms);
-
+ rsense_u_ohms = rsense_n_ohms/1000;
num = raw_data - iadc->adc->calib.offset_raw;
if (num < 0) {
sign = 1;
@@ -627,7 +630,7 @@
(iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
result_current = result->result_uv;
result_current *= QPNP_IADC_NANO_VOLTS_FACTOR;
- do_div(result_current, rsense_n_ohms);
+ do_div(result_current, rsense_u_ohms);
if (sign) {
result->result_uv = -result->result_uv;
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 5d66241..986c062 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -30,7 +30,6 @@
#define DEBUG_FW_UPDATE
#define SHOW_PROGRESS
-#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img"
#define MAX_FIRMWARE_ID_LEN 10
#define FORCE_UPDATE false
#define INSIDE_FIRMWARE_UPDATE
@@ -585,7 +584,8 @@
deviceFirmwareID = extract_uint(firmware_id);
/* .img firmware id */
- strptr = strstr(FW_IMAGE_NAME, "PR");
+ strptr = strnstr(fwu->rmi4_data->fw_image_name, "PR",
+ sizeof(fwu->rmi4_data->fw_image_name));
if (!strptr) {
dev_err(&i2c_client->dev,
"No valid PR number (PRxxxxxxx)" \
@@ -1219,19 +1219,28 @@
pr_notice("%s: Start of reflash process\n", __func__);
+ if (!fwu->rmi4_data->fw_image_name) {
+ retval = 0;
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "Firmware image name not given, skipping update\n");
+ goto exit;
+ }
+
if (fwu->ext_data_source)
fw_image = fwu->ext_data_source;
else {
dev_dbg(&fwu->rmi4_data->i2c_client->dev,
"%s: Requesting firmware image %s\n",
- __func__, FW_IMAGE_NAME);
+ __func__, fwu->rmi4_data->fw_image_name);
- retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
+ retval = request_firmware(&fw_entry,
+ fwu->rmi4_data->fw_image_name,
&fwu->rmi4_data->i2c_client->dev);
if (retval != 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Firmware image %s not available\n",
- __func__, FW_IMAGE_NAME);
+ __func__,
+ fwu->rmi4_data->fw_image_name);
retval = -EINVAL;
goto exit;
}
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index e1b3884..417ef83 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1006,6 +1006,13 @@
rmi4_pdata->panel_y = temp_val;
}
+ rc = of_property_read_string(np, "synaptics,fw-image-name",
+ &rmi4_pdata->fw_image_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw image name\n");
+ return rc;
+ }
+
/* reset, irq gpio info */
rmi4_pdata->reset_gpio = of_get_named_gpio_flags(np,
"synaptics,reset-gpio", 0, &rmi4_pdata->reset_flags);
@@ -2030,6 +2037,8 @@
rmi4_data->flip_x = rmi4_data->board->x_flip;
rmi4_data->flip_y = rmi4_data->board->y_flip;
+ rmi4_data->fw_image_name = rmi4_data->board->fw_image_name;
+
rmi4_data->input_dev->name = DRIVER_NAME;
rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
rmi4_data->input_dev->id.bustype = BUS_I2C;
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 9356937..16b1f8f 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -198,6 +198,7 @@
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
+ const char *fw_image_name;
unsigned char current_page;
unsigned char button_0d_enabled;
unsigned char full_pm_cycle;
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 1c15a41..aea3431 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -66,6 +66,8 @@
DMX_OK = 0, /* Received Ok */
DMX_OK_PES_END, /* Received OK, data reached end of PES packet */
DMX_OK_PCR, /* Received OK, data with new PCR/STC pair */
+ DMX_OK_EOS, /* Received OK, reached End-of-Stream (EOS) */
+ DMX_OK_MARKER, /* Received OK, reached a data Marker */
DMX_LENGTH_ERROR, /* Incorrect length */
DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */
DMX_CRC_ERROR, /* Incorrect CRC */
@@ -87,7 +89,7 @@
enum dmx_success status;
/*
- * data_length may be 0 in case of DMX_OK_PES_END
+ * data_length may be 0 in case of DMX_OK_PES_END or DMX_OK_EOS
* and in non-DMX_OK_XXX events. In DMX_OK_PES_END,
* data_length is for data comming after the end of PES.
*/
@@ -125,6 +127,10 @@
u32 ts_packets_num;
u32 ts_dropped_bytes;
} buf;
+
+ struct {
+ u64 id;
+ } marker;
};
};
@@ -232,6 +238,9 @@
enum dmx_tsp_format_t tsp_format);
int (*set_secure_mode)(struct dmx_ts_feed *feed,
struct dmx_secure_mode *sec_mode);
+ int (*oob_command) (struct dmx_ts_feed *feed,
+ struct dmx_oob_command *cmd);
+
};
/*--------------------------------------------------------------------------*/
@@ -280,6 +289,8 @@
u32 bytes_num);
int (*set_secure_mode)(struct dmx_section_feed *feed,
struct dmx_secure_mode *sec_mode);
+ int (*oob_command) (struct dmx_section_feed *feed,
+ struct dmx_oob_command *cmd);
};
/*--------------------------------------------------------------------------*/
@@ -413,6 +424,8 @@
int (*unmap_buffer) (struct dmx_demux *demux,
void *priv_handle);
+
+ int (*get_tsp_size) (struct dmx_demux *demux);
};
#endif /* #ifndef __DEMUX_H */
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index dce37e5..ca61bcf 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -485,23 +485,56 @@
return NULL;
}
-static int dvr_input_thread_entry(void *arg)
+static void dvb_dvr_oob_cmd(struct dmxdev *dmxdev, struct dmx_oob_command *cmd)
{
- struct dmxdev *dmxdev = arg;
- struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
- int ret;
- size_t todo;
- int bytes_written;
- size_t split;
+ int i;
+ struct dmxdev_filter *filter;
+ struct dmxdev_feed *feed;
- while (1) {
+ for (i = 0; i < dmxdev->filternum; i++) {
+ filter = &dmxdev->filter[i];
+ if (!filter || filter->state != DMXDEV_STATE_GO)
+ continue;
+
+ switch (filter->type) {
+ case DMXDEV_TYPE_SEC:
+ filter->feed.sec.feed->oob_command(
+ filter->feed.sec.feed, cmd);
+ break;
+ case DMXDEV_TYPE_PES:
+ feed = list_first_entry(&filter->feed.ts,
+ struct dmxdev_feed, next);
+ feed->ts->oob_command(feed->ts, cmd);
+ break;
+ case DMXDEV_TYPE_NONE:
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static int dvb_dvr_feed_cmd(struct dmxdev *dmxdev, struct dvr_command *dvr_cmd)
+{
+ int ret = 0;
+ size_t todo;
+ int bytes_written = 0;
+ size_t split;
+ size_t tsp_size;
+ struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
+ todo = dvr_cmd->cmd.data_feed_count;
+
+ if (dmxdev->demux->get_tsp_size)
+ tsp_size = dmxdev->demux->get_tsp_size(dmxdev->demux);
+ else
+ tsp_size = 188;
+
+ while (todo >= tsp_size) {
/* wait for input */
ret = wait_event_interruptible(
src->queue,
- (!src->data) ||
- (dvb_ringbuffer_avail(src) > 188) ||
- (src->error != 0) ||
- dmxdev->dvr_in_exit);
+ (dvb_ringbuffer_avail(src) >= tsp_size) || (!src->data)
+ || (dmxdev->dvr_in_exit) || (src->error));
if (ret < 0)
break;
@@ -510,23 +543,21 @@
if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
spin_unlock(&dmxdev->dvr_in_lock);
+ ret = -ENODEV;
break;
}
if (src->error) {
spin_unlock(&dmxdev->dvr_in_lock);
wake_up_all(&src->queue);
+ ret = -EINVAL;
break;
}
dmxdev->dvr_processing_input = 1;
- ret = dvb_ringbuffer_avail(src);
- todo = ret;
-
- split = (src->pread + ret > src->size) ?
- src->size - src->pread :
- 0;
+ split = (src->pread + todo > src->size) ?
+ src->size - src->pread : 0;
/*
* In DVR PULL mode, write might block.
@@ -537,54 +568,128 @@
*/
if (split > 0) {
spin_unlock(&dmxdev->dvr_in_lock);
- bytes_written = dmxdev->demux->write(dmxdev->demux,
+ ret = dmxdev->demux->write(dmxdev->demux,
src->data + src->pread,
split);
- if (bytes_written < 0) {
+ if (ret < 0) {
printk(KERN_ERR "dmxdev: dvr write error %d\n",
- bytes_written);
+ ret);
continue;
}
- if (dmxdev->dvr_in_exit)
+ if (dmxdev->dvr_in_exit) {
+ ret = -ENODEV;
break;
+ }
spin_lock(&dmxdev->dvr_in_lock);
- todo -= bytes_written;
- DVB_RINGBUFFER_SKIP(src, bytes_written);
- if (bytes_written < split) {
+ todo -= ret;
+ bytes_written += ret;
+ DVB_RINGBUFFER_SKIP(src, ret);
+ if (ret < split) {
dmxdev->dvr_processing_input = 0;
spin_unlock(&dmxdev->dvr_in_lock);
wake_up_all(&src->queue);
continue;
}
-
}
spin_unlock(&dmxdev->dvr_in_lock);
- bytes_written = dmxdev->demux->write(dmxdev->demux,
- src->data + src->pread, todo);
+ ret = dmxdev->demux->write(dmxdev->demux,
+ src->data + src->pread, todo);
- if (bytes_written < 0) {
+ if (ret < 0) {
printk(KERN_ERR "dmxdev: dvr write error %d\n",
- bytes_written);
+ ret);
continue;
}
- if (dmxdev->dvr_in_exit)
+ if (dmxdev->dvr_in_exit) {
+ ret = -ENODEV;
break;
+ }
spin_lock(&dmxdev->dvr_in_lock);
- DVB_RINGBUFFER_SKIP(src, bytes_written);
+ todo -= ret;
+ bytes_written += ret;
+ DVB_RINGBUFFER_SKIP(src, ret);
dmxdev->dvr_processing_input = 0;
spin_unlock(&dmxdev->dvr_in_lock);
wake_up_all(&src->queue);
}
+ if (ret < 0)
+ return ret;
+
+ return bytes_written;
+}
+
+static int dvr_input_thread_entry(void *arg)
+{
+ struct dmxdev *dmxdev = arg;
+ struct dvb_ringbuffer *cmdbuf = &dmxdev->dvr_cmd_buffer;
+ struct dvr_command dvr_cmd;
+ int leftover = 0;
+ int ret;
+
+ while (1) {
+ /* wait for input */
+ ret = wait_event_interruptible(
+ cmdbuf->queue,
+ (!cmdbuf->data) ||
+ (dvb_ringbuffer_avail(cmdbuf) >= sizeof(dvr_cmd)) ||
+ (dmxdev->dvr_in_exit));
+
+ if (ret < 0)
+ break;
+
+ spin_lock(&dmxdev->dvr_in_lock);
+
+ if (!cmdbuf->data || dmxdev->exit || dmxdev->dvr_in_exit) {
+ spin_unlock(&dmxdev->dvr_in_lock);
+ break;
+ }
+
+ dvb_ringbuffer_read(cmdbuf, (u8 *)&dvr_cmd, sizeof(dvr_cmd));
+
+ spin_unlock(&dmxdev->dvr_in_lock);
+
+ if (dvr_cmd.type == DVR_DATA_FEED_CMD) {
+ dvr_cmd.cmd.data_feed_count += leftover;
+
+ ret = dvb_dvr_feed_cmd(dmxdev, &dvr_cmd);
+ if (ret < 0) {
+ printk(KERN_ERR
+ "%s: DVR data feed failed, ret=%d\n",
+ __func__, ret);
+ continue;
+ }
+
+ leftover = dvr_cmd.cmd.data_feed_count - ret;
+ } else {
+ /*
+ * For EOS, try to process leftover data in the input
+ * buffer.
+ */
+ if (dvr_cmd.cmd.oobcmd.type == DMX_OOB_CMD_EOS) {
+ struct dvr_command feed_cmd;
+
+ feed_cmd.type = DVR_DATA_FEED_CMD;
+ feed_cmd.cmd.data_feed_count =
+ dvb_ringbuffer_avail(
+ &dmxdev->dvr_input_buffer);
+
+ dvb_dvr_feed_cmd(dmxdev, &dvr_cmd);
+ }
+
+ dvb_dvr_oob_cmd(dmxdev, &dvr_cmd.cmd.oobcmd);
+ }
+ }
+
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
schedule();
@@ -675,6 +780,15 @@
dmxdev->demux->dvr_input.priv_handle = NULL;
dmxdev->demux->dvr_input.ringbuff = &dmxdev->dvr_input_buffer;
+ mem = vmalloc(DVR_CMDS_BUFFER_SIZE);
+ if (!mem) {
+ vfree(dmxdev->dvr_input_buffer.data);
+ dmxdev->dvr_input_buffer.data = NULL;
+ mutex_unlock(&dmxdev->mutex);
+ return -ENOMEM;
+ }
+ dvb_ringbuffer_init(&dmxdev->dvr_cmd_buffer, mem,
+ DVR_CMDS_BUFFER_SIZE);
dvbdev->writers--;
dmxdev->dvr_input_thread =
@@ -684,6 +798,10 @@
"dvr_input");
if (IS_ERR(dmxdev->dvr_input_thread)) {
+ vfree(dmxdev->dvr_input_buffer.data);
+ vfree(dmxdev->dvr_cmd_buffer.data);
+ dmxdev->dvr_input_buffer.data = NULL;
+ dmxdev->dvr_cmd_buffer.data = NULL;
mutex_unlock(&dmxdev->mutex);
return -ENOMEM;
}
@@ -725,7 +843,8 @@
int i;
dmxdev->dvr_in_exit = 1;
- wake_up_all(&dmxdev->dvr_input_buffer.queue);
+
+ wake_up_all(&dmxdev->dvr_cmd_buffer.queue);
/*
* There might be dmx filters reading now from DVR
@@ -776,6 +895,15 @@
dmxdev->demux->dvr_input.priv_handle);
dmxdev->demux->dvr_input.priv_handle = NULL;
}
+
+ if (dmxdev->dvr_cmd_buffer.data) {
+ void *mem = dmxdev->dvr_cmd_buffer.data;
+ mb();
+ spin_lock_irq(&dmxdev->dvr_in_lock);
+ dmxdev->dvr_cmd_buffer.data = NULL;
+ spin_unlock_irq(&dmxdev->dvr_in_lock);
+ vfree(mem);
+ }
}
/* TODO */
dvbdev->users--;
@@ -850,12 +978,57 @@
return ret;
}
+static void dvb_dvr_queue_data_feed(struct dmxdev *dmxdev, size_t count)
+{
+ struct dvb_ringbuffer *cmdbuf = &dmxdev->dvr_cmd_buffer;
+ struct dvr_command *dvr_cmd;
+ int last_dvr_cmd;
+
+ spin_lock(&dmxdev->dvr_in_lock);
+
+ /* Peek at the last DVR command queued, try to coalesce FEED commands */
+ if (dvb_ringbuffer_avail(cmdbuf) >= sizeof(*dvr_cmd)) {
+ last_dvr_cmd = cmdbuf->pwrite - sizeof(*dvr_cmd);
+ if (last_dvr_cmd < 0)
+ last_dvr_cmd += cmdbuf->size;
+
+ dvr_cmd = (struct dvr_command *)&cmdbuf->data[last_dvr_cmd];
+ if (dvr_cmd->type == DVR_DATA_FEED_CMD) {
+ dvr_cmd->cmd.data_feed_count += count;
+ spin_unlock(&dmxdev->dvr_in_lock);
+ return;
+ }
+ }
+
+ /*
+ * We assume command buffer is large enough so that overflow should not
+ * happen. Overflow to the command buffer means data previously written
+ * to the input buffer is 'orphan' - does not have a matching FEED
+ * command. Issue a warning if this ever happens.
+ * Orphan data might still be processed if EOS is issued.
+ */
+ if (dvb_ringbuffer_free(cmdbuf) < sizeof(*dvr_cmd)) {
+ printk(KERN_ERR "%s: DVR command buffer overflow\n", __func__);
+ spin_unlock(&dmxdev->dvr_in_lock);
+ return;
+ }
+
+ dvr_cmd = (struct dvr_command *)&cmdbuf->data[cmdbuf->pwrite];
+ dvr_cmd->type = DVR_DATA_FEED_CMD;
+ dvr_cmd->cmd.data_feed_count = count;
+ DVB_RINGBUFFER_PUSH(cmdbuf, sizeof(*dvr_cmd));
+ spin_unlock(&dmxdev->dvr_in_lock);
+
+ wake_up_all(&cmdbuf->queue);
+}
+
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct dvb_device *dvbdev = file->private_data;
struct dmxdev *dmxdev = dvbdev->priv;
struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
+ struct dvb_ringbuffer *cmdbuf = &dmxdev->dvr_cmd_buffer;
int ret;
size_t todo;
ssize_t free_space;
@@ -864,7 +1037,7 @@
return -EOPNOTSUPP;
if (((file->f_flags & O_ACCMODE) == O_RDONLY) ||
- (!src->data))
+ (!src->data) || (!cmdbuf->data))
return -EINVAL;
if ((file->f_flags & O_NONBLOCK) &&
@@ -874,10 +1047,9 @@
ret = 0;
for (todo = count; todo > 0; todo -= ret) {
ret = wait_event_interruptible(src->queue,
- (!src->data) ||
- (dvb_ringbuffer_free(src)) ||
- (src->error != 0) ||
- (dmxdev->dvr_in_exit));
+ (dvb_ringbuffer_free(src)) ||
+ (!src->data) || (!cmdbuf->data) ||
+ (src->error != 0) || (dmxdev->dvr_in_exit));
if (ret < 0)
return ret;
@@ -885,7 +1057,7 @@
if (mutex_lock_interruptible(&dmxdev->mutex))
return -ERESTARTSYS;
- if (!src->data) {
+ if ((!src->data) || (!cmdbuf->data)) {
mutex_unlock(&dmxdev->mutex);
return 0;
}
@@ -917,8 +1089,9 @@
buf += ret;
+ dvb_dvr_queue_data_feed(dmxdev, ret);
+
mutex_unlock(&dmxdev->mutex);
- wake_up_all(&src->queue);
}
return (count - todo) ? (count - todo) : ret;
@@ -968,6 +1141,34 @@
return res;
}
+/*
+ * dvb_dvr_push_oob_cmd
+ *
+ * Note: this function assume dmxdev->mutex was taken, so command buffer cannot
+ * be released during its operation.
+ */
+static int dvb_dvr_push_oob_cmd(struct dmxdev *dmxdev, unsigned int f_flags,
+ struct dmx_oob_command *cmd)
+{
+ struct dvb_ringbuffer *cmdbuf = &dmxdev->dvr_cmd_buffer;
+ struct dvr_command *dvr_cmd;
+
+ if ((f_flags & O_ACCMODE) == O_RDONLY ||
+ dmxdev->source < DMX_SOURCE_DVR0)
+ return -EPERM;
+
+ if (dvb_ringbuffer_free(cmdbuf) < sizeof(*dvr_cmd))
+ return -ENOMEM;
+
+ dvr_cmd = (struct dvr_command *)&cmdbuf->data[cmdbuf->pwrite];
+ dvr_cmd->type = DVR_OOB_CMD;
+ dvr_cmd->cmd.oobcmd = *cmd;
+ DVB_RINGBUFFER_PUSH(cmdbuf, sizeof(*dvr_cmd));
+ wake_up_all(&cmdbuf->queue);
+
+ return 0;
+}
+
static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
unsigned int f_flags,
unsigned long size)
@@ -1245,9 +1446,19 @@
return 0;
}
+/*
+ * dvb_dvr_feed_data - Notify new data in DVR input buffer
+ *
+ * @dmxdev - demux device instance
+ * @f_flags - demux device file flag (access mode)
+ * @bytes_count - how many bytes were written to the input buffer
+ *
+ * Note: this function assume dmxdev->mutex was taken, so buffer cannot
+ * be released during its operation.
+ */
static int dvb_dvr_feed_data(struct dmxdev *dmxdev,
- unsigned int f_flags,
- u32 bytes_count)
+ unsigned int f_flags,
+ u32 bytes_count)
{
ssize_t free_space;
struct dvb_ringbuffer *buffer = &dmxdev->dvr_input_buffer;
@@ -1263,10 +1474,9 @@
if (bytes_count > free_space)
return -EINVAL;
- buffer->pwrite =
- (buffer->pwrite + bytes_count) % buffer->size;
+ DVB_RINGBUFFER_PUSH(buffer, bytes_count);
- wake_up_all(&buffer->queue);
+ dvb_dvr_queue_data_feed(dmxdev, bytes_count);
return 0;
}
@@ -1825,8 +2035,10 @@
wake_up_all(&dmxdevfilter->buffer.queue);
return 0;
}
+
spin_lock(&dmxdevfilter->dev->lock);
- if (dmxdevfilter->state != DMXDEV_STATE_GO) {
+ if (dmxdevfilter->state != DMXDEV_STATE_GO ||
+ dmxdevfilter->eos_state) {
spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
@@ -1896,13 +2108,15 @@
int ret;
spin_lock(&dmxdevfilter->dev->lock);
- if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
+
+ if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER ||
+ dmxdevfilter->state != DMXDEV_STATE_GO ||
+ dmxdevfilter->eos_state) {
spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
- if (dmxdevfilter->params.pes.output == DMX_OUT_TAP
- || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
+ if (dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) {
buffer = &dmxdevfilter->buffer;
events = &dmxdevfilter->events;
} else {
@@ -1916,11 +2130,6 @@
return 0;
}
- if (dmxdevfilter->state != DMXDEV_STATE_GO) {
- spin_unlock(&dmxdevfilter->dev->lock);
- return 0;
- }
-
if (dmxdevfilter->params.pes.output == DMX_OUT_TAP) {
if ((success == DMX_OK) &&
(!events->current_event_data_size)) {
@@ -2010,7 +2219,8 @@
spin_lock(&dmxdevfilter->dev->lock);
- if (dmxdevfilter->state != DMXDEV_STATE_GO) {
+ if (dmxdevfilter->state != DMXDEV_STATE_GO ||
+ dmxdevfilter->eos_state) {
spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
@@ -2023,6 +2233,17 @@
spin_unlock(&dmxdevfilter->dev->lock);
wake_up_all(&dmxdevfilter->buffer.queue);
+ } else if (dmx_data_ready->status == DMX_OK_EOS) {
+ event.type = DMX_EVENT_EOS;
+ dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+ spin_unlock(&dmxdevfilter->dev->lock);
+ wake_up_all(&dmxdevfilter->buffer.queue);
+ } else if (dmx_data_ready->status == DMX_OK_MARKER) {
+ event.type = DMX_EVENT_MARKER;
+ event.params.marker.id = dmx_data_ready->marker.id;
+ dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+ spin_unlock(&dmxdevfilter->dev->lock);
+ wake_up_all(&dmxdevfilter->buffer.queue);
} else {
spin_unlock(&dmxdevfilter->dev->lock);
}
@@ -2076,7 +2297,8 @@
spin_lock(&dmxdevfilter->dev->lock);
- if (dmxdevfilter->state != DMXDEV_STATE_GO) {
+ if (dmxdevfilter->state != DMXDEV_STATE_GO ||
+ dmxdevfilter->eos_state) {
spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
@@ -2089,6 +2311,27 @@
events = &dmxdevfilter->dev->dvr_output_events;
}
+ if (dmx_data_ready->status == DMX_OK_EOS) {
+ dmxdevfilter->eos_state = 1;
+ dprintk("dmxdev: DMX_OK_EOS - entering EOS state\n");
+ event.type = DMX_EVENT_EOS;
+ dvb_dmxdev_add_event(events, &event);
+ spin_unlock(&dmxdevfilter->dev->lock);
+ wake_up_all(&dmxdevfilter->buffer.queue);
+ return 0;
+ }
+
+ if (dmx_data_ready->status == DMX_OK_MARKER) {
+ dprintk("dmxdev: DMX_OK_MARKER - id=%llu\n",
+ dmx_data_ready->marker.id);
+ event.type = DMX_EVENT_MARKER;
+ event.params.marker.id = dmx_data_ready->marker.id;
+ dvb_dmxdev_add_event(events, &event);
+ spin_unlock(&dmxdevfilter->dev->lock);
+ wake_up_all(&dmxdevfilter->buffer.queue);
+ return 0;
+ }
+
if (dmx_data_ready->status == DMX_OK_PCR) {
dprintk("dmxdev: event callback DMX_OK_PCR\n");
event.type = DMX_EVENT_NEW_PCR;
@@ -2505,6 +2748,8 @@
spin_unlock_irq(&filter->dev->lock);
}
+ filter->eos_state = 0;
+
spin_lock_irq(&filter->dev->lock);
dvb_dmxdev_flush_output(&filter->buffer, &filter->events);
spin_unlock_irq(&filter->dev->lock);
@@ -2535,7 +2780,7 @@
secfeed,
dvb_dmxdev_section_callback);
if (ret < 0) {
- printk("DVB (%s): could not alloc feed\n",
+ printk(KERN_ERR "DVB (%s): could not alloc feed\n",
__func__);
return ret;
}
@@ -2556,7 +2801,7 @@
ret = (*secfeed)->set(*secfeed, para->pid, 32768,
(para->flags & DMX_CHECK_CRC) ? 1 : 0);
if (ret < 0) {
- printk("DVB (%s): could not set feed\n",
+ printk(KERN_ERR "DVB (%s): could not set feed\n",
__func__);
dvb_dmxdev_feed_restart(filter);
return ret;
@@ -3033,6 +3278,12 @@
if (mutex_lock_interruptible(&dmxdevfilter->mutex))
return -ERESTARTSYS;
+ if (dmxdevfilter->eos_state &&
+ dvb_ringbuffer_empty(&dmxdevfilter->buffer)) {
+ mutex_unlock(&dmxdevfilter->mutex);
+ return 0;
+ }
+
if (dmxdevfilter->type == DMXDEV_TYPE_SEC)
ret = dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos);
else
@@ -3494,6 +3745,10 @@
ret = dvb_dvr_get_event(dmxdev, file->f_flags, parg);
break;
+ case DMX_PUSH_OOB_COMMAND:
+ ret = dvb_dvr_push_oob_cmd(dmxdev, file->f_flags, parg);
+ break;
+
default:
ret = -EINVAL;
break;
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 1443de5..7845b75 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -144,6 +144,9 @@
enum dmx_tsp_format_t dmx_tsp_format;
u32 rec_chunk_size;
+ /* End-of-stream indication has been received */
+ int eos_state;
+
/* only for sections */
struct timer_list timer;
int todo;
@@ -186,6 +189,8 @@
struct dvb_ringbuffer dvr_input_buffer;
enum dmx_buffer_mode dvr_input_buffer_mode;
struct task_struct *dvr_input_thread;
+ /* DVR commands (data feed / OOB command) queue */
+ struct dvb_ringbuffer dvr_cmd_buffer;
#define DVR_BUFFER_SIZE (10*188*1024)
@@ -194,6 +199,21 @@
spinlock_t dvr_in_lock;
};
+enum dvr_cmd {
+ DVR_DATA_FEED_CMD,
+ DVR_OOB_CMD
+};
+
+struct dvr_command {
+ enum dvr_cmd type;
+ union {
+ struct dmx_oob_command oobcmd;
+ size_t data_feed_count;
+ } cmd;
+};
+
+#define DVR_CMDS_BUFFER_SIZE (sizeof(struct dvr_command)*500)
+
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
void dvb_dmxdev_release(struct dmxdev *dmxdev);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 0fef315..4740a80 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1250,6 +1250,93 @@
return 0;
}
+static int dvbdmx_ts_feed_oob_cmd(struct dmx_ts_feed *ts_feed,
+ struct dmx_oob_command *cmd)
+{
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+ struct dmx_data_ready data;
+ struct dvb_demux *dvbdmx = feed->demux;
+ int ret;
+
+ mutex_lock(&dvbdmx->mutex);
+
+ if (feed->state != DMX_STATE_GO) {
+ mutex_unlock(&dvbdmx->mutex);
+ return -EINVAL;
+ }
+
+ /* Decoder feeds are handled by plug-in */
+ if (feed->ts_type & TS_DECODER) {
+ if (feed->demux->oob_command)
+ ret = feed->demux->oob_command(feed, cmd);
+ else
+ ret = 0;
+
+ mutex_unlock(&dvbdmx->mutex);
+ return ret;
+ }
+
+ data.data_length = 0;
+
+ switch (cmd->type) {
+ case DMX_OOB_CMD_EOS:
+ if (feed->ts_type & TS_PAYLOAD_ONLY) {
+ if (feed->secure_mode.is_secured) {
+ /* Secure feeds are handled by plug-in */
+ if (feed->demux->oob_command)
+ ret = feed->demux->oob_command(feed,
+ cmd);
+ else
+ ret = 0;
+ break;
+ }
+
+ /* Close last PES on non-secure feeds */
+ if (feed->pusi_seen) {
+ data.status = DMX_OK_PES_END;
+ data.pes_end.start_gap = 0;
+ data.pes_end.actual_length =
+ feed->peslen;
+ data.pes_end.disc_indicator_set = 0;
+ data.pes_end.pes_length_mismatch = 0;
+ data.pes_end.stc = 0;
+ data.pes_end.tei_counter =
+ feed->pes_tei_counter;
+ data.pes_end.cont_err_counter =
+ feed->pes_cont_err_counter;
+ data.pes_end.ts_packets_num =
+ feed->pes_ts_packets_num;
+
+ feed->peslen = 0;
+ feed->pes_tei_counter = 0;
+ feed->pes_ts_packets_num = 0;
+ feed->pes_cont_err_counter = 0;
+
+ ret = feed->data_ready_cb.ts(&feed->feed.ts,
+ &data);
+ if (ret)
+ break;
+ }
+ }
+ data.status = DMX_OK_EOS;
+ ret = feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ break;
+
+ case DMX_OOB_CMD_MARKER:
+ data.status = DMX_OK_MARKER;
+ data.marker.id = cmd->params.marker.id;
+ ret = feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&dvbdmx->mutex);
+ return ret;
+}
+
static int dmx_ts_set_tsp_out_format(
struct dmx_ts_feed *ts_feed,
enum dmx_tsp_format_t tsp_format)
@@ -1319,6 +1406,7 @@
(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
(*ts_feed)->notify_data_read = NULL;
(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
+ (*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
feed->state = DMX_STATE_FREE;
@@ -1598,6 +1686,55 @@
return 0;
}
+static int dvbdmx_section_feed_oob_cmd(struct dmx_section_feed *section_feed,
+ struct dmx_oob_command *cmd)
+{
+ struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
+ struct dvb_demux *dvbdmx = feed->demux;
+ struct dmx_data_ready data;
+ int ret;
+
+ data.data_length = 0;
+
+ mutex_lock(&dvbdmx->mutex);
+
+ if (feed->state != DMX_STATE_GO) {
+ mutex_unlock(&dvbdmx->mutex);
+ return -EINVAL;
+ }
+
+ /* Secure section feeds are handled by the plug-in */
+ if (feed->secure_mode.is_secured) {
+ if (feed->demux->oob_command)
+ ret = feed->demux->oob_command(feed, cmd);
+ else
+ ret = 0;
+
+ mutex_unlock(&dvbdmx->mutex);
+ return ret;
+ }
+
+ switch (cmd->type) {
+ case DMX_OOB_CMD_EOS:
+ data.status = DMX_OK_EOS;
+ ret = feed->data_ready_cb.sec(&feed->filter->filter, &data);
+ break;
+
+ case DMX_OOB_CMD_MARKER:
+ data.status = DMX_OK_MARKER;
+ data.marker.id = cmd->params.marker.id;
+ ret = feed->data_ready_cb.sec(&feed->filter->filter, &data);
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&dvbdmx->mutex);
+ return ret;
+}
+
static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
struct dmx_section_feed **feed,
dmx_section_cb callback)
@@ -1637,6 +1774,7 @@
(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
(*feed)->notify_data_read = NULL;
(*feed)->set_secure_mode = dmx_section_set_secure_mode;
+ (*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
mutex_unlock(&dvbdmx->mutex);
return 0;
@@ -1814,6 +1952,18 @@
return 0;
}
+static int dvbdmx_get_tsp_size(struct dmx_demux *demux)
+{
+ int tsp_size;
+ struct dvb_demux *dvbdemux = (struct dvb_demux *)demux;
+
+ mutex_lock(&dvbdemux->mutex);
+ tsp_size = dvbdemux->ts_packet_size;
+ mutex_unlock(&dvbdemux->mutex);
+
+ return tsp_size;
+}
+
static int dvbdmx_set_tsp_format(
struct dmx_demux *demux,
enum dmx_tsp_format_t tsp_format)
@@ -1944,6 +2094,7 @@
dmx->get_pes_pids = dvbdmx_get_pes_pids;
dmx->set_tsp_format = dvbdmx_set_tsp_format;
+ dmx->get_tsp_size = dvbdmx_get_tsp_size;
mutex_init(&dvbdemux->mutex);
spin_lock_init(&dvbdemux->lock);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index f3dc4b8..fc04219 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -139,6 +139,8 @@
const u8 *buf, size_t len);
void (*memcopy)(struct dvb_demux_feed *feed, u8 *dst,
const u8 *src, size_t len);
+ int (*oob_command)(struct dvb_demux_feed *feed,
+ struct dmx_oob_command *cmd);
int users;
#define MAX_DVB_DEMUX_USERS 10
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index 32aa4ef..802349a 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -38,6 +38,7 @@
struct camera_v4l2_private {
struct v4l2_fh fh;
unsigned int stream_id;
+ unsigned int is_vb2_valid; /*0 if no vb2 buffers on stream, else 1*/
struct vb2_queue vb2_q;
};
@@ -314,6 +315,7 @@
rc = camera_check_event_status(&event);
if (rc < 0)
goto set_fmt_fail;
+ sp->is_vb2_valid = 1;
}
return rc;
@@ -550,8 +552,8 @@
{
int rc = 0;
struct camera_v4l2_private *sp = fh_to_private(filep->private_data);
-
- rc = vb2_poll(&sp->vb2_q, filep, wait);
+ if (sp->is_vb2_valid == 1)
+ rc = vb2_poll(&sp->vb2_q, filep, wait);
poll_wait(filep, &sp->fh.wait, wait);
if (v4l2_event_pending(&sp->fh))
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index ad8aa82..1b762ea 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -33,7 +33,7 @@
#define MAX_NUM_COMPOSITE_MASK 4
#define MAX_NUM_STATS_COMP_MASK 2
#define MAX_INIT_FRAME_DROP 31
-#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
+#define ISP_Q2 (1 << 2)
#define VFE_PING_FLAG 0xFFFFFFFF
#define VFE_PONG_FLAG 0x0
@@ -183,6 +183,7 @@
struct msm_vfe_hardware_info {
int num_iommu_ctx;
+ int vfe_clk_idx;
struct msm_vfe_ops vfe_ops;
struct msm_vfe_axi_hardware_info *axi_hw_info;
struct msm_vfe_stats_hardware_info *stats_hw_info;
@@ -206,6 +207,7 @@
PAUSE,
START_PENDING,
STOP_PENDING,
+ STARTING,
STOPPING,
PAUSE_PENDING,
};
@@ -246,9 +248,16 @@
uint32_t burst_frame_count;/*number of sof before burst stop*/
uint8_t framedrop_update;
+ /*Bandwidth calculation info*/
+ uint32_t max_width;
+ /*Based on format plane size in Q2. e.g NV12 = 1.5*/
+ uint32_t format_factor;
+ uint32_t bandwidth;
+
/*Run time update variables*/
uint32_t runtime_init_frame_drop;
uint32_t runtime_burst_frame_count;/*number of sof before burst stop*/
+ uint32_t runtime_num_burst_capture;
uint8_t runtime_framedrop_update;
};
@@ -263,6 +272,8 @@
uint8_t pix_stream_count;
uint8_t raw_stream_count;
enum msm_vfe_inputmux input_mux;
+ uint32_t width;
+ long pixel_clock;
};
enum msm_wm_ub_cfg_type {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index b981653..31fa39e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -39,42 +39,7 @@
(VFE32_STATS_BASE(idx) + 0x4 * \
(~(ping_pong >> (idx + VFE32_STATS_PING_PONG_OFFSET)) & 0x1))
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors msm_vfe32_preview_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1027648000,
- .ib = 1105920000,
- },
-};
-
-static struct msm_bus_paths msm_vfe32_bus_client_config[] = {
- {
- ARRAY_SIZE(msm_vfe32_init_vectors),
- msm_vfe32_init_vectors,
- },
- {
- ARRAY_SIZE(msm_vfe32_preview_vectors),
- msm_vfe32_preview_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata msm_vfe32_bus_client_pdata = {
- msm_vfe32_bus_client_config,
- ARRAY_SIZE(msm_vfe32_bus_client_config),
- .name = "msm_camera_vfe",
-};
-
+#define VFE32_CLK_IDX 0
static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
{"vfe_clk", 266667000},
{"vfe_pclk", -1},
@@ -84,15 +49,11 @@
static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
{
int rc = -1;
-
- vfe_dev->bus_perf_client =
- msm_bus_scale_register_client(&msm_vfe32_bus_client_pdata);
- if (!vfe_dev->bus_perf_client) {
- pr_err("%s: Registration Failed!\n", __func__);
- vfe_dev->bus_perf_client = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
goto bus_scale_register_failed;
}
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 1);
if (vfe_dev->fs_vfe) {
rc = regulator_enable(vfe_dev->fs_vfe);
@@ -131,8 +92,7 @@
clk_enable_failed:
regulator_disable(vfe_dev->fs_vfe);
fs_failed:
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
bus_scale_register_failed:
return rc;
}
@@ -145,8 +105,7 @@
msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
regulator_disable(vfe_dev->fs_vfe);
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
}
static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1021,6 +980,7 @@
struct msm_vfe_hardware_info vfe32_hw_info = {
.num_iommu_ctx = 2,
+ .vfe_clk_idx = VFE32_CLK_IDX,
.vfe_ops = {
.irq_ops = {
.read_irq_status = msm_vfe32_read_irq_status,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index a786750..256d136 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -77,42 +77,7 @@
#define VFE40_BUS_BDG_QOS_CFG_6 0x000002DC
#define VFE40_BUS_BDG_QOS_CFG_7 0x000002E0
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors msm_vfe40_preview_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 2027648000U,
- .ib = 2805920000U,
- },
-};
-
-static struct msm_bus_paths msm_vfe40_bus_client_config[] = {
- {
- ARRAY_SIZE(msm_vfe40_init_vectors),
- msm_vfe40_init_vectors,
- },
- {
- ARRAY_SIZE(msm_vfe40_preview_vectors),
- msm_vfe40_preview_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata msm_vfe40_bus_client_pdata = {
- msm_vfe40_bus_client_config,
- ARRAY_SIZE(msm_vfe40_bus_client_config),
- .name = "msm_camera_vfe",
-};
-
+#define VFE40_CLK_IDX 1
static struct msm_cam_clk_info msm_vfe40_clk_info[] = {
{"camss_top_ahb_clk", -1},
{"vfe_clk_src", 266670000},
@@ -223,16 +188,11 @@
static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
{
int rc = -1;
-
- vfe_dev->bus_perf_client =
- msm_bus_scale_register_client(&msm_vfe40_bus_client_pdata);
- if (!vfe_dev->bus_perf_client) {
- pr_err("%s: Registration Failed!\n", __func__);
- vfe_dev->bus_perf_client = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
goto bus_scale_register_failed;
}
- msm_bus_scale_client_update_request(
- vfe_dev->bus_perf_client, 1);
if (vfe_dev->fs_vfe) {
rc = regulator_enable(vfe_dev->fs_vfe);
@@ -280,8 +240,7 @@
clk_enable_failed:
regulator_disable(vfe_dev->fs_vfe);
fs_failed:
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
bus_scale_register_failed:
return rc;
}
@@ -295,8 +254,7 @@
msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
regulator_disable(vfe_dev->fs_vfe);
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
}
static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1288,6 +1246,7 @@
struct msm_vfe_hardware_info vfe40_hw_info = {
.num_iommu_ctx = 1,
+ .vfe_clk_idx = VFE40_CLK_IDX,
.vfe_ops = {
.irq_ops = {
.read_irq_status = msm_vfe40_read_irq_status,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index f1bfd68..477985d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -18,6 +18,8 @@
((src < RDI_INTF_0) ? VFE_PIX_0 : \
(VFE_RAW_0 + src - RDI_INTF_0))
+#define HANDLE_TO_IDX(handle) (handle & 0xFF)
+
int msm_isp_axi_create_stream(
struct msm_vfe_axi_shared_data *axi_data,
struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -67,7 +69,7 @@
int rc = -1, i;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
switch (stream_cfg_cmd->output_format) {
case V4L2_PIX_FMT_SBGGR8:
@@ -95,12 +97,14 @@
case V4L2_PIX_FMT_QGRBG12:
case V4L2_PIX_FMT_QRGGB12:
stream_info->num_planes = 1;
+ stream_info->format_factor = ISP_Q2;
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
stream_info->num_planes = 2;
+ stream_info->format_factor = 1.5 * ISP_Q2;
break;
/*TD: Add more image format*/
default:
@@ -131,9 +135,12 @@
return rc;
}
- for (i = 0; i < stream_info->num_planes; i++)
+ for (i = 0; i < stream_info->num_planes; i++) {
stream_info->plane_offset[i] =
stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+ stream_info->max_width = max(stream_info->max_width,
+ stream_cfg_cmd->plane_cfg[i].output_width);
+ }
stream_info->stream_src = stream_cfg_cmd->stream_src;
stream_info->frame_based = stream_cfg_cmd->frame_base;
@@ -209,7 +216,7 @@
int i, j;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
for (i = 0; i < stream_info->num_planes; i++) {
for (j = 0; j < axi_data->hw_info->num_wm; j++) {
@@ -245,7 +252,7 @@
uint8_t comp_mask = 0;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
for (i = 0; i < stream_info->num_planes; i++)
comp_mask |= 1 << stream_info->wm[i];
@@ -285,7 +292,7 @@
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
stream_info = &axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
if (stream_info->state != valid_state) {
pr_err("%s: Invalid stream state\n", __func__);
rc = -EINVAL;
@@ -344,6 +351,8 @@
stream_info->runtime_init_frame_drop = stream_info->init_frame_drop;
stream_info->runtime_burst_frame_count =
stream_info->burst_frame_count;
+ stream_info->runtime_num_burst_capture =
+ stream_info->num_burst_capture;
stream_info->runtime_framedrop_update = stream_info->framedrop_update;
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(vfe_dev, stream_info);
}
@@ -411,7 +420,7 @@
{
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
uint32_t framedrop_period = msm_isp_get_framedrop_period(
stream_cfg_cmd->frame_skip_pattern);
@@ -443,6 +452,23 @@
}
}
+void msm_isp_calculate_bandwidth(
+ struct msm_vfe_axi_shared_data *axi_data,
+ struct msm_vfe_axi_stream *stream_info)
+{
+ if (stream_info->stream_src < RDI_INTF_0) {
+ stream_info->bandwidth =
+ (axi_data->src_info[VFE_PIX_0].pixel_clock /
+ axi_data->src_info[VFE_PIX_0].width) *
+ stream_info->max_width;
+ stream_info->bandwidth = stream_info->bandwidth *
+ stream_info->format_factor / ISP_Q2;
+ } else {
+ int rdi = SRC_TO_INTF(stream_info->stream_src);
+ stream_info->bandwidth = axi_data->src_info[rdi].pixel_clock;
+ }
+}
+
int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0, i;
@@ -461,13 +487,12 @@
if (rc) {
pr_err("%s: Request validation failed\n", __func__);
msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
- (stream_cfg_cmd->axi_stream_handle & 0xFF));
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle));
return rc;
}
- stream_info =
- &vfe_dev->axi_data.
- stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ stream_info = &vfe_dev->axi_data.
+ stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
@@ -504,7 +529,7 @@
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_release_cmd->stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_release_cmd->stream_handle)];
struct msm_vfe_axi_stream_cfg_cmd stream_cfg;
if (stream_info->state == AVALIABLE) {
@@ -538,79 +563,70 @@
msm_isp_axi_free_wm(axi_data, stream_info);
msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
- (stream_release_cmd->stream_handle & 0xFF));
+ HANDLE_TO_IDX(stream_release_cmd->stream_handle));
return rc;
}
-void msm_isp_axi_stream_enable_cfg(
+static void msm_isp_axi_stream_enable_cfg(
struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info,
- uint32_t *wm_reload_mask)
+ struct msm_vfe_axi_stream *stream_info)
{
int i;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
if (stream_info->state == INACTIVE)
return;
for (i = 0; i < stream_info->num_planes; i++) {
- /*TD: Frame base command*/
if (stream_info->state == START_PENDING)
vfe_dev->hw_info->vfe_ops.axi_ops.
enable_wm(vfe_dev, stream_info->wm[i], 1);
else
vfe_dev->hw_info->vfe_ops.axi_ops.
enable_wm(vfe_dev, stream_info->wm[i], 0);
-
- *wm_reload_mask |= (1 << stream_info->wm[i]);
}
- if (stream_info->state == START_PENDING) {
+ if (stream_info->state == START_PENDING)
axi_data->num_active_stream++;
- stream_info->state = ACTIVE;
- } else {
+ else
axi_data->num_active_stream--;
- stream_info->state = INACTIVE;
- }
}
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev)
{
int i;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
- uint32_t wm_reload_mask = 0x0;
for (i = 0; i < MAX_NUM_STREAM; i++) {
if (axi_data->stream_info[i].state == START_PENDING ||
axi_data->stream_info[i].state ==
STOP_PENDING) {
msm_isp_axi_stream_enable_cfg(
- vfe_dev, &axi_data->stream_info[i],
- &wm_reload_mask);
- if (axi_data->stream_info[i].state == STOP_PENDING)
- axi_data->stream_info[i].state = STOPPING;
+ vfe_dev, &axi_data->stream_info[i]);
+ axi_data->stream_info[i].state =
+ axi_data->stream_info[i].state ==
+ START_PENDING ? STARTING : STOPPING;
+ } else if (axi_data->stream_info[i].state == STARTING ||
+ axi_data->stream_info[i].state == STOPPING) {
+ axi_data->stream_info[i].state =
+ axi_data->stream_info[i].state == STARTING ?
+ ACTIVE : INACTIVE;
}
}
- /*Reload AXI*/
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
- if (vfe_dev->axi_data.stream_update) {
- vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
- ISP_DBG("%s: send update complete\n", __func__);
- vfe_dev->axi_data.stream_update = 0;
+ vfe_dev->axi_data.stream_update--;
+ if (vfe_dev->axi_data.stream_update == 0)
complete(&vfe_dev->stream_config_complete);
- }
}
static void msm_isp_cfg_pong_address(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info)
{
int i;
- struct msm_isp_buffer *buf = stream_info->buf[1];
+ struct msm_isp_buffer *buf = stream_info->buf[0];
for (i = 0; i < stream_info->num_planes; i++)
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
vfe_dev, stream_info->wm[i],
- VFE_PING_FLAG, buf->mapped_info[i].paddr +
+ VFE_PONG_FLAG, buf->mapped_info[i].paddr +
stream_info->plane_offset[i]);
- stream_info->buf[0] = buf;
+ stream_info->buf[1] = buf;
}
static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
@@ -636,7 +652,7 @@
struct msm_isp_buffer *buf = NULL;
uint32_t pingpong_bit = 0;
uint32_t bufq_handle = stream_info->bufq_handle;
- uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+ uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
vfe_dev->pdev->id, bufq_handle, &buf);
@@ -673,7 +689,7 @@
{
int rc;
struct msm_isp_event_data buf_event;
- uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+ uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
uint32_t frame_id = vfe_dev->axi_data.
src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id;
@@ -724,7 +740,7 @@
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
if (stream_info->stream_src < RDI_INTF_0)
pix_stream_cnt++;
if (stream_info->stream_src == PIX_ENCODER ||
@@ -793,16 +809,193 @@
ISP_DBG("%s\n", line_str);
}
-int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+/*Factor in Q2 format*/
+#define ISP_DEFAULT_FORMAT_FACTOR 6
+#define ISP_BUS_UTILIZATION_FACTOR 6
+static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
{
- int rc = 0, i;
- struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+ int i, rc = 0;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ uint32_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
+ uint32_t num_pix_streams = 0;
+ uint64_t total_bandwidth = 0;
+
+ for (i = 0; i < MAX_NUM_STREAM; i++) {
+ stream_info = &axi_data->stream_info[i];
+ if (stream_info->state == ACTIVE ||
+ stream_info->state == START_PENDING) {
+ if (stream_info->stream_src < RDI_INTF_0) {
+ total_pix_bandwidth += stream_info->bandwidth;
+ num_pix_streams++;
+ } else {
+ total_rdi_bandwidth += stream_info->bandwidth;
+ }
+ }
+ }
+ if (num_pix_streams > 0)
+ total_pix_bandwidth = total_pix_bandwidth /
+ num_pix_streams * (num_pix_streams - 1) +
+ axi_data->src_info[VFE_PIX_0].pixel_clock *
+ ISP_DEFAULT_FORMAT_FACTOR / ISP_Q2;
+ total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
+
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ total_bandwidth, total_bandwidth *
+ ISP_BUS_UTILIZATION_FACTOR / ISP_Q2);
+ if (rc < 0)
+ pr_err("%s: update failed\n", __func__);
+
+ return rc;
+}
+
+static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev)
+{
+ int rc;
+ unsigned long flags;
+ spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
+ init_completion(&vfe_dev->stream_config_complete);
+ vfe_dev->axi_data.stream_update = 2;
+ spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
+ rc = wait_for_completion_interruptible_timeout(
+ &vfe_dev->stream_config_complete,
+ msecs_to_jiffies(500));
+ if (rc == 0) {
+ pr_err("%s: wait timeout\n", __func__);
+ rc = -1;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+static int msm_isp_init_stream_ping_pong_reg(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info)
+{
+ int rc = 0;
+ /*Set address for both PING & PONG register */
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, VFE_PING_FLAG);
+ if (rc < 0) {
+ pr_err("%s: No free buffer for ping\n",
+ __func__);
+ return rc;
+ }
+
+ /* For burst stream of one capture, only one buffer
+ * is allocated. Duplicate ping buffer address to pong
+ * buffer to ensure hardware write to a valid address
+ */
+ if (stream_info->stream_type == BURST_STREAM &&
+ stream_info->runtime_num_burst_capture <= 1) {
+ msm_isp_cfg_pong_address(vfe_dev, stream_info);
+ } else {
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, VFE_PONG_FLAG);
+ if (rc < 0) {
+ pr_err("%s: No free buffer for pong\n",
+ __func__);
+ return rc;
+ }
+ }
+ return rc;
+}
+
+static void msm_isp_get_stream_wm_mask(
+ struct msm_vfe_axi_stream *stream_info,
+ uint32_t *wm_reload_mask)
+{
+ int i;
+ for (i = 0; i < stream_info->num_planes; i++)
+ *wm_reload_mask |= (1 << stream_info->wm[i]);
+}
+
+static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+ enum msm_isp_camif_update_state camif_update)
+{
+ int i, rc = 0;
+ uint8_t src_state, wait_for_complete = 0;
uint32_t wm_reload_mask = 0x0;
struct msm_vfe_axi_stream *stream_info;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
- uint8_t src_state;
+ for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+ stream_info = &axi_data->stream_info[
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+ src_state = axi_data->src_info[
+ SRC_TO_INTF(stream_info->stream_src)].active;
+
+ msm_isp_calculate_bandwidth(axi_data, stream_info);
+ msm_isp_reset_framedrop(vfe_dev, stream_info);
+ msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask);
+ rc = msm_isp_init_stream_ping_pong_reg(vfe_dev, stream_info);
+ if (rc < 0) {
+ pr_err("%s: No buffer for stream%d\n", __func__,
+ HANDLE_TO_IDX(
+ stream_cfg_cmd->stream_handle[i]));
+ return rc;
+ }
+
+ stream_info->state = START_PENDING;
+ if (src_state) {
+ wait_for_complete = 1;
+ } else {
+ if (vfe_dev->dump_reg)
+ msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
+
+ /*Configure AXI start bits to start immediately*/
+ msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+ stream_info->state = ACTIVE;
+ }
+ }
+ msm_isp_update_stream_bandwidth(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask);
+ vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
+
+ if (camif_update == ENABLE_CAMIF)
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, camif_update);
+
+ if (wait_for_complete)
+ rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+
+ return rc;
+}
+
+static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+ enum msm_isp_camif_update_state camif_update)
+{
+ int i, rc = 0;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+ stream_info = &axi_data->stream_info[
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+ stream_info->state = STOP_PENDING;
+ }
+
+ rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+ if (rc < 0) {
+ pr_err("%s: wait for config done failed\n", __func__);
+ return rc;
+ }
+ msm_isp_update_stream_bandwidth(vfe_dev);
+ if (camif_update == DISABLE_CAMIF)
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, DISABLE_CAMIF);
+ return rc;
+}
+
+
+int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+ int rc = 0;
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
enum msm_isp_camif_update_state camif_update;
- uint8_t wait_for_complete = 0;
+
rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
if (rc < 0) {
pr_err("%s: Invalid stream state\n", __func__);
@@ -813,104 +1006,18 @@
/*Configure UB*/
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
}
-
camif_update =
msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
- if (camif_update == DISABLE_CAMIF)
- vfe_dev->hw_info->vfe_ops.core_ops.
- update_camif_state(vfe_dev, DISABLE_CAMIF);
+ if (stream_cfg_cmd->cmd == START_STREAM)
+ rc = msm_isp_start_axi_stream(
+ vfe_dev, stream_cfg_cmd, camif_update);
+ else
+ rc = msm_isp_stop_axi_stream(
+ vfe_dev, stream_cfg_cmd, camif_update);
- /*
- * Stream start either immediately or at reg update
- * Depends on whether the stream src is active
- * If source is on, start and stop have to be done during reg update
- * If source is off, start can happen immediately or during reg update
- * stop has to be done immediately.
- */
- for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
- stream_info =
- &axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
-
- if (stream_info->stream_src < RDI_INTF_0)
- src_state = axi_data->src_info[0].active;
- else
- src_state = axi_data->src_info[
- (stream_info->stream_src - RDI_INTF_0)].active;
-
- stream_info->state = (stream_cfg_cmd->cmd == START_STREAM) ?
- START_PENDING : STOP_PENDING;
-
- if (stream_cfg_cmd->cmd == START_STREAM) {
- /*Configure framedrop*/
- msm_isp_reset_framedrop(vfe_dev, stream_info);
-
- /*Set address for both PING & PONG register */
- rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PONG_FLAG);
- if (rc < 0) {
- pr_err("%s: No buffer for start stream\n",
- __func__);
- return rc;
- }
- /* For burst stream of one capture, only one buffer
- * is allocated. Duplicate ping buffer address to pong
- * buffer to ensure hardware write to a valid address
- */
- if (stream_info->stream_type == BURST_STREAM &&
- stream_info->num_burst_capture <= 1) {
- msm_isp_cfg_pong_address(vfe_dev, stream_info);
- } else {
- rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PING_FLAG);
- }
- }
- if (src_state && camif_update != DISABLE_CAMIF) {
- /*On the fly stream start/stop */
- wait_for_complete = 1;
- } else {
- if (vfe_dev->dump_reg &&
- stream_cfg_cmd->cmd == START_STREAM)
- msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
- /*Configure AXI start bits to start immediately*/
- msm_isp_axi_stream_enable_cfg(
- vfe_dev, stream_info, &wm_reload_mask);
- }
- }
- if (!wait_for_complete) {
- /*Reload AXI*/
- if (stream_cfg_cmd->cmd == START_STREAM)
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
-
- vfe_dev->hw_info->vfe_ops.core_ops.
- reg_update(vfe_dev);
-
- if (camif_update == ENABLE_CAMIF)
- vfe_dev->hw_info->vfe_ops.core_ops.
- update_camif_state(vfe_dev, camif_update);
- } else {
- unsigned long flags;
- spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
- init_completion(&vfe_dev->stream_config_complete);
- axi_data->stream_update = 1;
- spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
- /*Reload AXI*/
- if (stream_cfg_cmd->cmd == START_STREAM)
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
- vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
- rc = wait_for_completion_interruptible_timeout(
- &vfe_dev->stream_config_complete,
- msecs_to_jiffies(500));
- if (rc == 0) {
- pr_err("%s: wait timeout\n", __func__);
- rc = -1;
- } else {
- rc = 0;
- }
- }
+ if (rc < 0)
+ pr_err("%s: start/stop stream failed\n", __func__);
return rc;
}
@@ -921,7 +1028,7 @@
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
stream_info = &axi_data->stream_info[
- (update_cmd->stream_handle & 0xFF)];
+ HANDLE_TO_IDX(update_cmd->stream_handle)];
if (stream_info->state != ACTIVE && stream_info->state != INACTIVE) {
pr_err("%s: Invalid stream state\n", __func__);
return -EINVAL;
@@ -984,18 +1091,25 @@
pr_err("%s: Invalid handle for composite irq\n",
__func__);
} else {
- stream_idx = comp_info->stream_handle & 0xFF;
+ stream_idx =
+ HANDLE_TO_IDX(comp_info->stream_handle);
stream_info =
&axi_data->stream_info[stream_idx];
ISP_DBG("%s: stream%d frame id: 0x%x\n",
__func__,
stream_idx, stream_info->frame_id);
stream_info->frame_id++;
+
+ if (stream_info->stream_type == BURST_STREAM)
+ stream_info->
+ runtime_num_burst_capture--;
+
msm_isp_get_done_buf(vfe_dev, stream_info,
pingpong_status, &done_buf);
if (stream_info->stream_type ==
CONTINUOUS_STREAM ||
- stream_info->num_burst_capture > 1) {
+ stream_info->
+ runtime_num_burst_capture > 1) {
rc = msm_isp_cfg_ping_pong_address(
vfe_dev, stream_info,
pingpong_status);
@@ -1015,16 +1129,20 @@
__func__);
continue;
}
- stream_idx = axi_data->free_wm[i] & 0xFF;
+ stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]);
stream_info = &axi_data->stream_info[stream_idx];
ISP_DBG("%s: stream%d frame id: 0x%x\n",
__func__,
stream_idx, stream_info->frame_id);
stream_info->frame_id++;
+
+ if (stream_info->stream_type == BURST_STREAM)
+ stream_info->runtime_num_burst_capture--;
+
msm_isp_get_done_buf(vfe_dev, stream_info,
pingpong_status, &done_buf);
if (stream_info->stream_type == CONTINUOUS_STREAM ||
- stream_info->num_burst_capture > 1) {
+ stream_info->runtime_num_burst_capture > 1) {
rc = msm_isp_cfg_ping_pong_address(vfe_dev,
stream_info, pingpong_status);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index ba845bc..f592a60 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -46,10 +46,6 @@
int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg);
-void msm_isp_axi_stream_enable_cfg(struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info,
- uint32_t *wm_reload_mask);
-
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev);
void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 3035d93..9fd87f3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -9,6 +9,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <linux/mutex.h>
#include <linux/io.h>
#include <media/v4l2-subdev.h>
@@ -19,6 +20,139 @@
#include "msm_camera_io_util.h"
#define MAX_ISP_V4l2_EVENTS 100
+static DEFINE_MUTEX(bandwidth_mgr_mutex);
+static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
+
+#define MSM_ISP_MIN_AB 300000000
+#define MSM_ISP_MIN_IB 450000000
+
+static struct msm_bus_vectors msm_isp_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors msm_isp_ping_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = MSM_ISP_MIN_AB,
+ .ib = MSM_ISP_MIN_IB,
+ },
+};
+
+static struct msm_bus_vectors msm_isp_pong_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = MSM_ISP_MIN_AB,
+ .ib = MSM_ISP_MIN_IB,
+ },
+};
+
+static struct msm_bus_paths msm_isp_bus_client_config[] = {
+ {
+ ARRAY_SIZE(msm_isp_init_vectors),
+ msm_isp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(msm_isp_ping_vectors),
+ msm_isp_ping_vectors,
+ },
+ {
+ ARRAY_SIZE(msm_isp_pong_vectors),
+ msm_isp_pong_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata msm_isp_bus_client_pdata = {
+ msm_isp_bus_client_config,
+ ARRAY_SIZE(msm_isp_bus_client_config),
+ .name = "msm_camera_isp",
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+ int rc = 0;
+ mutex_lock(&bandwidth_mgr_mutex);
+ isp_bandwidth_mgr.client_info[client].active = 1;
+ if (isp_bandwidth_mgr.use_count++) {
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return rc;
+ }
+ isp_bandwidth_mgr.bus_client =
+ msm_bus_scale_register_client(&msm_isp_bus_client_pdata);
+ if (!isp_bandwidth_mgr.bus_client) {
+ pr_err("%s: client register failed\n", __func__);
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return -EINVAL;
+ }
+
+ isp_bandwidth_mgr.bus_vector_active_idx = 1;
+ msm_bus_scale_client_update_request(
+ isp_bandwidth_mgr.bus_client,
+ isp_bandwidth_mgr.bus_vector_active_idx);
+
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return 0;
+}
+
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+ uint64_t ab, uint64_t ib)
+{
+ int i;
+ struct msm_bus_paths *path;
+ mutex_lock(&bandwidth_mgr_mutex);
+ if (!isp_bandwidth_mgr.use_count ||
+ !isp_bandwidth_mgr.bus_client) {
+ pr_err("%s: bandwidth manager inactive\n", __func__);
+ return -EINVAL;
+ }
+
+ isp_bandwidth_mgr.client_info[client].ab = ab;
+ isp_bandwidth_mgr.client_info[client].ib = ib;
+ ALT_VECTOR_IDX(isp_bandwidth_mgr.bus_vector_active_idx);
+ path =
+ &(msm_isp_bus_client_pdata.usecase[
+ isp_bandwidth_mgr.bus_vector_active_idx]);
+ path->vectors[0].ab = MSM_ISP_MIN_AB;
+ path->vectors[0].ib = MSM_ISP_MIN_IB;
+ for (i = 0; i < MAX_ISP_CLIENT; i++) {
+ if (isp_bandwidth_mgr.client_info[client].active) {
+ path->vectors[0].ab +=
+ isp_bandwidth_mgr.client_info[i].ab;
+ path->vectors[0].ib +=
+ isp_bandwidth_mgr.client_info[i].ib;
+ }
+ }
+ msm_bus_scale_client_update_request(isp_bandwidth_mgr.bus_client,
+ isp_bandwidth_mgr.bus_vector_active_idx);
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return 0;
+}
+
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+ mutex_lock(&bandwidth_mgr_mutex);
+ memset(&isp_bandwidth_mgr.client_info[client], 0,
+ sizeof(struct msm_isp_bandwidth_info));
+ if (--isp_bandwidth_mgr.use_count) {
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return;
+ }
+
+ if (!isp_bandwidth_mgr.bus_client)
+ return;
+
+ msm_bus_scale_client_update_request(
+ isp_bandwidth_mgr.bus_client, 0);
+ msm_bus_scale_unregister_client(isp_bandwidth_mgr.bus_client);
+ isp_bandwidth_mgr.bus_client = 0;
+ mutex_unlock(&bandwidth_mgr_mutex);
+}
static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
{
@@ -68,28 +202,67 @@
return rc;
}
-int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
- struct msm_vfe_pix_cfg *pix_cfg)
+static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, uint32_t rate)
{
int rc = 0;
- /*TD Validate config info
- * should check if all streams are off */
+ int clk_idx = vfe_dev->hw_info->vfe_clk_idx;
+ long round_rate =
+ clk_round_rate(vfe_dev->vfe_clk[clk_idx], rate);
+ if (round_rate < 0) {
+ pr_err("%s: Invalid vfe clock rate\n", __func__);
+ return round_rate;
+ }
- vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux = pix_cfg->input_mux;
+ rc = clk_set_rate(vfe_dev->vfe_clk[clk_idx], round_rate);
+ if (rc < 0) {
+ pr_err("%s: Vfe set rate error\n", __func__);
+ return rc;
+ }
+ return 0;
+}
- vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(vfe_dev, pix_cfg);
+int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
+ struct msm_vfe_input_cfg *input_cfg)
+{
+ int rc = 0;
+ if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) {
+ pr_err("%s: pixel path is active\n", __func__);
+ return -EINVAL;
+ }
+
+ vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock =
+ input_cfg->input_pix_clk;
+ vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux =
+ input_cfg->d.pix_cfg.input_mux;
+ vfe_dev->axi_data.src_info[VFE_PIX_0].width =
+ input_cfg->d.pix_cfg.camif_cfg.pixels_per_line;
+
+ rc = msm_isp_set_clk_rate(vfe_dev,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
+ if (rc < 0) {
+ pr_err("%s: clock set rate failed\n", __func__);
+ return rc;
+ }
+
+ vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(
+ vfe_dev, &input_cfg->d.pix_cfg);
return rc;
}
int msm_isp_cfg_rdi(struct vfe_device *vfe_dev,
- struct msm_vfe_rdi_cfg *rdi_cfg, enum msm_vfe_input_src input_src)
+ struct msm_vfe_input_cfg *input_cfg)
{
int rc = 0;
- /*TD Validate config info
- * should check if all streams are off */
+ if (vfe_dev->axi_data.src_info[input_cfg->input_src].active) {
+ pr_err("%s: RAW%d path is active\n", __func__,
+ input_cfg->input_src - VFE_RAW_0);
+ return -EINVAL;
+ }
- vfe_dev->hw_info->vfe_ops.core_ops.
- cfg_rdi_reg(vfe_dev, rdi_cfg, input_src);
+ vfe_dev->axi_data.src_info[input_cfg->input_src].pixel_clock =
+ input_cfg->input_pix_clk;
+ vfe_dev->hw_info->vfe_ops.core_ops.cfg_rdi_reg(
+ vfe_dev, &input_cfg->d.rdi_cfg, input_cfg->input_src);
return rc;
}
@@ -100,16 +273,16 @@
switch (input_cfg->input_src) {
case VFE_PIX_0:
- msm_isp_cfg_pix(vfe_dev, &input_cfg->d.pix_cfg);
+ rc = msm_isp_cfg_pix(vfe_dev, input_cfg);
break;
case VFE_RAW_0:
case VFE_RAW_1:
case VFE_RAW_2:
- msm_isp_cfg_rdi(vfe_dev, &input_cfg->d.rdi_cfg,
- input_cfg->input_src);
+ rc = msm_isp_cfg_rdi(vfe_dev, input_cfg);
break;
- case VFE_SRC_MAX:
- break;
+ default:
+ pr_err("%s: Invalid input source\n", __func__);
+ rc = -EINVAL;
}
return rc;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 3dac7e0..7934f26 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -22,6 +22,32 @@
#define ISP_DBG(fmt, args...) pr_debug(fmt, ##args)
#endif
+#define ALT_VECTOR_IDX(x) {x = 3 - x; }
+struct msm_isp_bandwidth_info {
+ uint32_t active;
+ uint64_t ab;
+ uint64_t ib;
+};
+
+enum msm_isp_hw_client {
+ ISP_VFE0,
+ ISP_VFE1,
+ ISP_CPP,
+ MAX_ISP_CLIENT,
+};
+
+struct msm_isp_bandwidth_mgr {
+ uint32_t bus_client;
+ uint32_t bus_vector_active_idx;
+ uint32_t use_count;
+ struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client);
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+ uint64_t ab, uint64_t ib);
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client);
+
int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index d30afb2..f209330 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -380,6 +380,8 @@
data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
data |= (1 << (intftype + 7));
+ if (intftype == PIX0)
+ data |= 1 << PIX0_LINE_BUF_EN_BIT;
msm_camera_io_w(data,
ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index afd91d1..9f8b2fa 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -16,6 +16,7 @@
/* common registers */
#define ISPIF_RST_CMD_ADDR 0x0000
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x0124
+#define PIX0_LINE_BUF_EN_BIT 0
#define ISPIF_VFE(m) (0x0)
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 80b32d4..5e61a4d 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -17,6 +17,7 @@
#define ISPIF_RST_CMD_ADDR 0x008
#define ISPIF_RST_CMD_1_ADDR 0x00C
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x01C
+#define PIX0_LINE_BUF_EN_BIT 6
#define ISPIF_VFE(m) ((m) * 0x200)
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index e50ac3a..56ec259 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -90,6 +90,7 @@
/* 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;
@@ -393,6 +394,7 @@
msm_init_queue(&session->command_ack_q);
msm_init_queue(&session->stream_q);
msm_enqueue(msm_session_q, &session->list);
+ mutex_init(&session->lock);
return 0;
}
@@ -408,10 +410,12 @@
list, __msm_queue_find_session, &session_id);
if (!session)
return -EINVAL;
-
+ mutex_lock(&session->lock);
cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
- if (!cmd_ack)
+ if (!cmd_ack) {
+ mutex_unlock(&session->lock);
return -ENOMEM;
+ }
msm_init_queue(&cmd_ack->command_q);
INIT_LIST_HEAD(&cmd_ack->list);
@@ -420,7 +424,7 @@
msm_enqueue(&session->command_ack_q, &cmd_ack->list);
session->command_ack_q.len++;
-
+ mutex_unlock(&session->lock);
return 0;
}
@@ -543,7 +547,7 @@
msm_destroy_session_streams(session);
msm_remove_session_cmd_ack_q(session);
-
+ mutex_destroy(&session->lock);
msm_delete_entry(msm_session_q, struct msm_session,
list, session);
@@ -683,33 +687,43 @@
list, __msm_queue_find_session, &session_id);
if (WARN_ON(!session))
return -EIO;
-
+ mutex_lock(&session->lock);
cmd_ack = msm_queue_find(&session->command_ack_q,
struct msm_command_ack, list,
__msm_queue_find_command_ack_q, &stream_id);
- if (WARN_ON(!cmd_ack))
+ if (WARN_ON(!cmd_ack)) {
+ mutex_unlock(&session->lock);
return -EIO;
+ }
v4l2_event_queue(vdev, event);
- if (timeout < 0)
+ if (timeout < 0) {
+ mutex_unlock(&session->lock);
return rc;
+ }
/* should wait on session based condition */
rc = wait_event_interruptible_timeout(cmd_ack->wait,
!list_empty_careful(&cmd_ack->command_q.list),
msecs_to_jiffies(timeout));
if (list_empty_careful(&cmd_ack->command_q.list)) {
- if (!rc)
+ if (!rc) {
+ pr_err("%s: Ankit Timed out\n", __func__);
rc = -ETIMEDOUT;
- if (rc < 0)
+ }
+ if (rc < 0) {
+ mutex_unlock(&session->lock);
return rc;
+ }
}
cmd = msm_dequeue(&cmd_ack->command_q,
struct msm_command, list);
- if (!cmd)
+ if (!cmd) {
+ mutex_unlock(&session->lock);
return -EINVAL;
+ }
event_data = (struct msm_v4l2_event_data *)cmd->event.u.data;
@@ -721,6 +735,7 @@
*event = cmd->event;
kzfree(cmd);
+ mutex_unlock(&session->lock);
return rc;
}
@@ -730,7 +745,7 @@
struct msm_v4l2_event_data *event_data =
(struct msm_v4l2_event_data *)&event.u.data[0];
struct msm_session *session = d1;
-
+ mutex_lock(&session->lock);
event.type = MSM_CAMERA_V4L2_EVENT_TYPE;
event.id = MSM_CAMERA_MSM_NOTIFY;
event_data->command = MSM_CAMERA_PRIV_SHUTDOWN;
@@ -739,7 +754,7 @@
msm_destroy_session_streams(session);
msm_remove_session_cmd_ack_q(session);
-
+ mutex_unlock(&session->lock);
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
index 2f969d2..c793ef6 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
@@ -1,3 +1,4 @@
ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/isp/
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
obj-$(CONFIG_MSM_CPP) += msm_cpp.o
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 2598b07..1203d17 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -34,6 +34,7 @@
#include <media/msmb_pproc.h>
#include <media/msmb_generic_buf_mgr.h>
#include "msm_cpp.h"
+#include "msm_isp_util.h"
#include "msm_camera_io_util.h"
#define MSM_CPP_DRV_NAME "msm_cpp"
@@ -582,6 +583,12 @@
static int cpp_init_hardware(struct cpp_device *cpp_dev)
{
int rc = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_CPP);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
+ goto bus_scale_register_failed;
+ }
+ msm_isp_update_bandwidth(ISP_CPP, 981345600, 1600020000);
if (cpp_dev->fs_cpp == NULL) {
cpp_dev->fs_cpp =
@@ -667,6 +674,9 @@
regulator_disable(cpp_dev->fs_cpp);
regulator_put(cpp_dev->fs_cpp);
fs_failed:
+ msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+ msm_isp_deinit_bandwidth_mgr(ISP_CPP);
+bus_scale_register_failed:
return rc;
}
@@ -688,6 +698,8 @@
regulator_put(cpp_dev->fs_cpp);
cpp_dev->fs_cpp = NULL;
}
+ msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+ msm_isp_deinit_bandwidth_mgr(ISP_CPP);
}
static void cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
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 6775a23..4e36e61 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
@@ -907,6 +907,7 @@
mpq_demux->num_active_feeds = 0;
mpq_demux->sdmx_filter_count = 0;
mpq_demux->sdmx_session_handle = SDMX_INVALID_SESSION_HANDLE;
+ mpq_demux->sdmx_eos = 0;
if (mpq_demux->demux.feednum > MPQ_MAX_DMX_FILES) {
MPQ_DVB_ERR_PRINT(
@@ -1127,7 +1128,7 @@
goto map_buffer_failed_free_buff;
}
- if (ionflag & ION_SECURE) {
+ if (ionflag & ION_FLAG_SECURE) {
MPQ_DVB_DBG_PRINT("%s: secured buffer\n", __func__);
*kernel_mem = NULL;
} else {
@@ -1207,7 +1208,7 @@
return -EINVAL;
}
- if (!(ionflag & ION_SECURE))
+ if (!(ionflag & ION_FLAG_SECURE))
ion_unmap_kernel(mpq_demux->ion_client, ion_handle);
ion_free(mpq_demux->ion_client, ion_handle);
@@ -2476,6 +2477,174 @@
feed_data->continuity_errs = 0;
}
+static int mpq_sdmx_dvr_buffer_desc(struct mpq_demux *mpq_demux,
+ struct sdmx_buff_descr *buf_desc)
+{
+ struct dvb_ringbuffer *rbuf = (struct dvb_ringbuffer *)
+ mpq_demux->demux.dmx.dvr_input.ringbuff;
+ struct ion_handle *ion_handle =
+ mpq_demux->demux.dmx.dvr_input.priv_handle;
+ ion_phys_addr_t phys_addr;
+ size_t len;
+ int ret;
+
+ ret = ion_phys(mpq_demux->ion_client, ion_handle, &phys_addr, &len);
+ if (ret) {
+ MPQ_DVB_ERR_PRINT(
+ "%s: Failed to obtain physical address of input buffer. ret = %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ buf_desc->base_addr = (void *)phys_addr;
+ buf_desc->size = rbuf->size;
+
+ return 0;
+}
+
+/**
+ * mpq_dmx_decoder_frame_closure - Helper function to handle closing current
+ * pending frame upon reaching EOS.
+ *
+ * @mpq_demux - mpq demux instance
+ * @mpq_feed - mpq feed object
+ */
+static void mpq_dmx_decoder_frame_closure(struct mpq_demux *mpq_demux,
+ struct mpq_feed *mpq_feed)
+{
+ struct mpq_streambuffer_packet_header packet;
+ struct mpq_streambuffer *stream_buffer;
+ struct mpq_adapter_video_meta_data meta_data;
+ struct mpq_video_feed_info *feed_data;
+ struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
+ struct dmx_data_ready data;
+
+ feed_data = &mpq_feed->video_info;
+
+ /*
+ * spin-lock is taken to protect against manipulation of video
+ * output buffer by the API (terminate video feed, re-use of video
+ * buffers).
+ */
+ spin_lock(&feed_data->video_buffer_lock);
+ stream_buffer = feed_data->video_buffer;
+
+ if (stream_buffer == NULL) {
+ MPQ_DVB_ERR_PRINT("%s: video_buffer released\n", __func__);
+ spin_unlock(&feed_data->video_buffer_lock);
+ return;
+ }
+
+ /* Report last pattern found */
+ if ((feed_data->pending_pattern_len) &&
+ mpq_dmx_is_video_frame(feed->indexing_params.standard,
+ feed_data->last_framing_match_type)) {
+ meta_data.packet_type = DMX_FRAMING_INFO_PACKET;
+ mpq_dmx_write_pts_dts(feed_data,
+ &(meta_data.info.framing.pts_dts_info));
+ mpq_dmx_save_pts_dts(feed_data);
+ packet.user_data_len =
+ sizeof(struct mpq_adapter_video_meta_data);
+ packet.raw_data_len = feed_data->pending_pattern_len;
+ packet.raw_data_offset = feed_data->frame_offset;
+ meta_data.info.framing.pattern_type =
+ feed_data->last_framing_match_type;
+
+ mpq_streambuffer_get_buffer_handle(stream_buffer,
+ 0, /* current write buffer handle */
+ &packet.raw_data_handle);
+
+ mpq_dmx_update_decoder_stat(mpq_demux);
+
+ /* Writing meta-data that includes the framing information */
+ if (mpq_streambuffer_pkt_write(stream_buffer, &packet,
+ (u8 *)&meta_data) < 0)
+ MPQ_DVB_ERR_PRINT("%s: Couldn't write packet\n",
+ __func__);
+
+ mpq_dmx_prepare_es_event_data(&packet, &meta_data, feed_data,
+ stream_buffer, &data);
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ }
+
+ spin_unlock(&feed_data->video_buffer_lock);
+}
+
+/**
+ * mpq_dmx_decoder_pes_closure - Helper function to handle closing current PES
+ * upon reaching EOS.
+ *
+ * @mpq_demux - mpq demux instance
+ * @mpq_feed - mpq feed object
+ */
+static void mpq_dmx_decoder_pes_closure(struct mpq_demux *mpq_demux,
+ struct mpq_feed *mpq_feed)
+{
+ struct mpq_streambuffer_packet_header packet;
+ struct mpq_streambuffer *stream_buffer;
+ struct mpq_adapter_video_meta_data meta_data;
+ struct mpq_video_feed_info *feed_data;
+ struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
+ struct dmx_data_ready data;
+
+ feed_data = &mpq_feed->video_info;
+
+ /*
+ * spin-lock is taken to protect against manipulation of video
+ * output buffer by the API (terminate video feed, re-use of video
+ * buffers).
+ */
+ spin_lock(&feed_data->video_buffer_lock);
+ stream_buffer = feed_data->video_buffer;
+
+ if (stream_buffer == NULL) {
+ MPQ_DVB_ERR_PRINT("%s: video_buffer released\n", __func__);
+ spin_unlock(&feed_data->video_buffer_lock);
+ return;
+ }
+
+ /*
+ * Close previous PES.
+ * Push new packet to the meta-data buffer.
+ */
+ if ((feed->pusi_seen) && (0 == feed_data->pes_header_left_bytes)) {
+ packet.raw_data_len = feed->peslen;
+ mpq_streambuffer_get_buffer_handle(stream_buffer,
+ 0, /* current write buffer handle */
+ &packet.raw_data_handle);
+ packet.raw_data_offset = feed_data->frame_offset;
+ packet.user_data_len =
+ sizeof(struct mpq_adapter_video_meta_data);
+
+ mpq_dmx_write_pts_dts(feed_data,
+ &(meta_data.info.pes.pts_dts_info));
+ mpq_dmx_save_pts_dts(feed_data);
+
+ meta_data.packet_type = DMX_PES_PACKET;
+
+ mpq_dmx_update_decoder_stat(mpq_demux);
+
+ if (mpq_streambuffer_pkt_write(stream_buffer, &packet,
+ (u8 *)&meta_data) < 0)
+ MPQ_DVB_ERR_PRINT("%s: Couldn't write packet\n",
+ __func__);
+
+ /* Save write offset where new PES will begin */
+ mpq_streambuffer_get_data_rw_offset(stream_buffer, NULL,
+ &feed_data->frame_offset);
+
+ mpq_dmx_prepare_es_event_data(&packet, &meta_data, feed_data,
+ stream_buffer, &data);
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ }
+ /* Reset PES info */
+ feed->peslen = 0;
+ feed_data->pes_header_offset = 0;
+ feed_data->pes_header_left_bytes = PES_MANDATORY_FIELDS_LEN;
+
+ spin_unlock(&feed_data->video_buffer_lock);
+}
+
static int mpq_dmx_process_video_packet_framing(
struct dvb_demux_feed *feed,
const u8 *buf)
@@ -3234,6 +3403,34 @@
}
EXPORT_SYMBOL(mpq_dmx_process_pcr_packet);
+static int mpq_dmx_decoder_eos_cmd(struct mpq_feed *mpq_feed)
+{
+ struct mpq_video_feed_info *feed_data = &mpq_feed->video_info;
+ struct mpq_streambuffer *stream_buffer;
+ struct mpq_streambuffer_packet_header oob_packet;
+ struct mpq_adapter_video_meta_data oob_meta_data;
+ int ret;
+
+ spin_lock(&feed_data->video_buffer_lock);
+ stream_buffer = feed_data->video_buffer;
+
+ if (stream_buffer == NULL) {
+ MPQ_DVB_ERR_PRINT("%s: video_buffer released\n", __func__);
+ spin_unlock(&feed_data->video_buffer_lock);
+ return 0;
+ }
+
+ memset(&oob_packet, 0, sizeof(oob_packet));
+ oob_packet.user_data_len = sizeof(oob_meta_data);
+ oob_meta_data.packet_type = DMX_EOS_PACKET;
+
+ ret = mpq_streambuffer_pkt_write(stream_buffer, &oob_packet,
+ (u8 *)&oob_meta_data);
+
+ spin_unlock(&feed_data->video_buffer_lock);
+ return ret;
+}
+
int mpq_sdmx_open_session(struct mpq_demux *mpq_demux)
{
enum sdmx_status ret = SDMX_SUCCESS;
@@ -3329,6 +3526,7 @@
__func__, status);
return -EINVAL;
}
+ mpq_demux->sdmx_eos = 0;
mpq_demux->sdmx_session_handle = SDMX_INVALID_SESSION_HANDLE;
}
@@ -4055,6 +4253,12 @@
data_event.data_length = 0;
feed->data_ready_cb.ts(&feed->feed.ts, &data_event);
}
+
+ if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
+ data_event.data_length = 0;
+ data_event.status = DMX_OK_EOS;
+ feed->data_ready_cb.ts(&feed->feed.ts, &data_event);
+ }
}
static void mpq_sdmx_section_filter_results(struct mpq_demux *mpq_demux,
@@ -4080,7 +4284,7 @@
__func__);
if ((!sts->metadata_fill_count) && (!sts->data_fill_count))
- return;
+ goto section_filter_check_eos;
mpq_feed->metadata_buf.pwrite = sts->metadata_write_offset;
mpq_feed->sdmx_buf.pwrite = sts->data_write_offset;
@@ -4101,6 +4305,19 @@
DVB_RINGBUFFER_SKIP(&mpq_feed->sdmx_buf, header.payload_length);
}
+
+section_filter_check_eos:
+ if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
+ event.data_length = 0;
+ event.status = DMX_OK_EOS;
+ f = feed->filter;
+
+ while (f && sec->is_filtering) {
+ feed->data_ready_cb.sec(&f->filter, &event);
+ f = f->next;
+ }
+ }
+
}
static void mpq_sdmx_decoder_filter_results(struct mpq_demux *mpq_demux,
@@ -4122,7 +4339,7 @@
struct dvb_demux_feed *feed = mpq_feed->dvb_demux_feed;
if ((!sts->metadata_fill_count) && (!sts->data_fill_count))
- goto decoder_filter_check_overflow;
+ goto decoder_filter_check_flags;
/* Update meta data buffer write pointer */
mpq_feed->metadata_buf.pwrite = sts->metadata_write_offset;
@@ -4220,7 +4437,8 @@
mpq_feed->video_info.ts_packets_num =
counters.pes_ts_count;
mpq_feed->video_info.ts_dropped_bytes =
- counters.drop_count * mpq_demux->demux.ts_packet_size;
+ counters.drop_count *
+ mpq_demux->demux.ts_packet_size;
sbuf = mpq_feed->video_info.video_buffer;
if (sbuf == NULL) {
@@ -4261,7 +4479,7 @@
spin_unlock(&mpq_feed->video_info.video_buffer_lock);
}
-decoder_filter_check_overflow:
+decoder_filter_check_flags:
if ((mpq_demux->demux.playback_mode == DMX_PB_MODE_PUSH) &&
(sts->error_indicators & SDMX_FILTER_ERR_D_LIN_BUFS_FULL)) {
MPQ_DVB_ERR_PRINT("%s: DMX_OVERRUN_ERROR\n", __func__);
@@ -4270,6 +4488,21 @@
mpq_feed->dvb_demux_feed->data_ready_cb.ts(
&mpq_feed->dvb_demux_feed->feed.ts, &data_event);
}
+
+ if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
+ /* Notify decoder via the stream buffer */
+ ret = mpq_dmx_decoder_eos_cmd(mpq_feed);
+ if (ret)
+ MPQ_DVB_ERR_PRINT(
+ "%s: Failed to notify decoder on EOS, ret=%d\n",
+ __func__, ret);
+
+ /* Notify user filter */
+ data_event.data_length = 0;
+ data_event.status = DMX_OK_EOS;
+ mpq_feed->dvb_demux_feed->data_ready_cb.ts(
+ &mpq_feed->dvb_demux_feed->feed.ts, &data_event);
+ }
}
static void mpq_sdmx_pcr_filter_results(struct mpq_demux *mpq_demux,
@@ -4289,10 +4522,8 @@
MPQ_DVB_ERR_PRINT("%s: internal PCR buffer overflowed!\n",
__func__);
- /* MPQ_TODO: Parse rest of error indicators ? */
-
if ((!sts->metadata_fill_count) && (!sts->data_fill_count))
- return;
+ goto pcr_filter_check_eos;
if (DMX_TSP_FORMAT_192_TAIL == mpq_demux->demux.tsp_format)
stc_len = 4;
@@ -4338,6 +4569,13 @@
feed->data_ready_cb.ts(&feed->feed.ts, &data);
}
}
+
+pcr_filter_check_eos:
+ if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
+ data.data_length = 0;
+ data.status = DMX_OK_EOS;
+ feed->data_ready_cb.ts(&feed->feed.ts, &data);
+ }
}
static void mpq_sdmx_raw_filter_results(struct mpq_demux *mpq_demux,
@@ -4352,7 +4590,7 @@
feed->feed.ts.buffer.ringbuff;
if ((!sts->metadata_fill_count) && (!sts->data_fill_count))
- goto raw_filter_check_overflow;
+ goto raw_filter_check_flags;
new_data = sts->data_write_offset -
buf->pwrite;
@@ -4374,7 +4612,7 @@
MPQ_DVB_DBG_PRINT("%s: Callback DMX_OK, size=%d\n",
__func__, data_event.data_length);
-raw_filter_check_overflow:
+raw_filter_check_flags:
if ((mpq_demux->demux.playback_mode == DMX_PB_MODE_PUSH) &&
(sts->error_indicators & SDMX_FILTER_ERR_D_BUF_FULL)) {
MPQ_DVB_DBG_PRINT("%s: DMX_OVERRUN_ERROR\n", __func__);
@@ -4382,6 +4620,13 @@
data_event.data_length = 0;
feed->data_ready_cb.ts(&feed->feed.ts, &data_event);
}
+
+ if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
+ data_event.data_length = 0;
+ data_event.status = DMX_OK_EOS;
+ feed->data_ready_cb.ts(&feed->feed.ts, &data_event);
+ }
+
}
static void mpq_sdmx_process_results(struct mpq_demux *mpq_demux)
@@ -4457,8 +4702,7 @@
{
struct sdmx_filter_status *sts;
struct mpq_feed *mpq_feed;
- /* MPQ_TODO: EOS handling */
- u8 flags = mpq_sdmx_debug ? SDMX_INPUT_FLAG_DBG_ENABLE : 0;
+ u8 flags = 0;
u32 errors;
u32 status;
u32 prev_read_offset;
@@ -4485,6 +4729,12 @@
return 0;
}
+ /* Set input flags */
+ if (mpq_demux->sdmx_eos)
+ flags |= SDMX_INPUT_FLAG_EOS;
+ if (mpq_sdmx_debug)
+ flags |= SDMX_INPUT_FLAG_DBG_ENABLE;
+
/* Build up to date filter status array */
for (i = 0; i < MPQ_MAX_DMX_FILES; i++) {
mpq_feed = &mpq_demux->feeds[i];
@@ -4590,11 +4840,7 @@
size_t count)
{
struct sdmx_buff_descr buf_desc;
- struct dvb_ringbuffer *rbuf = (struct dvb_ringbuffer *)
- mpq_demux->demux.dmx.dvr_input.ringbuff;
- ion_phys_addr_t phys_addr;
u32 read_offset;
- size_t len;
int ret;
if (mpq_demux == NULL || input_handle == NULL) {
@@ -4602,17 +4848,14 @@
return -EINVAL;
}
- ret = ion_phys(mpq_demux->ion_client, input_handle, &phys_addr, &len);
+ ret = mpq_sdmx_dvr_buffer_desc(mpq_demux, &buf_desc);
if (ret) {
MPQ_DVB_ERR_PRINT(
- "%s: Failed to obtain physical address of input buffer. ret = %d\n",
+ "%s: Failed to init input buffer descriptor. ret = %d\n",
__func__, ret);
return ret;
}
-
- buf_desc.base_addr = (void *)phys_addr;
- buf_desc.size = rbuf->size;
- read_offset = rbuf->pread;
+ read_offset = mpq_demux->demux.dmx.dvr_input.ringbuff->pread;
return mpq_sdmx_process(mpq_demux, &buf_desc, count, read_offset);
}
@@ -4649,10 +4892,9 @@
* process managed to consume, unless some sdmx error occurred, for
* which should process the whole buffer
*/
- if (mpq_demux->num_active_feeds > mpq_demux->num_secure_feeds) {
+ if (mpq_demux->num_active_feeds > mpq_demux->num_secure_feeds)
dvb_dmx_swfilter_format(dvb_demux, buf, ret,
dvb_demux->tsp_format);
- }
if (signal_pending(current))
return -EINTR;
@@ -4676,3 +4918,78 @@
return mpq_dmx_info.secure_demux_app_loaded;
}
EXPORT_SYMBOL(mpq_sdmx_is_loaded);
+
+int mpq_dmx_oob_command(struct dvb_demux_feed *feed,
+ struct dmx_oob_command *cmd)
+{
+ struct mpq_feed *mpq_feed = feed->priv;
+ struct mpq_demux *mpq_demux = mpq_feed->mpq_demux;
+ struct dmx_data_ready event;
+ int ret = 0;
+
+ mutex_lock(&mpq_demux->mutex);
+ mpq_feed = feed->priv;
+
+ event.data_length = 0;
+
+ switch (cmd->type) {
+ case DMX_OOB_CMD_EOS:
+ event.status = DMX_OK_EOS;
+ if (!feed->secure_mode.is_secured) {
+ if (dvb_dmx_is_video_feed(feed)) {
+ if (mpq_dmx_info.decoder_framing)
+ mpq_dmx_decoder_pes_closure(mpq_demux,
+ mpq_feed);
+ else
+ mpq_dmx_decoder_frame_closure(mpq_demux,
+ mpq_feed);
+ ret = mpq_dmx_decoder_eos_cmd(mpq_feed);
+ if (ret)
+ MPQ_DVB_ERR_PRINT(
+ "%s: Couldn't write oob eos packet\n",
+ __func__);
+ }
+ ret = feed->data_ready_cb.ts(&feed->feed.ts, &event);
+ } else if (!mpq_demux->sdmx_eos) {
+ struct sdmx_buff_descr buf_desc;
+
+ mpq_demux->sdmx_eos = 1;
+ ret = mpq_sdmx_dvr_buffer_desc(mpq_demux, &buf_desc);
+ if (!ret) {
+ mutex_unlock(&mpq_demux->mutex);
+ mpq_sdmx_process_buffer(mpq_demux, &buf_desc,
+ 0, 0);
+ return 0;
+ }
+ }
+ break;
+ case DMX_OOB_CMD_MARKER:
+ event.status = DMX_OK_MARKER;
+ event.marker.id = cmd->params.marker.id;
+
+ if (feed->type == DMX_TYPE_SEC) {
+ struct dvb_demux_filter *f = feed->filter;
+ struct dmx_section_feed *sec = &feed->feed.sec;
+
+ while (f && sec->is_filtering) {
+ ret = feed->data_ready_cb.sec(&f->filter,
+ &event);
+ if (ret)
+ break;
+ f = f->next;
+ }
+ } else {
+ /* MPQ_TODO: Notify decoder via the stream buffer */
+ ret = feed->data_ready_cb.ts(&feed->feed.ts, &event);
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&mpq_demux->mutex);
+ return ret;
+}
+EXPORT_SYMBOL(mpq_dmx_oob_command);
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 7affcc6..4abf088 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
@@ -242,7 +242,7 @@
* @pes_header: Used for feeds that output data to decoder,
* holds PES header of current processed PES.
* @pes_header_left_bytes: Used for feeds that output data to decoder,
- * holds remainning PES header bytes of current processed PES.
+ * holds remaining PES header bytes of current processed PES.
* @pes_header_offset: Holds the offset within the current processed
* pes header.
* @fullness_wait_cancel: Flag used to signal to abort waiting for
@@ -369,6 +369,7 @@
* Used before each call to sdmx_process() to build up to date state.
* @sdmx_session_handle: Secure demux open session handle
* @sdmx_filter_count: Number of active secure demux filters
+ * @sdmx_eos: End-of-stream indication flag for current sdmx session
* @plugin_priv: Underlying plugin's own private data
* @hw_notification_interval: Notification interval in msec,
* exposed in debugfs.
@@ -415,6 +416,7 @@
int sdmx_session_handle;
int sdmx_session_ref_count;
int sdmx_filter_count;
+ int sdmx_eos;
void *plugin_priv;
/* debug-fs */
@@ -725,6 +727,22 @@
*/
int mpq_sdmx_is_loaded(void);
+/**
+ * mpq_dmx_oob_command - Handles OOB command from dvb-demux.
+ *
+ * OOB marker commands trigger callback to the dmxdev.
+ * Handling of EOS command may trigger current (last on stream) PES/Frame to
+ * be reported, in addition to callback to the dmxdev.
+ * In case secure demux is active for the feed, EOS command is passed to the
+ * secure demux for handling.
+ *
+ * @feed: dvb demux feed object
+ * @cmd: oob command data
+ *
+ * returns 0 on success or error
+ */
+int mpq_dmx_oob_command(struct dvb_demux_feed *feed,
+ struct dmx_oob_command *cmd);
#endif /* _MPQ_DMX_PLUGIN_COMMON_H */
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 3d48441..026d1cb 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
@@ -687,6 +687,7 @@
mpq_demux->demux.decoder_buffer_status = mpq_dmx_decoder_buffer_status;
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;
/* 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 beb4cce..e263aef 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
@@ -1742,6 +1742,7 @@
mpq_demux->demux.decoder_buffer_status = mpq_dmx_decoder_buffer_status;
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;
/* 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 60ce9e5..81a2a93 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
@@ -127,6 +127,7 @@
mpq_demux->demux.decoder_buffer_status = NULL;
mpq_demux->demux.reuse_decoder_buffer = NULL;
mpq_demux->demux.set_secure_mode = NULL;
+ mpq_demux->demux.oob_command = 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 23121b2..b55f367 100644
--- a/drivers/media/platform/msm/dvb/include/mpq_adapter.h
+++ b/drivers/media/platform/msm/dvb/include/mpq_adapter.h
@@ -62,10 +62,10 @@
};
enum dmx_packet_type {
- DMX_PADDING_PACKET,
DMX_PES_PACKET,
DMX_FRAMING_INFO_PACKET,
- DMX_EOS_PACKET
+ DMX_EOS_PACKET,
+ DMX_MARKER_PACKET
};
struct dmx_pts_dts_info {
@@ -94,6 +94,11 @@
struct dmx_pts_dts_info pts_dts_info;
};
+struct dmx_marker_info {
+ /* marker id */
+ u64 id;
+};
+
/** The meta-data used for video interface */
struct mpq_adapter_video_meta_data {
/** meta-data packet type */
@@ -103,6 +108,7 @@
union {
struct dmx_framing_packet_info framing;
struct dmx_pes_packet_info pes;
+ struct dmx_marker_info marker;
} info;
} __packed;
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 45a9dd5..3f33535 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -186,7 +186,9 @@
case DMX_EOS_PACKET:
break;
case DMX_PES_PACKET:
- case DMX_PADDING_PACKET:
+ case DMX_MARKER_PACKET:
+ break;
+ default:
break;
}
} while (!frame_found);
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 3b12a26..79a492e 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -152,16 +152,7 @@
rc = ion_handle_get_flags(client->clnt, hndl, &ionflags);
if (rc) {
dprintk(VIDC_ERR, "Failed to get ion flags: %d\n", rc);
- goto fail_map;
- }
- if (ION_IS_CACHED(ionflags)) {
- mem->kvaddr = ion_map_kernel(client->clnt, hndl);
- if (!mem->kvaddr) {
- dprintk(VIDC_ERR,
- "Failed to map shared mem in kernel\n");
- rc = -EIO;
- goto fail_map;
- }
+ goto fail_device_address;
}
mem->flags = ionflags;
@@ -184,9 +175,6 @@
mem->device_addr, mem->size);
return rc;
fail_device_address:
- if (mem->kvaddr)
- ion_unmap_kernel(client->clnt, hndl);
-fail_map:
ion_free(client->clnt, hndl);
fail_import_fd:
return rc;
@@ -366,20 +354,14 @@
rc = -EINVAL;
goto cache_op_failed;
}
- if (mem->kvaddr) {
- rc = msm_ion_do_cache_op(client->clnt,
- (struct ion_handle *)mem->smem_priv,
- (unsigned long *) mem->kvaddr,
- (unsigned long)mem->size,
- msm_cache_ops);
- if (rc) {
- dprintk(VIDC_ERR,
+ rc = msm_ion_do_cache_op(client->clnt,
+ (struct ion_handle *)mem->smem_priv,
+ 0, (unsigned long)mem->size,
+ msm_cache_ops);
+ if (rc) {
+ dprintk(VIDC_ERR,
"cache operation failed %d\n", rc);
- goto cache_op_failed;
- }
- } else {
- dprintk(VIDC_WARN,
- "cache operation failed as no kernel mapping\n");
+ goto cache_op_failed;
}
}
cache_op_failed:
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index b80d63e..4425909 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.h
@@ -25,7 +25,7 @@
enum smem_prop {
SMEM_CACHED = ION_FLAG_CACHED,
- SMEM_SECURE = ION_SECURE,
+ SMEM_SECURE = ION_FLAG_SECURE,
};
enum hal_buffer {
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 2ca5008..eca8091 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -24,7 +24,7 @@
#define MAX_NUM_OUTPUT_BUFFERS 6
enum msm_vdec_ctrl_cluster {
- MSM_VDEC_CTRL_CLUSTER_MAX = 1,
+ MSM_VDEC_CTRL_CLUSTER_MAX = 1 << 0,
};
static const char *const mpeg_video_vidc_divx_format[] = {
@@ -621,13 +621,6 @@
frame_sz.height = inst->prop.height;
dprintk(VIDC_DBG, "width = %d, height = %d\n",
frame_sz.width, frame_sz.height);
- rc = msm_comm_try_set_prop(inst,
- HAL_PARAM_FRAME_SIZE, &frame_sz);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed : Frame size setting\n", __func__);
- goto exit;
- }
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -1364,7 +1357,7 @@
return NULL;
for (c = 0; c < NUM_CTRLS; c++) {
- if (msm_vdec_ctrls[c].cluster == type) {
+ if (msm_vdec_ctrls[c].cluster & type) {
cluster[sz] = msm_vdec_ctrls[c].priv;
++sz;
}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index bf29a95..bbd56fb 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -107,16 +107,17 @@
};
enum msm_venc_ctrl_cluster {
- MSM_VENC_CTRL_CLUSTER_QP = 1,
- MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD,
- MSM_VENC_CTRL_CLUSTER_H264_PROFILE_LEVEL,
- MSM_VENC_CTRL_CLUSTER_MPEG_PROFILE_LEVEL,
- MSM_VENC_CTRL_CLUSTER_H263_PROFILE_LEVEL,
- MSM_VENC_CTRL_CLUSTER_H264_ENTROPY,
- MSM_VENC_CTRL_CLUSTER_SLICING,
- MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH,
- MSM_VENC_CTRL_CLUSTER_BITRATE,
- MSM_VENC_CTRL_CLUSTER_MAX,
+ MSM_VENC_CTRL_CLUSTER_QP = 1 << 0,
+ MSM_VENC_CTRL_CLUSTER_INTRA_PERIOD = 1 << 1,
+ MSM_VENC_CTRL_CLUSTER_H264_PROFILE_LEVEL = 1 << 2,
+ MSM_VENC_CTRL_CLUSTER_MPEG_PROFILE_LEVEL = 1 << 3,
+ MSM_VENC_CTRL_CLUSTER_H263_PROFILE_LEVEL = 1 << 4,
+ MSM_VENC_CTRL_CLUSTER_H264_ENTROPY = 1 << 5,
+ MSM_VENC_CTRL_CLUSTER_SLICING = 1 << 6,
+ MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH = 1 << 7,
+ MSM_VENC_CTRL_CLUSTER_BITRATE = 1 << 8,
+ MSM_VENC_CTRL_CLUSTER_TIMING = 1 << 9,
+ MSM_VENC_CTRL_CLUSTER_MAX = 1 << 10,
};
static struct msm_vidc_ctrl msm_venc_ctrls[] = {
@@ -2187,7 +2188,7 @@
return NULL;
for (c = 0; c < NUM_CTRLS; c++) {
- if (msm_venc_ctrls[c].cluster == type) {
+ if (msm_venc_ctrls[c].cluster & type) {
cluster[sz] = msm_venc_ctrls[c].priv;
++sz;
}
diff --git a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
index fee7b47..ceb0149 100644
--- a/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-mfc-subdev.c
@@ -2040,7 +2040,7 @@
}
heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
heap_mask |= inst->secure ? 0 : ION_HEAP(ION_IOMMU_HEAP_ID);
- ion_flags |= inst->secure ? ION_SECURE : 0;
+ ion_flags |= inst->secure ? ION_FLAG_SECURE : 0;
if (vcd_get_ion_status()) {
for (i = 0; i < 4; ++i) {
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index e589878..1d3c9f55 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -168,7 +168,7 @@
if (secure) {
alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
- ion_flags = ION_SECURE;
+ ion_flags = ION_FLAG_SECURE;
align = SZ_1M;
} else {
alloc_regions = ION_HEAP(ION_IOMMU_HEAP_ID);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 362a391..188ac32 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -60,6 +60,7 @@
#define QSEE_CE_CLK_100MHZ 100000000
#define QSEECOM_MAX_SG_ENTRY 512
+#define QSEECOM_DISK_ENCRYTPION_KEY_ID 0
enum qseecom_clk_definitions {
CLK_DFAB = 0,
@@ -109,6 +110,12 @@
struct qseecom_handle *handle;
};
+struct ce_hw_usage_info {
+ uint32_t qsee_ce_hw_instance;
+ uint32_t hlos_ce_hw_instance;
+ uint32_t disk_encrypt_pipe;
+};
+
struct qseecom_clk {
struct clk *ce_core_clk;
struct clk *ce_clk;
@@ -134,6 +141,7 @@
uint32_t qsee_version;
struct device *pdev;
bool commonlib_loaded;
+ struct ce_hw_usage_info ce_info;
int qsee_bw_count;
int qsee_sfpb_bw_count;
@@ -171,6 +179,20 @@
atomic_t ioctl_count;
};
+enum qseecom_set_clear_key_flag {
+ QSEECOM_CLEAR_CE_KEY_CMD = 0,
+ QSEECOM_SET_CE_KEY_CMD,
+};
+
+struct qseecom_set_key_parameter {
+ uint32_t ce_hw;
+ uint32_t pipe;
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+ unsigned char hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_set_clear_key_flag set_clear_key_flag;
+};
+
struct qseecom_sg_entry {
uint32_t phys_addr;
uint32_t len;
@@ -503,7 +525,6 @@
struct qseecom_client_listener_data_irsp send_data_rsp;
struct qseecom_registered_listener_list *ptr_svc = NULL;
-
while (resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
/*
@@ -1875,7 +1896,7 @@
int rc = 0;
struct qseecom_clk *qclk;
- qclk = &qseecom.qsee;
+ qclk = &qseecom.qsee;
/* Enable CE core clk */
rc = clk_prepare_enable(qclk->ce_core_clk);
if (rc) {
@@ -2282,6 +2303,273 @@
}
}
+static int __qseecom_get_ce_pipe_info(
+ enum qseecom_key_management_usage_type usage,
+ uint32_t *pipe, uint32_t *ce_hw)
+{
+ int ret;
+ switch (usage) {
+ case QSEOS_KM_USAGE_DISK_ENCRYPTION:
+ if (qseecom.ce_info.disk_encrypt_pipe == 0xFF ||
+ qseecom.ce_info.hlos_ce_hw_instance == 0xFF) {
+ pr_err("nfo unavailable: disk encr pipe %d ce_hw %d\n",
+ qseecom.ce_info.disk_encrypt_pipe,
+ qseecom.ce_info.hlos_ce_hw_instance);
+ ret = -EINVAL;
+ } else {
+ *pipe = qseecom.ce_info.disk_encrypt_pipe;
+ *ce_hw = qseecom.ce_info.hlos_ce_hw_instance;
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ uint8_t *key_id, uint32_t flags)
+{
+ struct qseecom_key_generate_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+
+ memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.flags = flags;
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
+ &ireq, sizeof(struct qseecom_key_generate_ireq),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("scm call to generate key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("gen key scm call failed resp.result %d\n", resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ uint8_t *key_id, uint32_t flags)
+{
+ struct qseecom_key_delete_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+
+ memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.flags = flags;
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
+ &ireq, sizeof(struct qseecom_key_delete_ireq),
+ &resp, sizeof(struct qseecom_command_scm_resp));
+ if (ret) {
+ pr_err("scm call to delete key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("Delete key scm call failed resp.result %d\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ struct qseecom_set_key_parameter *set_key_para)
+{
+ struct qseecom_key_select_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+ memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.ce = set_key_para->ce_hw;
+ ireq.pipe = set_key_para->pipe;
+ ireq.flags = set_key_para->flags;
+
+ if (set_key_para->set_clear_key_flag ==
+ QSEECOM_SET_CE_KEY_CMD)
+ memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
+ QSEECOM_HASH_SIZE);
+ else
+ memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_SET_KEY,
+ &ireq, sizeof(struct qseecom_key_select_ireq),
+ &resp, sizeof(struct qseecom_command_scm_resp));
+ if (ret) {
+ pr_err("scm call to set key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("Set key scm call failed resp.result %d\n", resp.result);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int qseecom_create_key(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ uint32_t ce_hw = 0;
+ uint32_t pipe = 0;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+ int ret = 0;
+ uint32_t flags = 0;
+ struct qseecom_set_key_parameter set_key_para;
+ struct qseecom_create_key_req create_key_req;
+
+ ret = copy_from_user(&create_key_req, argp, sizeof(create_key_req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+
+ if (create_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", create_key_req.usage);
+ return -EFAULT;
+ }
+
+ ret = __qseecom_get_ce_pipe_info(create_key_req.usage, &pipe, &ce_hw);
+ if (ret) {
+ pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = __qseecom_generate_and_save_key(data, create_key_req.usage,
+ key_id, flags);
+ if (ret) {
+ pr_err("Failed to generate key on storage: %d\n", ret);
+ return -EFAULT;
+ }
+
+ set_key_para.ce_hw = ce_hw;
+ set_key_para.pipe = pipe;
+ memcpy(set_key_para.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ set_key_para.flags = flags;
+ set_key_para.set_clear_key_flag = QSEECOM_SET_CE_KEY_CMD;
+ memcpy((void *)set_key_para.hash32, (void *)create_key_req.hash32,
+ QSEECOM_HASH_SIZE);
+
+ ret = __qseecom_set_clear_ce_key(data, create_key_req.usage,
+ &set_key_para);
+ if (ret) {
+ pr_err("Failed to create key: pipe %d, ce %d: %d\n",
+ pipe, ce_hw, ret);
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+static int qseecom_wipe_key(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ uint32_t ce_hw = 0;
+ uint32_t pipe = 0;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+ int ret = 0;
+ uint32_t flags = 0;
+ int i;
+ struct qseecom_wipe_key_req wipe_key_req;
+ struct qseecom_set_key_parameter clear_key_para;
+
+ ret = copy_from_user(&wipe_key_req, argp, sizeof(wipe_key_req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+
+ if (wipe_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", wipe_key_req.usage);
+ return -EFAULT;
+ }
+
+ ret = __qseecom_get_ce_pipe_info(wipe_key_req.usage, &pipe, &ce_hw);
+ if (ret) {
+ pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = __qseecom_delete_saved_key(data, wipe_key_req.usage, key_id,
+ flags);
+ if (ret) {
+ pr_err("Failed to delete key from ssd storage: %d\n", ret);
+ return -EFAULT;
+ }
+
+ /* an invalid key_id 0xff is used to indicate clear key*/
+ for (i = 0; i < QSEECOM_KEY_ID_SIZE; i++)
+ clear_key_para.key_id[i] = 0xff;
+ clear_key_para.ce_hw = ce_hw;
+ clear_key_para.pipe = pipe;
+ clear_key_para.flags = flags;
+ clear_key_para.set_clear_key_flag = QSEECOM_CLEAR_CE_KEY_CMD;
+ ret = __qseecom_set_clear_ce_key(data, wipe_key_req.usage,
+ &clear_key_para);
+ if (ret) {
+ pr_err("Failed to wipe key: pipe %d, ce %d: %d\n",
+ pipe, ce_hw, ret);
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
static long qseecom_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
@@ -2471,6 +2759,29 @@
mutex_unlock(&app_access_lock);
break;
}
+ case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_create_key(data, argp);
+ if (ret)
+ pr_err("failed to create encryption key: %d\n", ret);
+
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
+ case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_wipe_key(data, argp);
+ if (ret)
+ pr_err("failed to wipe encryption key: %d\n", ret);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
default:
return -EINVAL;
}
@@ -2528,6 +2839,7 @@
ret = qseecom_unload_app(data);
break;
case QSEECOM_SECURE_SERVICE:
+ case QSEECOM_GENERIC:
ret = qseecom_unmap_ion_allocated_memory(data);
if (ret) {
pr_err("Close failed\n");
@@ -2741,6 +3053,42 @@
/* register client for bus scaling */
if (pdev->dev.of_node) {
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,disk-encrypt-pipe-pair",
+ &qseecom.ce_info.disk_encrypt_pipe)) {
+ pr_err("Fail to get disk-encrypt pipe pair information.\n");
+ qseecom.ce_info.disk_encrypt_pipe = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("bam_pipe_pair=0x%x",
+ qseecom.ce_info.disk_encrypt_pipe);
+ }
+
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,qsee-ce-hw-instance",
+ &qseecom.ce_info.qsee_ce_hw_instance)) {
+ pr_err("Fail to get qsee ce hw instance information.\n");
+ qseecom.ce_info.qsee_ce_hw_instance = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("qsee-ce-hw-instance=0x%x",
+ qseecom.ce_info.qsee_ce_hw_instance);
+ }
+
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,hlos-ce-hw-instance",
+ &qseecom.ce_info.hlos_ce_hw_instance)) {
+ pr_err("Fail to get hlos ce hw instance information.\n");
+ qseecom.ce_info.hlos_ce_hw_instance = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("hlos-ce-hw-instance=0x%x",
+ qseecom.ce_info.hlos_ce_hw_instance);
+ }
+
ret = __qseecom_init_clk();
if (ret)
goto err;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index fc7c399..d339d81 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -45,6 +45,9 @@
#include "sd_ops.h"
#include "sdio_ops.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/mmc.h>
+
static void mmc_clk_scaling(struct mmc_host *host, bool from_wq);
/* If the device is not responding */
@@ -1486,6 +1489,19 @@
if (ios->clock > 0)
mmc_set_ungated(host);
host->ops->set_ios(host, ios);
+ if (ios->old_rate != ios->clock) {
+ if (likely(ios->clk_ts)) {
+ char trace_info[80];
+ snprintf(trace_info, 80,
+ "%s: freq_KHz %d --> %d | t = %d",
+ mmc_hostname(host), ios->old_rate / 1000,
+ ios->clock / 1000, jiffies_to_msecs(
+ (long)jiffies - (long)ios->clk_ts));
+ trace_mmc_clk(trace_info);
+ }
+ ios->old_rate = ios->clock;
+ ios->clk_ts = jiffies;
+ }
}
EXPORT_SYMBOL(mmc_set_ios);
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index ed67df4..2ecd6f7 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -18,7 +18,7 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/sched.h>
-#include <linux/spinlock.h>
+#include <linux/atomic.h>
#include <mach/ecm_ipa.h>
#define DRIVER_NAME "ecm_ipa"
@@ -27,6 +27,9 @@
#define ECM_IPA_IPV6_HDR_NAME "ecm_eth_ipv6"
#define IPA_TO_USB_CLIENT IPA_CLIENT_USB_CONS
#define INACTIVITY_MSEC_DELAY 100
+#define DEFAULT_OUTSTANDING_HIGH 64
+#define DEFAULT_OUTSTANDING_LOW 32
+
#define ECM_IPA_ERROR(fmt, args...) \
pr_err(DRIVER_NAME "@%s@%d@ctx:%s: "\
fmt, __func__, __LINE__, current->comm, ## args)
@@ -45,8 +48,6 @@
/**
* struct ecm_ipa_dev - main driver context parameters
- * @ack_spinlock: protect last sent skb
- * @last_out_skb: last sent skb saved until Tx notify is received from IPA
* @net: network interface struct implemented by this driver
* @folder: debugfs folder for various debuging switches
* @tx_enable: flag that enable/disable Tx path to continue to IPA
@@ -56,15 +57,19 @@
* @tx_file: saved debugfs entry to allow cleanup
* @rx_file: saved debugfs entry to allow cleanup
* @rm_file: saved debugfs entry to allow cleanup
+ * @outstanding_high_file saved debugfs entry to allow cleanup
+ * @outstanding_low_file saved debugfs entry to allow cleanup
* @dma_file: saved debugfs entry to allow cleanup
* @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table
* @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table
* @usb_to_ipa_hdl: save handle for IPA pipe operations
* @ipa_to_usb_hdl: save handle for IPA pipe operations
+ * @outstanding_pkts: number of packets sent to IPA without TX complete ACKed
+ * @outstanding_high: number of outstanding packets allowed
+ * @outstanding_low: number of outstanding packets which shall cause
+ * to netdev queue start (after stopped due to outstanding_high reached)
*/
struct ecm_ipa_dev {
- spinlock_t ack_spinlock;
- struct sk_buff *last_out_skb;
struct net_device *net;
bool tx_enable;
bool rx_enable;
@@ -74,11 +79,16 @@
struct dentry *tx_file;
struct dentry *rx_file;
struct dentry *rm_file;
+ struct dentry *outstanding_high_file;
+ struct dentry *outstanding_low_file;
struct dentry *dma_file;
uint32_t eth_ipv4_hdr_hdl;
uint32_t eth_ipv6_hdr_hdl;
u32 usb_to_ipa_hdl;
u32 ipa_to_usb_hdl;
+ atomic_t outstanding_pkts;
+ u8 outstanding_high;
+ u8 outstanding_low;
};
/**
@@ -200,7 +210,9 @@
memset(dev, 0, sizeof(*dev));
dev->tx_enable = true;
dev->rx_enable = true;
- spin_lock_init(&dev->ack_spinlock);
+ atomic_set(&dev->outstanding_pkts, 0);
+ dev->outstanding_high = DEFAULT_OUTSTANDING_HIGH;
+ dev->outstanding_low = DEFAULT_OUTSTANDING_LOW;
dev->net = net;
ecm_ipa_ctx = dev;
*priv = (void *)dev;
@@ -662,7 +674,6 @@
int ret;
netdev_tx_t status = NETDEV_TX_BUSY;
struct ecm_ipa_dev *dev = netdev_priv(net);
- unsigned long flags;
if (unlikely(netif_queue_stopped(net))) {
ECM_IPA_ERROR("interface queue is stopped\n");
@@ -682,23 +693,24 @@
goto resource_busy;
}
- spin_lock_irqsave(&dev->ack_spinlock, flags);
- if (dev->last_out_skb) {
- pr_debug("No Tx-ack received for previous packet\n");
- spin_unlock_irqrestore(&dev->ack_spinlock, flags);
+ pr_debug("Before sending packet the outstanding packets counter is %d\n",
+ atomic_read(&dev->outstanding_pkts));
+
+ if (atomic_read(&dev->outstanding_pkts) >= dev->outstanding_high) {
+ pr_debug("Outstanding high boundary reached (%d)- stopping queue\n",
+ dev->outstanding_high);
netif_stop_queue(net);
status = -NETDEV_TX_BUSY;
goto out;
- } else {
- dev->last_out_skb = skb;
}
- spin_unlock_irqrestore(&dev->ack_spinlock, flags);
ret = ipa_tx_dp(IPA_TO_USB_CLIENT, skb, NULL);
if (ret) {
ECM_IPA_ERROR("ipa transmit failed (%d)\n", ret);
goto fail_tx_packet;
}
+
+ atomic_inc(&dev->outstanding_pkts);
net->stats.tx_packets++;
net->stats.tx_bytes += skb->len;
status = NETDEV_TX_OK;
@@ -766,7 +778,6 @@
{
struct sk_buff *skb = (struct sk_buff *)data;
struct ecm_ipa_dev *dev = priv;
- unsigned long flags;
if (!dev) {
ECM_IPA_ERROR("dev is NULL pointer\n");
@@ -776,15 +787,16 @@
ECM_IPA_ERROR("unsupported event on Tx callback\n");
return;
}
- spin_lock_irqsave(&dev->ack_spinlock, flags);
- if (skb != dev->last_out_skb)
- ECM_IPA_ERROR("ACKed/Sent not the same(FIFO expected)\n");
- dev->last_out_skb = NULL;
- spin_unlock_irqrestore(&dev->ack_spinlock, flags);
- if (netif_queue_stopped(dev->net)) {
- pr_debug("waking up queue\n");
+ atomic_dec(&dev->outstanding_pkts);
+ if (netif_queue_stopped(dev->net) &&
+ atomic_read(&dev->outstanding_pkts) < (dev->outstanding_low)) {
+ pr_debug("Outstanding low boundary reached (%d) - waking up queue\n",
+ dev->outstanding_low);
netif_wake_queue(dev->net);
}
+ pr_debug("After Tx-complete the outstanding packets counter is %d\n",
+ atomic_read(&dev->outstanding_pkts));
+
dev_kfree_skb_any(skb);
return;
}
@@ -889,8 +901,8 @@
static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *dev)
{
- const mode_t flags = S_IRUSR | S_IRGRP | S_IROTH |
- S_IWUSR | S_IWGRP | S_IWOTH;
+ const mode_t flags = S_IRUGO | S_IWUGO;
+
int ret = -EINVAL;
ECM_IPA_LOG_ENTRY();
if (!dev)
@@ -929,6 +941,22 @@
ret = -EFAULT;
goto fail_file;
}
+
+ dev->outstanding_high_file = debugfs_create_u8("outstanding_high",
+ flags, dev->folder, &dev->outstanding_high);
+ if (!dev->outstanding_high_file) {
+ ECM_IPA_ERROR("could not create outstanding_high file\n");
+ ret = -EFAULT;
+ goto fail_file;
+ }
+ dev->outstanding_low_file = debugfs_create_u8("outstanding_low",
+ flags, dev->folder, &dev->outstanding_low);
+ if (!dev->outstanding_low_file) {
+ ECM_IPA_ERROR("could not create outstanding_low file\n");
+ ret = -EFAULT;
+ goto fail_file;
+ }
+
ECM_IPA_LOG_EXIT();
return 0;
fail_file:
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index eeb98e9..dd00081 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -403,7 +403,7 @@
sys->connection.dest_pipe_index = ipa_ctx->a5_pipe_index++;
sys->connection.mode = SPS_MODE_SRC;
sys->connection.options = SPS_O_AUTO_ENABLE | SPS_O_EOT |
- SPS_O_ACK_TRANSFERS;
+ SPS_O_ACK_TRANSFERS | SPS_O_NO_DISABLE;
}
sys->desc_mem_buf.size = props->desc_fifo_sz;
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index a4b7e22..f2f80bf 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -33,17 +33,56 @@
static int ipa_disable_data_path(u32 clnt_hdl)
{
+ DECLARE_COMPLETION_ONSTACK(tag_rsp);
+ struct ipa_desc desc = {0};
+ struct ipa_ip_packet_tag cmd;
struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
+ struct ipa_tree_node *node;
+ int result = 0;
if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
return 0;
}
+ node = kmem_cache_zalloc(ipa_ctx->tree_node_cache, GFP_KERNEL);
+ if (!node) {
+ IPAERR("failed to alloc tree node object\n");
+ result = -ENOMEM;
+ goto fail_alloc;
+ }
+
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
+ cmd.tag = (u32) &tag_rsp;
+
+ desc.pyld = &cmd;
+ desc.len = sizeof(struct ipa_ip_packet_tag);
+ desc.type = IPA_IMM_CMD_DESC;
+ desc.opcode = IPA_IP_PACKET_TAG;
+
+ IPADBG("Wait on TAG %p clnt=%d\n", &tag_rsp, clnt_hdl);
+
+ node->hdl = cmd.tag;
+ mutex_lock(&ipa_ctx->lock);
+ if (ipa_insert(&ipa_ctx->tag_tree, node)) {
+ IPAERR("failed to add to tree\n");
+ result = -EINVAL;
+ mutex_unlock(&ipa_ctx->lock);
+ goto fail_insert;
+ }
+ mutex_unlock(&ipa_ctx->lock);
+
+ if (ipa_send_cmd(1, &desc)) {
+ ipa_write_reg(ipa_ctx->mmio,
+ IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
+ IPAERR("fail to send TAG command\n");
+ result = -EPERM;
+ goto fail_send;
+ }
+ wait_for_completion(&tag_rsp);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
@@ -52,6 +91,13 @@
}
return 0;
+
+fail_send:
+ rb_erase(&node->node, &ipa_ctx->tag_tree);
+fail_insert:
+ kmem_cache_free(ipa_ctx->tree_node_cache, node);
+fail_alloc:
+ return result;
}
static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -238,6 +284,9 @@
ep->connect.event_thresh = IPA_EVENT_THRESHOLD;
ep->connect.options = SPS_O_AUTO_ENABLE; /* BAM-to-BAM */
+ if (IPA_CLIENT_IS_CONS(in->client))
+ ep->connect.options |= SPS_O_NO_DISABLE;
+
result = sps_connect(ep->ep_hdl, &ep->connect);
if (result) {
IPAERR("sps_connect fails.\n");
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 86eebf6..5f7f3d9 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -528,6 +528,8 @@
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
struct ipa_ep_context *ep;
int cnt = 0;
+ struct completion *compl;
+ struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
@@ -582,6 +584,35 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
+ if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
+ /* retrieve the compl object from tag value */
+ mux_hdr++;
+ compl = (struct completion *)
+ ntohl(*((u32 *)mux_hdr));
+ IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
+ *((u32 *)mux_hdr + 1), compl);
+
+ mutex_lock(&ipa_ctx->lock);
+ node = ipa_search(&ipa_ctx->tag_tree,
+ (u32)compl);
+ if (node) {
+ complete_all(compl);
+ rb_erase(&node->node,
+ &ipa_ctx->tag_tree);
+ kmem_cache_free(
+ ipa_ctx->tree_node_cache, node);
+ } else {
+ WARN_ON(1);
+ }
+ mutex_unlock(&ipa_ctx->lock);
+ }
+ dev_kfree_skb(rx_skb);
+ ipa_replenish_rx_cache();
+ ++cnt;
+ continue;
+ }
+
/*
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
@@ -791,7 +822,8 @@
ipa_ctx->a5_pipe_index++;
ipa_ctx->ep[ipa_ep_idx].connect.src_pipe_index = ipa_ep_idx;
ipa_ctx->ep[ipa_ep_idx].connect.options =
- SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
+ SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS |
+ SPS_O_NO_DISABLE;
if (ipa_ctx->polling_mode)
ipa_ctx->ep[ipa_ep_idx].connect.options |= SPS_O_POLL;
} else {
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 31d1a78..3ebb1cd 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -827,9 +827,14 @@
}
if (bam_pipe_is_enabled(dev->base, pipe_index)) {
- SPS_ERR("sps:BAM 0x%x pipe %d sharing violation",
- BAM_ID(dev), pipe_index);
- return SPS_ERROR;
+ if (params->options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d is already enabled\n",
+ BAM_ID(dev), pipe_index);
+ else {
+ SPS_ERR("sps:BAM 0x%x pipe %d sharing violation\n",
+ BAM_ID(dev), pipe_index);
+ return SPS_ERROR;
+ }
}
if (bam_pipe_init(dev->base, pipe_index, &hw_params, dev->props.ee)) {
@@ -882,8 +887,13 @@
bam_pipe->state |= BAM_STATE_INIT;
result = 0;
exit_err:
- if (result)
- bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ if (result) {
+ if (params->options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d connection exits\n",
+ BAM_ID(dev), pipe_index);
+ else
+ bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ }
exit_init_err:
if (result) {
/* Clear the client pipe state */
@@ -916,7 +926,11 @@
dev->pipe_active_mask &= ~(1UL << pipe_index);
}
dev->pipe_remote_mask &= ~(1UL << pipe_index);
- bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ if (pipe->connect.options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d exits\n", BAM_ID(dev),
+ pipe_index);
+ else
+ bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
if (pipe->sys.desc_cache != NULL) {
u32 size = pipe->num_descs * sizeof(void *);
if (pipe->desc_size + size <= PAGE_SIZE)
@@ -1114,7 +1128,12 @@
struct sps_pipe *pipe = dev->pipes[pipe_index];
/* Disable the BAM pipe */
- bam_pipe_disable(dev->base, pipe_index);
+ if (pipe->connect.options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d enters disable state\n",
+ BAM_ID(dev), pipe_index);
+ else
+ bam_pipe_disable(dev->base, pipe_index);
+
pipe->state &= ~BAM_STATE_ENABLED;
return 0;
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 37ac7b5..f917ef6 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -194,6 +194,12 @@
int prev_voltage_based_soc;
bool use_voltage_soc;
+ int prev_batt_terminal_uv;
+ int high_ocv_correction_limit_uv;
+ int low_ocv_correction_limit_uv;
+ int flat_ocv_threshold_uv;
+ int hold_soc_est;
+
int ocv_high_threshold_uv;
int ocv_low_threshold_uv;
unsigned long last_recalc_time;
@@ -651,6 +657,7 @@
chip->last_cc_uah = INT_MIN;
chip->last_ocv_temp = batt_temp;
chip->last_soc_invalid = true;
+ chip->prev_batt_terminal_uv = 0;
}
#define OCV_RAW_UNINITIALIZED 0xFFFF
@@ -1296,11 +1303,13 @@
pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
ibat_ua, soc);
}
+
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return soc;
}
/*
- * battery is in CV phase - begin liner inerpolation of soc based on
+ * battery is in CV phase - begin linear interpolation of soc based on
* battery charge current
*/
@@ -1308,10 +1317,11 @@
* if voltage lessened (possibly because of a system load)
* keep reporting the prev chg soc
*/
- if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
+ if (batt_terminal_uv <= chip->prev_batt_terminal_uv) {
pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
- batt_terminal_uv,
- chip->max_voltage_uv, chip->prev_chg_soc);
+ batt_terminal_uv, chip->prev_batt_terminal_uv,
+ chip->prev_chg_soc);
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return chip->prev_chg_soc;
}
@@ -1334,6 +1344,7 @@
}
pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return chip->prev_chg_soc;
}
@@ -1369,6 +1380,7 @@
int slope = 0;
int rc = 0;
int delta_ocv_uv_limit = 0;
+ int correction_limit_uv = 0;
rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
if (rc < 0) {
@@ -1460,6 +1472,21 @@
pr_debug("new delta ocv = %d\n", delta_ocv_uv);
}
+ if (chip->last_ocv_uv > chip->flat_ocv_threshold_uv)
+ correction_limit_uv = chip->high_ocv_correction_limit_uv;
+ else
+ correction_limit_uv = chip->low_ocv_correction_limit_uv;
+
+ if (abs(delta_ocv_uv) > correction_limit_uv) {
+ pr_debug("limiting delta ocv %d limit = %d\n",
+ delta_ocv_uv, correction_limit_uv);
+ if (delta_ocv_uv > 0)
+ delta_ocv_uv = correction_limit_uv;
+ else
+ delta_ocv_uv = -correction_limit_uv;
+ pr_debug("new delta ocv = %d\n", delta_ocv_uv);
+ }
+
chip->last_ocv_uv -= delta_ocv_uv;
if (chip->last_ocv_uv >= chip->max_voltage_uv)
@@ -1474,9 +1501,9 @@
/*
* if soc_new is ZERO force it higher so that phone doesnt report soc=0
- * soc = 0 should happen only when soc_est == 0
+ * soc = 0 should happen only when soc_est is above a set value
*/
- if (soc_new == 0 && soc_est != 0)
+ if (soc_new == 0 && soc_est >= chip->hold_soc_est)
soc_new = 1;
soc = soc_new;
@@ -2143,6 +2170,7 @@
chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
+ chip->flat_ocv_threshold_uv = batt_data->flat_ocv_threshold_uv;
if (chip->pc_temp_ocv_lut == NULL) {
pr_err("temp ocv lut table is NULL\n");
@@ -2195,6 +2223,14 @@
chip->use_ocv_thresholds = of_property_read_bool(
chip->spmi->dev.of_node,
"qcom,use-ocv-thresholds");
+ SPMI_PROP_READ(high_ocv_correction_limit_uv,
+ "high-ocv-correction-limit-uv", rc);
+ SPMI_PROP_READ(low_ocv_correction_limit_uv,
+ "low-ocv-correction-limit-uv", rc);
+ SPMI_PROP_READ(hold_soc_est,
+ "hold-soc-est", rc);
+ SPMI_PROP_READ(ocv_high_threshold_uv,
+ "ocv-voltage-high-threshold-uv", rc);
SPMI_PROP_READ(ocv_high_threshold_uv,
"ocv-voltage-high-threshold-uv", rc);
SPMI_PROP_READ(ocv_low_threshold_uv,
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index f4efa756..8129ef3 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -157,6 +157,11 @@
/* smbb_misc_interrupts */
#define TFTWDOG_IRQ BIT(0)
+/* SMBB types */
+#define SMBB BIT(1)
+#define SMBBP BIT(2)
+#define SMBCL BIT(3)
+
/* Workaround flags */
#define CHG_FLAGS_VCP_WA BIT(0)
@@ -194,6 +199,8 @@
* @warm_bat_decidegc Warm battery temperature in degree Celsius
* @cool_bat_decidegc Cool battery temperature in degree Celsius
* @revision: PMIC revision
+ * @type: SMBB type
+ * @tchg_mins maximum allowed software initiated charge time
* @thermal_levels amount of thermal mitigation levels
* @thermal_mitigation thermal mitigation level values
* @therm_lvl_sel thermal mitigation level selection
@@ -247,6 +254,8 @@
unsigned int cool_bat_decidegc;
unsigned int safe_current;
unsigned int revision;
+ unsigned int type;
+ unsigned int tchg_mins;
unsigned int thermal_levels;
unsigned int therm_lvl_sel;
unsigned int *thermal_mitigation;
@@ -813,16 +822,16 @@
int rc = 0;
struct qpnp_vadc_result results;
- if (chip->revision > 0) {
+ if (chip->revision == 0 && chip->type == SMBB) {
+ pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
+ return 0;
+ } else {
rc = qpnp_vadc_read(VBAT_SNS, &results);
if (rc) {
pr_err("Unable to read vbat rc=%d\n", rc);
return 0;
}
return results.physical;
- } else {
- pr_err("vbat reading not supported for 1.0 rc=%d\n", rc);
- return 0;
}
}
@@ -1421,7 +1430,7 @@
static void
qpnp_chg_setup_flags(struct qpnp_chg_chip *chip)
{
- if (chip->revision > 0)
+ if (chip->revision > 0 && chip->type == SMBB)
chip->flags |= CHG_FLAGS_VCP_WA;
}
@@ -1651,7 +1660,9 @@
case SMBBP_BOOST_SUBTYPE:
break;
case SMBB_MISC_SUBTYPE:
+ chip->type = SMBB;
case SMBBP_MISC_SUBTYPE:
+ chip->type = SMBBP;
pr_debug("Setting BOOT_DONE\n");
rc = qpnp_chg_masked_write(chip,
chip->misc_base + CHGR_MISC_BOOT_DONE,
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index f7e5eee..ee80975 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -280,10 +280,13 @@
num = ((adc_code * tmdev->tsens_factor) -
tmdev->sensor[sensor_num].offset);
den = (int) tmdev->sensor[sensor_num].slope_mul_tsens_factor;
- degc = num/den;
- if ((degc >= 0) && (num % den != 0))
- degc++;
+ if (num > 0)
+ degc = ((num + (den/2))/den);
+ else if (num < 0)
+ degc = ((num - (den/2))/den);
+ else
+ degc = num/den;
return degc;
}
@@ -344,6 +347,17 @@
}
EXPORT_SYMBOL(tsens_get_temp);
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
+{
+ if (!tmdev)
+ return -ENODEV;
+
+ *tsens_num_sensors = tmdev->tsens_num_sensor;
+
+ return 0;
+}
+EXPORT_SYMBOL(tsens_get_max_sensor_num);
+
static int tsens_tz_get_mode(struct thermal_zone_device *thermal,
enum thermal_device_mode *mode)
{
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 954848e..7aa14de 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -1706,6 +1706,30 @@
port->uartclk = 7372800;
msm_hsl_port = UART_TO_MSM(port);
+ msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
+ if (unlikely(IS_ERR(msm_hsl_port->clk))) {
+ ret = PTR_ERR(msm_hsl_port->clk);
+ if (ret != -EPROBE_DEFER)
+ pr_err("Error getting clk\n");
+ return ret;
+ }
+
+ /* Interface clock is not required by all UART configurations.
+ * GSBI UART and BLSP UART needs interface clock but Legacy UART
+ * do not require interface clock. Hence, do not fail probe with
+ * iface clk_get failure.
+ */
+ msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
+ if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
+ ret = PTR_ERR(msm_hsl_port->pclk);
+ if (ret == -EPROBE_DEFER) {
+ clk_put(msm_hsl_port->clk);
+ return ret;
+ } else {
+ msm_hsl_port->pclk = NULL;
+ }
+ }
+
/* Identify UART functional mode as 2-wire or 4-wire. */
if (pdata && pdata->config_gpio == 4)
msm_hsl_port->func_mode = UART_FOUR_WIRE;
@@ -1743,22 +1767,12 @@
"gsbi_resource");
if (!gsbi_resource)
gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
- msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
if (gsbi_resource)
msm_hsl_port->uart_type = GSBI_HSUART;
else
msm_hsl_port->uart_type = LEGACY_HSUART;
- if (unlikely(IS_ERR(msm_hsl_port->clk))) {
- pr_err("Error getting clk\n");
- return PTR_ERR(msm_hsl_port->clk);
- }
- if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
- pr_err("Error getting pclk\n");
- return PTR_ERR(msm_hsl_port->pclk);
- }
uart_resource = platform_get_resource_byname(pdev,
IORESOURCE_MEM,
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index f60aa6a..161634e 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -408,6 +408,11 @@
struct platform_driver *pdrv;
c = &port->ctrl_ch;
+ if (c->ch) {
+ smd_close(c->ch);
+ c->ch = NULL;
+ }
+
if (test_bit(CH_READY, &c->flags) ||
test_bit(CH_PREPARE_READY, &c->flags)) {
clear_bit(CH_PREPARE_READY, &c->flags);
@@ -460,11 +465,6 @@
smd_tiocmset(c->ch, c->cbits_tomodem, clear_bits);
}
- if (c->ch) {
- smd_close(c->ch);
- c->ch = NULL;
- }
-
queue_delayed_work(grmnet_ctrl_wq, &port->disconnect_w, 0);
}
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 9879122..4a085aa 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1332,44 +1332,48 @@
if (pdata->resume_gpio)
gpio_direction_output(pdata->resume_gpio, 1);
- mehci->resume_status = 0;
- resume_thread = kthread_run(msm_hsic_resume_thread,
- mehci, "hsic_resume_thread");
- if (IS_ERR(resume_thread)) {
- pr_err("Error creating resume thread:%lu\n",
- PTR_ERR(resume_thread));
- return PTR_ERR(resume_thread);
+ if (!mehci->ehci.resume_sof_bug) {
+ ehci_bus_resume(hcd);
+ } else {
+ mehci->resume_status = 0;
+ resume_thread = kthread_run(msm_hsic_resume_thread,
+ mehci, "hsic_resume_thread");
+ if (IS_ERR(resume_thread)) {
+ pr_err("Error creating resume thread:%lu\n",
+ PTR_ERR(resume_thread));
+ return PTR_ERR(resume_thread);
+ }
+
+ wait_for_completion(&mehci->rt_completion);
+
+ if (mehci->resume_status < 0)
+ return mehci->resume_status;
+
+ dbg_log_event(NULL, "FPR: Wokeup", 0);
+ spin_lock_irq(&ehci->lock);
+ (void) ehci_readl(ehci, &ehci->regs->command);
+
+ temp = 0;
+ if (ehci->async->qh_next.qh)
+ temp |= CMD_ASE;
+ if (ehci->periodic_sched)
+ temp |= CMD_PSE;
+ if (temp) {
+ ehci->command |= temp;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ }
+
+ ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+ hcd->state = HC_STATE_RUNNING;
+ ehci->rh_state = EHCI_RH_RUNNING;
+ ehci->command |= CMD_RUN;
+
+ /* Now we can safely re-enable irqs */
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+ spin_unlock_irq(&ehci->lock);
}
- wait_for_completion(&mehci->rt_completion);
-
- if (mehci->resume_status < 0)
- return mehci->resume_status;
-
- dbg_log_event(NULL, "FPR: Wokeup", 0);
- spin_lock_irq(&ehci->lock);
- (void) ehci_readl(ehci, &ehci->regs->command);
-
- temp = 0;
- if (ehci->async->qh_next.qh)
- temp |= CMD_ASE;
- if (ehci->periodic_sched)
- temp |= CMD_PSE;
- if (temp) {
- ehci->command |= temp;
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
- }
-
- ehci->next_statechange = jiffies + msecs_to_jiffies(5);
- hcd->state = HC_STATE_RUNNING;
- ehci->rh_state = EHCI_RH_RUNNING;
- ehci->command |= CMD_RUN;
-
- /* Now we can safely re-enable irqs */
- ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
-
- spin_unlock_irq(&ehci->lock);
-
if (pdata->resume_gpio)
gpio_direction_output(pdata->resume_gpio, 0);
@@ -1808,6 +1812,8 @@
res_gpio = 0;
pdata->resume_gpio = res_gpio;
+ pdata->phy_sof_workaround = of_property_read_bool(node,
+ "qcom,phy-sof-workaround");
pdata->ignore_cal_pad_config = of_property_read_bool(node,
"hsic,ignore-cal-pad-config");
of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -1899,10 +1905,12 @@
spin_lock_init(&mehci->wakeup_lock);
- mehci->ehci.susp_sof_bug = 1;
- mehci->ehci.reset_sof_bug = 1;
+ if (pdata->phy_sof_workaround) {
+ mehci->ehci.susp_sof_bug = 1;
+ mehci->ehci.reset_sof_bug = 1;
+ mehci->ehci.resume_sof_bug = 1;
+ }
- mehci->ehci.resume_sof_bug = 1;
mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
mehci->enable_hbm = pdata->enable_hbm;
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index e415a95..e8d7489 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3273,10 +3273,10 @@
pr_debug("pipe->flags 0x%x\n", pipe->flags);
if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) {
mfd->mem_hid &= ~BIT(ION_IOMMU_HEAP_ID);
- mfd->mem_hid |= ION_SECURE;
+ mfd->mem_hid |= ION_FLAG_SECURE;
} else {
mfd->mem_hid |= BIT(ION_IOMMU_HEAP_ID);
- mfd->mem_hid &= ~ION_SECURE;
+ mfd->mem_hid &= ~ION_FLAG_SECURE;
}
}
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 2423de5..f8b7f2f 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -2314,7 +2314,7 @@
pr_err("ion_map_iommu() read failed\n");
return -ENOMEM;
}
- if (mfd->mem_hid & ION_SECURE) {
+ if (mfd->mem_hid & ION_FLAG_SECURE) {
if (ion_phys(mfd->iclient, buf->ihdl,
&addr, (size_t *)&len)) {
pr_err("%s:%d: ion_phys map failed\n",
@@ -2377,7 +2377,7 @@
if (!IS_ERR_OR_NULL(mfd->iclient)) {
if (!IS_ERR_OR_NULL(buf->ihdl)) {
if (mdp_iommu_split_domain) {
- if (!(mfd->mem_hid & ION_SECURE))
+ if (!(mfd->mem_hid & ION_FLAG_SECURE))
ion_unmap_iommu(mfd->iclient, buf->ihdl,
DISPLAY_WRITE_DOMAIN, GEN_POOL);
ion_unmap_iommu(mfd->iclient, buf->ihdl,
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index de765ea..fd680e6 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -1,3 +1,6 @@
+mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o
+obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp3.o
+
mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o
mdss-mdp-objs += mdss_mdp_pp.o
mdss-mdp-objs += mdss_mdp_intf_video.o
@@ -12,6 +15,9 @@
obj-$(CONFIG_DEBUG_FS) += mdss_debug.o
endif
+dsi-v2-objs = dsi_v2.o dsi_host_v2.o dsi_io_v2.o dsi_panel_v2.o
+obj-$(CONFIG_FB_MSM_MDSS) += dsi-v2.o
+
mdss-dsi-objs := mdss_dsi.o mdss_dsi_host.o
mdss-dsi-objs += mdss_dsi_panel.o
mdss-dsi-objs += msm_mdss_io_8974.o
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
new file mode 100644
index 0000000..453cbaa
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -0,0 +1,1034 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+
+#include "dsi_v2.h"
+#include "dsi_io_v2.h"
+#include "dsi_host_v2.h"
+
+#define DSI_POLL_SLEEP_US 1000
+#define DSI_POLL_TIMEOUT_US 16000
+#define DSI_ESC_CLK_RATE 19200000
+
+struct dsi_host_v2_private {
+ struct completion dma_comp;
+ int irq_enabled;
+ spinlock_t irq_lock;
+ spinlock_t mdp_lock;
+ int mdp_busy;
+ int irq_no;
+ unsigned char *dsi_base;
+ struct device dis_dev;
+};
+
+static struct dsi_host_v2_private *dsi_host_private;
+
+int msm_dsi_init(void)
+{
+ if (!dsi_host_private) {
+ dsi_host_private = kzalloc(sizeof(struct dsi_host_v2_private),
+ GFP_KERNEL);
+ if (!dsi_host_private) {
+ pr_err("fail to alloc dsi host private data\n");
+ return -ENOMEM;
+ }
+ }
+
+ init_completion(&dsi_host_private->dma_comp);
+ spin_lock_init(&dsi_host_private->irq_lock);
+ spin_lock_init(&dsi_host_private->mdp_lock);
+ return 0;
+}
+
+void msm_dsi_deinit(void)
+{
+ kfree(dsi_host_private);
+ dsi_host_private = NULL;
+}
+
+void msm_dsi_ack_err_status(unsigned char *ctrl_base)
+{
+ u32 status;
+
+ status = MIPI_INP(ctrl_base + DSI_ACK_ERR_STATUS);
+
+ if (status) {
+ MIPI_OUTP(ctrl_base + DSI_ACK_ERR_STATUS, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void msm_dsi_timeout_status(unsigned char *ctrl_base)
+{
+ u32 status;
+
+ status = MIPI_INP(ctrl_base + DSI_TIMEOUT_STATUS);
+ if (status & 0x0111) {
+ MIPI_OUTP(ctrl_base + DSI_TIMEOUT_STATUS, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void msm_dsi_dln0_phy_err(unsigned char *ctrl_base)
+{
+ u32 status;
+
+ status = MIPI_INP(ctrl_base + DSI_DLN0_PHY_ERR);
+
+ if (status & 0x011111) {
+ MIPI_OUTP(ctrl_base + DSI_DLN0_PHY_ERR, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void msm_dsi_fifo_status(unsigned char *ctrl_base)
+{
+ u32 status;
+
+ status = MIPI_INP(ctrl_base + DSI_FIFO_STATUS);
+
+ if (status & 0x44444489) {
+ MIPI_OUTP(ctrl_base + DSI_FIFO_STATUS, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void msm_dsi_status(unsigned char *ctrl_base)
+{
+ u32 status;
+
+ status = MIPI_INP(ctrl_base + DSI_STATUS);
+
+ if (status & 0x80000000) {
+ MIPI_OUTP(ctrl_base + DSI_STATUS, status);
+ pr_debug("%s: status=%x\n", __func__, status);
+ }
+}
+
+void msm_dsi_error(unsigned char *ctrl_base)
+{
+ msm_dsi_ack_err_status(ctrl_base);
+ msm_dsi_timeout_status(ctrl_base);
+ msm_dsi_fifo_status(ctrl_base);
+ msm_dsi_status(ctrl_base);
+ msm_dsi_dln0_phy_err(ctrl_base);
+}
+
+void msm_dsi_enable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
+ if (dsi_host_private->irq_enabled) {
+ pr_debug("%s: IRQ aleady enabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+ return;
+ }
+
+ enable_irq(dsi_host_private->irq_no);
+ dsi_host_private->irq_enabled = 1;
+ spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+}
+
+void msm_dsi_disable_irq(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&dsi_host_private->irq_lock, flags);
+ if (dsi_host_private->irq_enabled == 0) {
+ pr_debug("%s: IRQ already disabled\n", __func__);
+ spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+ return;
+ }
+ disable_irq(dsi_host_private->irq_no);
+ dsi_host_private->irq_enabled = 0;
+ spin_unlock_irqrestore(&dsi_host_private->irq_lock, flags);
+}
+
+void msm_dsi_disable_irq_nosync(void)
+{
+ spin_lock(&dsi_host_private->irq_lock);
+ if (dsi_host_private->irq_enabled == 0) {
+ pr_debug("%s: IRQ cannot be disabled\n", __func__);
+ spin_unlock(&dsi_host_private->irq_lock);
+ return;
+ }
+ disable_irq_nosync(dsi_host_private->irq_no);
+ dsi_host_private->irq_enabled = 0;
+ spin_unlock(&dsi_host_private->irq_lock);
+}
+
+irqreturn_t msm_dsi_isr(int irq, void *ptr)
+{
+ u32 isr;
+
+ isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+ MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
+
+ if (isr & DSI_INTR_ERROR)
+ msm_dsi_error(dsi_host_private->dsi_base);
+
+ if (isr & DSI_INTR_CMD_DMA_DONE)
+ complete(&dsi_host_private->dma_comp);
+
+ if (isr & DSI_INTR_CMD_MDP_DONE) {
+ spin_lock(&dsi_host_private->mdp_lock);
+ dsi_host_private->mdp_busy = false;
+ msm_dsi_disable_irq_nosync();
+ spin_unlock(&dsi_host_private->mdp_lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
+int msm_dsi_irq_init(struct device *dev, int irq_no)
+{
+ int ret;
+
+ ret = devm_request_irq(dev, irq_no, msm_dsi_isr,
+ IRQF_DISABLED, "DSI", NULL);
+ if (ret) {
+ pr_err("msm_dsi_irq_init request_irq() failed!\n");
+ return ret;
+ }
+ dsi_host_private->irq_no = irq_no;
+ disable_irq(irq_no);
+ return 0;
+}
+
+void msm_dsi_host_init(struct mipi_panel_info *pinfo)
+{
+ u32 dsi_ctrl, intr_ctrl, data;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ pr_debug("msm_dsi_host_init\n");
+ pinfo->rgb_swap = DSI_RGB_SWAP_RGB;
+
+ if (pinfo->mode == DSI_VIDEO_MODE) {
+ data = 0;
+ if (pinfo->pulse_mode_hsa_he)
+ data |= BIT(28);
+ if (pinfo->hfp_power_stop)
+ data |= BIT(24);
+ if (pinfo->hbp_power_stop)
+ data |= BIT(20);
+ if (pinfo->hsa_power_stop)
+ data |= BIT(16);
+ if (pinfo->eof_bllp_power_stop)
+ data |= BIT(15);
+ if (pinfo->bllp_power_stop)
+ data |= BIT(12);
+ data |= ((pinfo->traffic_mode & 0x03) << 8);
+ data |= ((pinfo->dst_format & 0x03) << 4); /* 2 bits */
+ data |= (pinfo->vc & 0x03);
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_CTRL, data);
+
+ data = 0;
+ data |= ((pinfo->rgb_swap & 0x07) << 12);
+ if (pinfo->b_sel)
+ data |= BIT(8);
+ if (pinfo->g_sel)
+ data |= BIT(4);
+ if (pinfo->r_sel)
+ data |= BIT(0);
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_DATA_CTRL, data);
+ } else if (pinfo->mode == DSI_CMD_MODE) {
+ data = 0;
+ data |= ((pinfo->interleave_max & 0x0f) << 20);
+ data |= ((pinfo->rgb_swap & 0x07) << 16);
+ if (pinfo->b_sel)
+ data |= BIT(12);
+ if (pinfo->g_sel)
+ data |= BIT(8);
+ if (pinfo->r_sel)
+ data |= BIT(4);
+ data |= (pinfo->dst_format & 0x0f); /* 4 bits */
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_CTRL, data);
+
+ /* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
+ data = pinfo->wr_mem_continue & 0x0ff;
+ data <<= 8;
+ data |= (pinfo->wr_mem_start & 0x0ff);
+ if (pinfo->insert_dcs_cmd)
+ data |= BIT(16);
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL,
+ data);
+ } else
+ pr_err("%s: Unknown DSI mode=%d\n", __func__, pinfo->mode);
+
+ dsi_ctrl = BIT(8) | BIT(2); /* clock enable & cmd mode */
+ intr_ctrl = 0;
+ intr_ctrl = (DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_CMD_MDP_DONE_MASK);
+
+ if (pinfo->crc_check)
+ dsi_ctrl |= BIT(24);
+ if (pinfo->ecc_check)
+ dsi_ctrl |= BIT(20);
+ if (pinfo->data_lane3)
+ dsi_ctrl |= BIT(7);
+ if (pinfo->data_lane2)
+ dsi_ctrl |= BIT(6);
+ if (pinfo->data_lane1)
+ dsi_ctrl |= BIT(5);
+ if (pinfo->data_lane0)
+ dsi_ctrl |= BIT(4);
+
+ /* from frame buffer, low power mode */
+ /* DSI_COMMAND_MODE_DMA_CTRL */
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, 0x14000000);
+
+ data = 0;
+ if (pinfo->te_sel)
+ data |= BIT(31);
+ data |= pinfo->mdp_trigger << 4;/* cmd mdp trigger */
+ data |= pinfo->dma_trigger; /* cmd dma trigger */
+ data |= (pinfo->stream & 0x01) << 8;
+ MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, data);
+
+ /* DSI_LAN_SWAP_CTRL */
+ MIPI_OUTP(ctrl_base + DSI_LANE_SWAP_CTRL, pinfo->dlane_swap);
+
+ /* clock out ctrl */
+ data = pinfo->t_clk_post & 0x3f; /* 6 bits */
+ data <<= 8;
+ data |= pinfo->t_clk_pre & 0x3f; /* 6 bits */
+ /* DSI_CLKOUT_TIMING_CTRL */
+ MIPI_OUTP(ctrl_base + DSI_CLKOUT_TIMING_CTRL, data);
+
+ data = 0;
+ if (pinfo->rx_eot_ignore)
+ data |= BIT(4);
+ if (pinfo->tx_eot_append)
+ data |= BIT(0);
+ MIPI_OUTP(ctrl_base + DSI_EOT_PACKET_CTRL, data);
+
+
+ /* allow only ack-err-status to generate interrupt */
+ /* DSI_ERR_INT_MASK0 */
+ MIPI_OUTP(ctrl_base + DSI_ERR_INT_MASK0, 0x13ff3fe0);
+
+ intr_ctrl |= DSI_INTR_ERROR_MASK;
+ MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
+
+ dsi_ctrl |= BIT(0); /* enable dsi */
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+
+ wmb();
+}
+
+void msm_dsi_set_tx_power_mode(int mode)
+{
+ u32 data;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ data = MIPI_INP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL);
+
+ if (mode == 0)
+ data &= ~BIT(26);
+ else
+ data |= BIT(26);
+
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
+}
+
+void msm_dsi_sw_reset(void)
+{
+ u32 dsi_ctrl;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ pr_debug("msm_dsi_sw_reset\n");
+
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ dsi_ctrl &= ~0x01;
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+ wmb();
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0x23f);
+ wmb();
+
+ MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x01);
+ wmb();
+ MIPI_OUTP(ctrl_base + DSI_SOFT_RESET, 0x00);
+ wmb();
+}
+
+void msm_dsi_controller_cfg(int enable)
+{
+ u32 dsi_ctrl, status;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ pr_debug("msm_dsi_controller_cfg\n");
+
+ /* Check for CMD_MODE_DMA_BUSY */
+ if (readl_poll_timeout((ctrl_base + DSI_STATUS),
+ status,
+ ((status & 0x02) == 0),
+ DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
+ pr_err("%s: DSI status=%x failed\n", __func__, status);
+
+ /* Check for x_HS_FIFO_EMPTY */
+ if (readl_poll_timeout((ctrl_base + DSI_FIFO_STATUS),
+ status,
+ ((status & 0x11111000) == 0x11111000),
+ DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
+ pr_err("%s: FIFO status=%x failed\n", __func__, status);
+
+ /* Check for VIDEO_MODE_ENGINE_BUSY */
+ if (readl_poll_timeout((ctrl_base + DSI_STATUS),
+ status,
+ ((status & 0x08) == 0),
+ DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US)) {
+ pr_err("%s: DSI status=%x\n", __func__, status);
+ pr_err("%s: Doing sw reset\n", __func__);
+ msm_dsi_sw_reset();
+ }
+
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ if (enable)
+ dsi_ctrl |= 0x01;
+ else
+ dsi_ctrl &= ~0x01;
+
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+ wmb();
+}
+
+void msm_dsi_op_mode_config(int mode, struct mdss_panel_data *pdata)
+{
+ u32 dsi_ctrl, intr_ctrl;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ pr_debug("msm_dsi_op_mode_config\n");
+
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ /*If Video enabled, Keep Video and Cmd mode ON */
+ if (dsi_ctrl & 0x02)
+ dsi_ctrl &= ~0x05;
+ else
+ dsi_ctrl &= ~0x07;
+
+ if (mode == DSI_VIDEO_MODE) {
+ dsi_ctrl |= 0x03;
+ intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK;
+ } else { /* command mode */
+ dsi_ctrl |= 0x05;
+ if (pdata->panel_info.type == MIPI_VIDEO_PANEL)
+ dsi_ctrl |= 0x02;
+
+ intr_ctrl = DSI_INTR_CMD_DMA_DONE_MASK | DSI_INTR_ERROR_MASK |
+ DSI_INTR_CMD_MDP_DONE_MASK;
+ }
+
+ pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
+
+ MIPI_OUTP(ctrl_base + DSI_INT_CTRL, intr_ctrl);
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+ wmb();
+}
+
+void msm_dsi_cmd_mdp_start(void)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+ msm_dsi_enable_irq();
+ dsi_host_private->mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+}
+
+int msm_dsi_cmd_reg_tx(u32 data)
+{
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ MIPI_OUTP(ctrl_base + DSI_TRIG_CTRL, 0x04);/* sw trigger */
+ MIPI_OUTP(ctrl_base + DSI_CTRL, 0x135);
+ wmb();
+
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_DMA_CTRL, data);
+ wmb();
+ MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
+ wmb();
+
+ udelay(300); /*per spec*/
+
+ return 0;
+}
+
+int msm_dsi_cmd_dma_tx(struct dsi_buf *tp)
+{
+ int len;
+ unsigned long size, addr;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ len = ALIGN(tp->len, 4);
+ size = ALIGN(tp->len, SZ_4K);
+
+ tp->dmap = dma_map_single(&dsi_host_private->dis_dev, tp->data, size,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&dsi_host_private->dis_dev, tp->dmap)) {
+ pr_err("%s: dmap mapp failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ addr = tp->dmap;
+
+ INIT_COMPLETION(dsi_host_private->dma_comp);
+
+ MIPI_OUTP(ctrl_base + DSI_DMA_CMD_OFFSET, addr);
+ MIPI_OUTP(ctrl_base + DSI_DMA_CMD_LENGTH, len);
+ wmb();
+
+ MIPI_OUTP(ctrl_base + DSI_CMD_MODE_DMA_SW_TRIGGER, 0x01);
+ wmb();
+
+ wait_for_completion_interruptible(&dsi_host_private->dma_comp);
+
+ dma_unmap_single(&dsi_host_private->dis_dev, tp->dmap, size,
+ DMA_TO_DEVICE);
+ tp->dmap = 0;
+ return 0;
+}
+
+int msm_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen)
+{
+ u32 *lp, data;
+ int i, off, cnt;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ lp = (u32 *)rp->data;
+ cnt = rlen;
+ cnt += 3;
+ cnt >>= 2;
+
+ if (cnt > 4)
+ cnt = 4; /* 4 x 32 bits registers only */
+
+ off = DSI_RDBK_DATA0;
+ off += ((cnt - 1) * 4);
+
+ for (i = 0; i < cnt; i++) {
+ data = (u32)MIPI_INP(ctrl_base + off);
+ *lp++ = ntohl(data); /* to network byte order */
+ pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
+ __func__, data, ntohl(data));
+ off -= 4;
+ rp->len += sizeof(*lp);
+ }
+
+ return 0;
+}
+
+int msm_dsi_cmds_tx(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+{
+ struct dsi_cmd_desc *cm;
+ u32 dsi_ctrl, ctrl;
+ int i, video_mode;
+ unsigned long flag;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ /* turn on cmd mode
+ * for video mode, do not send cmds more than
+ * one pixel line, since it only transmit it
+ * during BLLP.
+ */
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(ctrl_base + DSI_CTRL, ctrl);
+ }
+
+ spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+ msm_dsi_enable_irq();
+ dsi_host_private->mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+ cm = cmds;
+ dsi_buf_init(tp);
+ for (i = 0; i < cnt; i++) {
+ dsi_buf_init(tp);
+ dsi_cmd_dma_add(tp, cm);
+ msm_dsi_cmd_dma_tx(tp);
+ if (cm->wait)
+ msleep(cm->wait);
+ cm++;
+ }
+
+ spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+ dsi_host_private->mdp_busy = false;
+ msm_dsi_disable_irq();
+ spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+ if (video_mode)
+ MIPI_OUTP(ctrl_base + DSI_CTRL, dsi_ctrl);
+ return 0;
+}
+
+/* MDSS_DSI_MRPS, Maximum Return Packet Size */
+static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
+
+static struct dsi_cmd_desc pkt_size_cmd[] = {
+ {DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
+ sizeof(max_pktsize), max_pktsize}
+};
+
+/*
+ * DSI panel reply with MAX_RETURN_PACKET_SIZE bytes of data
+ * plus DCS header, ECC and CRC for DCS long read response
+ * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
+ * hold data per transaction.
+ * MDSS_DSI_LEN equal to 8
+ * len should be either 4 or 8
+ * any return data more than MDSS_DSI_LEN need to be break down
+ * to multiple transactions.
+ *
+ * ov_mutex need to be acquired before call this function.
+ */
+int msm_dsi_cmds_rx(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int cnt, len, diff, pkt_size;
+ unsigned long flag;
+ char cmd;
+
+ if (pdata->panel_info.mipi.no_max_pkt_size)
+ rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
+
+ len = rlen;
+ diff = 0;
+
+ if (len <= 2) {
+ cnt = 4; /* short read */
+ } else {
+ if (len > DSI_LEN)
+ len = DSI_LEN; /* 8 bytes at most */
+
+ len = ALIGN(len, 4); /* len 4 bytes align */
+ diff = len - rlen;
+ /*
+ * add extra 2 bytes to len to have overall
+ * packet size is multipe by 4. This also make
+ * sure 4 bytes dcs headerlocates within a
+ * 32 bits register after shift in.
+ * after all, len should be either 6 or 10.
+ */
+ len += 2;
+ cnt = len + 6; /* 4 bytes header + 2 bytes crc */
+ }
+
+ spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+ msm_dsi_enable_irq();
+ dsi_host_private->mdp_busy = true;
+ spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+ if (!pdata->panel_info.mipi.no_max_pkt_size) {
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ dsi_buf_init(tp);
+ dsi_cmd_dma_add(tp, pkt_size_cmd);
+ msm_dsi_cmd_dma_tx(tp);
+ pr_debug("%s: Max packet size sent\n", __func__);
+ }
+
+ dsi_buf_init(tp);
+ dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ msm_dsi_cmd_dma_tx(tp);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ dsi_buf_init(rp);
+ if (pdata->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
+
+ msm_dsi_cmd_dma_rx(rp, cnt);
+
+ spin_lock_irqsave(&dsi_host_private->mdp_lock, flag);
+ dsi_host_private->mdp_busy = false;
+ msm_dsi_disable_irq();
+ spin_unlock_irqrestore(&dsi_host_private->mdp_lock, flag);
+
+ if (pdata->panel_info.mipi.no_max_pkt_size) {
+ /*
+ * remove extra 2 bytes from previous
+ * rx transaction at shift register
+ * which was inserted during copy
+ * shift registers to rx buffer
+ * rx payload start from long alignment addr
+ */
+ rp->data += 2;
+ }
+
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ dsi_long_read_resp(rp);
+ rp->len -= 2; /* extra 2 bytes added */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ pr_debug("%s: Unknown cmd received\n", __func__);
+ break;
+ }
+
+ return rp->len;
+}
+
+static int msm_dsi_cal_clk_rate(struct mdss_panel_data *pdata,
+ u32 *bitclk_rate,
+ u32 *byteclk_rate,
+ u32 *pclk_rate)
+{
+ struct mdss_panel_info *pinfo;
+ struct mipi_panel_info *mipi;
+ u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+ int lanes;
+
+ pinfo = &pdata->panel_info;
+ mipi = &pdata->panel_info.mipi;
+
+ hbp = pdata->panel_info.lcdc.h_back_porch;
+ hfp = pdata->panel_info.lcdc.h_front_porch;
+ vbp = pdata->panel_info.lcdc.v_back_porch;
+ vfp = pdata->panel_info.lcdc.v_front_porch;
+ hspw = pdata->panel_info.lcdc.h_pulse_width;
+ vspw = pdata->panel_info.lcdc.v_pulse_width;
+ width = pdata->panel_info.xres;
+ height = pdata->panel_info.yres;
+
+ lanes = 0;
+ if (mipi->data_lane0)
+ lanes++;
+ if (mipi->data_lane1)
+ lanes++;
+ if (mipi->data_lane2)
+ lanes++;
+ if (mipi->data_lane3)
+ lanes++;
+ if (lanes == 0)
+ return -EINVAL;
+
+ *bitclk_rate = (width + hbp + hfp + hspw) * (height + vbp + vfp + vspw);
+ *bitclk_rate *= mipi->frame_rate;
+ *bitclk_rate *= pdata->panel_info.bpp;
+ *bitclk_rate /= lanes;
+
+ *byteclk_rate = *bitclk_rate / 8;
+ *pclk_rate = *byteclk_rate * lanes * 8 / pdata->panel_info.bpp;
+
+ pr_debug("bitclk=%u, byteclk=%u, pck_=%u\n",
+ *bitclk_rate, *byteclk_rate, *pclk_rate);
+ return 0;
+}
+
+static int msm_dsi_on(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ u32 clk_rate;
+ struct mdss_panel_info *pinfo;
+ struct mipi_panel_info *mipi;
+ u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
+ u32 ystride, bpp, data;
+ u32 dummy_xres, dummy_yres;
+ u32 bitclk_rate = 0, byteclk_rate = 0, pclk_rate = 0;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+
+ pr_debug("msm_dsi_on\n");
+
+ pinfo = &pdata->panel_info;
+
+ ret = msm_dsi_regulator_enable();
+ if (ret) {
+ pr_err("%s: DSI power on failed\n", __func__);
+ return ret;
+ }
+
+ msm_dsi_ahb_ctrl(1);
+ msm_dsi_phy_sw_reset(dsi_host_private->dsi_base);
+ msm_dsi_phy_init(dsi_host_private->dsi_base, pdata);
+
+ msm_dsi_cal_clk_rate(pdata, &bitclk_rate, &byteclk_rate, &pclk_rate);
+ msm_dsi_clk_set_rate(DSI_ESC_CLK_RATE, byteclk_rate, pclk_rate);
+ msm_dsi_prepare_clocks();
+ msm_dsi_clk_enable();
+
+ clk_rate = pdata->panel_info.clk_rate;
+ clk_rate = min(clk_rate, pdata->panel_info.clk_max);
+
+ hbp = pdata->panel_info.lcdc.h_back_porch;
+ hfp = pdata->panel_info.lcdc.h_front_porch;
+ vbp = pdata->panel_info.lcdc.v_back_porch;
+ vfp = pdata->panel_info.lcdc.v_front_porch;
+ hspw = pdata->panel_info.lcdc.h_pulse_width;
+ vspw = pdata->panel_info.lcdc.v_pulse_width;
+ width = pdata->panel_info.xres;
+ height = pdata->panel_info.yres;
+
+ mipi = &pdata->panel_info.mipi;
+ if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
+ dummy_xres = pdata->panel_info.lcdc.xres_pad;
+ dummy_yres = pdata->panel_info.lcdc.yres_pad;
+
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_H,
+ ((hspw + hbp + width + dummy_xres) << 16 |
+ (hspw + hbp)));
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_ACTIVE_V,
+ ((vspw + vbp + height + dummy_yres) << 16 |
+ (vspw + vbp)));
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_TOTAL,
+ (vspw + vbp + height + dummy_yres +
+ vfp - 1) << 16 | (hspw + hbp +
+ width + dummy_xres + hfp - 1));
+
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_HSYNC, (hspw << 16));
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC, 0);
+ MIPI_OUTP(ctrl_base + DSI_VIDEO_MODE_VSYNC_VPOS,
+ (vspw << 16));
+
+ } else { /* command mode */
+ if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+ bpp = 3;
+ else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
+ bpp = 3;
+ else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+ bpp = 2;
+ else
+ bpp = 3; /* Default format set to RGB888 */
+
+ ystride = width * bpp + 1;
+
+ data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_CTRL,
+ data);
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_CTRL,
+ data);
+
+ data = height << 16 | width;
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM1_TOTAL,
+ data);
+ MIPI_OUTP(ctrl_base + DSI_COMMAND_MODE_MDP_STREAM0_TOTAL,
+ data);
+ }
+
+ msm_dsi_sw_reset();
+ msm_dsi_host_init(mipi);
+
+ if (mipi->force_clk_lane_hs) {
+ u32 tmp;
+
+ tmp = MIPI_INP(ctrl_base + DSI_LANE_CTRL);
+ tmp |= (1<<28);
+ MIPI_OUTP(ctrl_base + DSI_LANE_CTRL, tmp);
+ wmb();
+ }
+
+ msm_dsi_op_mode_config(mipi->mode, pdata);
+
+ return ret;
+}
+
+static int msm_dsi_off(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+
+ pr_debug("msm_dsi_off\n");
+ msm_dsi_clk_set_rate(0, 0, 0);
+ msm_dsi_clk_disable();
+ msm_dsi_unprepare_clocks();
+
+ /* disable DSI controller */
+ msm_dsi_controller_cfg(0);
+ msm_dsi_ahb_ctrl(0);
+
+ ret = msm_dsi_regulator_disable();
+ if (ret) {
+ pr_err("%s: Panel power off failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int __devinit msm_dsi_probe(struct platform_device *pdev)
+{
+ struct dsi_interface intf;
+ int rc = 0;
+
+ pr_debug("%s\n", __func__);
+
+ rc = msm_dsi_init();
+ if (rc)
+ return rc;
+
+ if (pdev->dev.of_node) {
+ struct resource *mdss_dsi_mres;
+ pdev->id = 0;
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mdss_dsi_mres) {
+ pr_err("%s:%d unable to get the MDSS reg resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ } else {
+ dsi_host_private->dsi_base = ioremap(
+ mdss_dsi_mres->start,
+ resource_size(mdss_dsi_mres));
+ if (!dsi_host_private->dsi_base) {
+ pr_err("%s:%d unable to remap dsi resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ }
+
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!mdss_dsi_mres || mdss_dsi_mres->start == 0) {
+ pr_err("%s:%d unable to get the MDSS irq resources",
+ __func__, __LINE__);
+ rc = -ENODEV;
+ goto dsi_probe_error;
+ } else {
+ rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to init irq, rc=%d\n",
+ __func__, rc);
+ goto dsi_probe_error;
+ }
+ }
+
+ rc = msm_dsi_io_init(pdev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to init DSI IO, rc=%d\n",
+ __func__, rc);
+ goto dsi_probe_error;
+ }
+
+ rc = of_platform_populate(pdev->dev.of_node,
+ NULL, NULL, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to add child nodes, rc=%d\n",
+ __func__, rc);
+ goto dsi_probe_error;
+ }
+
+ }
+
+ dsi_host_private->dis_dev = pdev->dev;
+ intf.on = msm_dsi_on;
+ intf.off = msm_dsi_off;
+ intf.op_mode_config = msm_dsi_op_mode_config;
+ intf.tx = msm_dsi_cmds_tx;
+ intf.rx = msm_dsi_cmds_rx;
+ intf.index = 0;
+ intf.private = NULL;
+ dsi_register_interface(&intf);
+ pr_debug("%s success\n", __func__);
+ return 0;
+dsi_probe_error:
+ if (dsi_host_private->dsi_base) {
+ iounmap(dsi_host_private->dsi_base);
+ dsi_host_private->dsi_base = NULL;
+ }
+ msm_dsi_io_deinit();
+ msm_dsi_deinit();
+ return rc;
+}
+
+static int __devexit msm_dsi_remove(struct platform_device *pdev)
+{
+ msm_dsi_disable_irq();
+ msm_dsi_io_deinit();
+ iounmap(dsi_host_private->dsi_base);
+ dsi_host_private->dsi_base = NULL;
+ msm_dsi_deinit();
+ return 0;
+}
+
+static const struct of_device_id msm_dsi_v2_dt_match[] = {
+ {.compatible = "qcom,msm-dsi-v2"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_dsi_v2_dt_match);
+
+static struct platform_driver msm_dsi_v2_driver = {
+ .probe = msm_dsi_probe,
+ .remove = __devexit_p(msm_dsi_remove),
+ .shutdown = NULL,
+ .driver = {
+ .name = "msm_dsi_v2",
+ .of_match_table = msm_dsi_v2_dt_match,
+ },
+};
+
+static int msm_dsi_v2_register_driver(void)
+{
+ return platform_driver_register(&msm_dsi_v2_driver);
+}
+
+static int __init msm_dsi_v2_driver_init(void)
+{
+ int ret;
+
+ ret = msm_dsi_v2_register_driver();
+ if (ret) {
+ pr_err("msm_dsi_v2_register_driver() failed!\n");
+ return ret;
+ }
+
+ return ret;
+}
+module_init(msm_dsi_v2_driver_init);
+
+static void __exit msm_dsi_v2_driver_cleanup(void)
+{
+ platform_driver_unregister(&msm_dsi_v2_driver);
+}
+module_exit(msm_dsi_v2_driver_cleanup);
diff --git a/drivers/video/msm/mdss/dsi_host_v2.h b/drivers/video/msm/mdss/dsi_host_v2.h
new file mode 100644
index 0000000..cec9774
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_host_v2.h
@@ -0,0 +1,169 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef DSI_HOST_V2_H
+#define DSI_HOST_V2_H
+
+#include <linux/bitops.h>
+
+#define DSI_INTR_ERROR_MASK BIT(25)
+#define DSI_INTR_ERROR BIT(24)
+#define DSI_INTR_VIDEO_DONE_MASK BIT(17)
+#define DSI_INTR_VIDEO_DONE BIT(16)
+#define DSI_INTR_CMD_MDP_DONE_MASK BIT(9)
+#define DSI_INTR_CMD_MDP_DONE BIT(8)
+#define DSI_INTR_CMD_DMA_DONE_MASK BIT(1)
+#define DSI_INTR_CMD_DMA_DONE BIT(0)
+
+#define DSI_CTRL 0x0000
+#define DSI_STATUS 0x0004
+#define DSI_FIFO_STATUS 0x0008
+#define DSI_VIDEO_MODE_CTRL 0x000C
+#define DSI_VIDEO_MODE_DATA_CTRL 0x001C
+#define DSI_VIDEO_MODE_ACTIVE_H 0x0020
+#define DSI_VIDEO_MODE_ACTIVE_V 0x0024
+#define DSI_VIDEO_MODE_TOTAL 0x0028
+#define DSI_VIDEO_MODE_HSYNC 0x002C
+#define DSI_VIDEO_MODE_VSYNC 0x0030
+#define DSI_VIDEO_MODE_VSYNC_VPOS 0x0034
+#define DSI_COMMAND_MODE_DMA_CTRL 0x0038
+#define DSI_COMMAND_MODE_MDP_CTRL 0x003C
+#define DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL 0x0040
+#define DSI_DMA_CMD_OFFSET 0x0044
+#define DSI_DMA_CMD_LENGTH 0x0048
+#define DSI_DMA_FIFO_CTRL 0x004C
+#define DSI_COMMAND_MODE_MDP_STREAM0_CTRL 0x0054
+#define DSI_COMMAND_MODE_MDP_STREAM0_TOTAL 0x0058
+#define DSI_COMMAND_MODE_MDP_STREAM1_CTRL 0x005C
+#define DSI_COMMAND_MODE_MDP_STREAM1_TOTAL 0x0060
+#define DSI_ACK_ERR_STATUS 0x0064
+#define DSI_RDBK_DATA0 0x0068
+#define DSI_RDBK_DATA1 0x006C
+#define DSI_RDBK_DATA2 0x0070
+#define DSI_RDBK_DATA3 0x0074
+#define DSI_RDBK_DATATYPE0 0x0078
+#define DSI_RDBK_DATATYPE1 0x007C
+#define DSI_TRIG_CTRL 0x0080
+#define DSI_EXT_MUX 0x0084
+#define DSI_EXT_TE_PULSE_DETECT_CTRL 0x0088
+#define DSI_CMD_MODE_DMA_SW_TRIGGER 0x008C
+#define DSI_CMD_MODE_MDP_SW_TRIGGER 0x0090
+#define DSI_CMD_MODE_BTA_SW_TRIGGER 0x0094
+#define DSI_RESET_SW_TRIGGER 0x0098
+#define DSI_LANE_CTRL 0x00A8
+#define DSI_LANE_SWAP_CTRL 0x00AC
+#define DSI_DLN0_PHY_ERR 0x00B0
+#define DSI_TIMEOUT_STATUS 0x00BC
+#define DSI_CLKOUT_TIMING_CTRL 0x00C0
+#define DSI_EOT_PACKET 0x00C4
+#define DSI_EOT_PACKET_CTRL 0x00C8
+#define DSI_ERR_INT_MASK0 0x0108
+#define DSI_INT_CTRL 0x010c
+#define DSI_SOFT_RESET 0x0114
+#define DSI_CLK_CTRL 0x0118
+#define DSI_CLK_STATUS 0x011C
+#define DSI_PHY_SW_RESET 0x0128
+#define DSI_COMMAND_MODE_MDP_IDLE_CTRL 0x0190
+#define DSI_VERSION 0x01F0
+
+#define DSI_DSIPHY_PLL_CTRL_0 0x0200
+#define DSI_DSIPHY_PLL_CTRL_1 0x0204
+#define DSI_DSIPHY_PLL_CTRL_2 0x0208
+#define DSI_DSIPHY_PLL_CTRL_3 0x020C
+#define DSI_DSIPHY_PLL_CTRL_4 0x0210
+#define DSI_DSIPHY_PLL_CTRL_5 0x0214
+#define DSI_DSIPHY_PLL_CTRL_6 0x0218
+#define DSI_DSIPHY_PLL_CTRL_7 0x021C
+#define DSI_DSIPHY_PLL_CTRL_8 0x0220
+#define DSI_DSIPHY_PLL_CTRL_9 0x0224
+#define DSI_DSIPHY_PLL_CTRL_10 0x0228
+#define DSI_DSIPHY_PLL_CTRL_11 0x022C
+#define DSI_DSIPHY_PLL_CTRL_12 0x0230
+#define DSI_DSIPHY_PLL_CTRL_13 0x0234
+#define DSI_DSIPHY_PLL_CTRL_14 0x0238
+#define DSI_DSIPHY_PLL_CTRL_15 0x023C
+#define DSI_DSIPHY_PLL_CTRL_16 0x0240
+#define DSI_DSIPHY_PLL_CTRL_17 0x0244
+#define DSI_DSIPHY_PLL_CTRL_18 0x0248
+#define DSI_DSIPHY_PLL_CTRL_19 0x024C
+#define DSI_DSIPHY_ANA_CTRL0 0x0260
+#define DSI_DSIPHY_ANA_CTRL1 0x0264
+#define DSI_DSIPHY_ANA_CTRL2 0x0268
+#define DSI_DSIPHY_ANA_CTRL3 0x026C
+#define DSI_DSIPHY_ANA_CTRL4 0x0270
+#define DSI_DSIPHY_ANA_CTRL5 0x0274
+#define DSI_DSIPHY_ANA_CTRL6 0x0278
+#define DSI_DSIPHY_ANA_CTRL7 0x027C
+#define DSI_DSIPHY_PLL_RDY 0x0280
+#define DSI_DSIPHY_PLL_ANA_STATUS0 0x0294
+#define DSI_DSIPHY_PLL_ANA_STATUS1 0x0298
+#define DSI_DSIPHY_PLL_ANA_STATUS2 0x029C
+#define DSI_DSIPHY_LN0_CFG0 0x0300
+#define DSI_DSIPHY_LN0_CFG1 0x0304
+#define DSI_DSIPHY_LN0_CFG2 0x0308
+#define DSI_DSIPHY_LN1_CFG0 0x0340
+#define DSI_DSIPHY_LN1_CFG1 0x0344
+#define DSI_DSIPHY_LN1_CFG2 0x0348
+#define DSI_DSIPHY_LN2_CFG0 0x0380
+#define DSI_DSIPHY_LN2_CFG1 0x0384
+#define DSI_DSIPHY_LN2_CFG2 0x0388
+#define DSI_DSIPHY_LN3_CFG0 0x03C0
+#define DSI_DSIPHY_LN3_CFG1 0x03C4
+#define DSI_DSIPHY_LN3_CFG2 0x03C8
+#define DSI_DSIPHY_LNCK_CFG0 0x0400
+#define DSI_DSIPHY_LNCK_CFG1 0x0404
+#define DSI_DSIPHY_LNCK_CFG2 0x0408
+#define DSI_DSIPHY_TIMING_CTRL_0 0x0440
+#define DSI_DSIPHY_TIMING_CTRL_1 0x0444
+#define DSI_DSIPHY_TIMING_CTRL_2 0x0448
+#define DSI_DSIPHY_TIMING_CTRL_3 0x044C
+#define DSI_DSIPHY_TIMING_CTRL_4 0x0450
+#define DSI_DSIPHY_TIMING_CTRL_5 0x0454
+#define DSI_DSIPHY_TIMING_CTRL_6 0x0458
+#define DSI_DSIPHY_TIMING_CTRL_7 0x045C
+#define DSI_DSIPHY_TIMING_CTRL_8 0x0460
+#define DSI_DSIPHY_TIMING_CTRL_9 0x0464
+#define DSI_DSIPHY_TIMING_CTRL_10 0x0468
+#define DSI_DSIPHY_TIMING_CTRL_11 0x046C
+#define DSI_DSIPHY_CTRL_0 0x0470
+#define DSI_DSIPHY_CTRL_1 0x0474
+#define DSI_DSIPHY_CTRL_2 0x0478
+#define DSI_DSIPHY_CTRL_3 0x047C
+#define DSI_DSIPHY_STRENGTH_CTRL_0 0x0480
+#define DSI_DSIPHY_STRENGTH_CTRL_1 0x0484
+#define DSI_DSIPHY_STRENGTH_CTRL_2 0x0488
+#define DSI_DSIPHY_LDO_CNTRL 0x04B0
+#define DSI_DSIPHY_REGULATOR_CTRL_0 0x0500
+#define DSI_DSIPHY_REGULATOR_CTRL_1 0x0504
+#define DSI_DSIPHY_REGULATOR_CTRL_2 0x0508
+#define DSI_DSIPHY_REGULATOR_CTRL_3 0x050C
+#define DSI_DSIPHY_REGULATOR_CTRL_4 0x0510
+#define DSI_DSIPHY_REGULATOR_TEST 0x0514
+#define DSI_DSIPHY_REGULATOR_CAL_PWR_CFG 0x0518
+#define DSI_DSIPHY_CAL_HW_TRIGGER 0x0528
+#define DSI_DSIPHY_CAL_SW_CFG0 0x052C
+#define DSI_DSIPHY_CAL_SW_CFG1 0x0530
+#define DSI_DSIPHY_CAL_SW_CFG2 0x0534
+#define DSI_DSIPHY_CAL_HW_CFG0 0x0538
+#define DSI_DSIPHY_CAL_HW_CFG1 0x053C
+#define DSI_DSIPHY_CAL_HW_CFG2 0x0540
+#define DSI_DSIPHY_CAL_HW_CFG3 0x0544
+#define DSI_DSIPHY_CAL_HW_CFG4 0x0548
+#define DSI_DSIPHY_REGULATOR_CAL_STATUS0 0x0550
+#define DSI_DSIPHY_BIST_CTRL0 0x048C
+#define DSI_DSIPHY_BIST_CTRL1 0x0490
+#define DSI_DSIPHY_BIST_CTRL2 0x0494
+#define DSI_DSIPHY_BIST_CTRL3 0x0498
+#define DSI_DSIPHY_BIST_CTRL4 0x049C
+#define DSI_DSIPHY_BIST_CTRL5 0x04A0
+
+#endif /* DSI_HOST_V2_H */
diff --git a/drivers/video/msm/mdss/dsi_io_v2.c b/drivers/video/msm/mdss/dsi_io_v2.c
new file mode 100644
index 0000000..0486c4c
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_io_v2.c
@@ -0,0 +1,426 @@
+/* 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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#include "dsi_v2.h"
+#include "dsi_io_v2.h"
+#include "dsi_host_v2.h"
+
+struct msm_dsi_io_private {
+ struct regulator *vdda_vreg;
+ struct clk *dsi_byte_clk;
+ struct clk *dsi_esc_clk;
+ struct clk *dsi_pixel_clk;
+ struct clk *dsi_ahb_clk;
+ int msm_dsi_clk_on;
+ int msm_dsi_ahb_clk_on;
+};
+
+static struct msm_dsi_io_private *dsi_io_private;
+
+#define DSI_VDDA_VOLTAGE 1200000
+
+void msm_dsi_ahb_ctrl(int enable)
+{
+ if (enable) {
+ if (dsi_io_private->msm_dsi_ahb_clk_on) {
+ pr_debug("ahb clks already ON\n");
+ return;
+ }
+ clk_enable(dsi_io_private->dsi_ahb_clk);
+ dsi_io_private->msm_dsi_ahb_clk_on = 1;
+ } else {
+ if (dsi_io_private->msm_dsi_ahb_clk_on == 0) {
+ pr_debug("ahb clk already OFF\n");
+ return;
+ }
+ clk_disable(dsi_io_private->dsi_ahb_clk);
+ dsi_io_private->msm_dsi_ahb_clk_on = 0;
+ }
+}
+
+int msm_dsi_io_init(struct platform_device *dev)
+{
+ int rc;
+
+ if (!dsi_io_private) {
+ dsi_io_private = kzalloc(sizeof(struct msm_dsi_io_private),
+ GFP_KERNEL);
+ if (!dsi_io_private) {
+ pr_err("fail to alloc dsi io private data structure\n");
+ return -ENOMEM;
+ }
+ }
+
+ rc = msm_dsi_clk_init(dev);
+ if (rc) {
+ pr_err("fail to initialize DSI clock\n");
+ return rc;
+ }
+
+ rc = msm_dsi_regulator_init(dev);
+ if (rc) {
+ pr_err("fail to initialize DSI regulator\n");
+ return rc;
+ }
+ return 0;
+}
+
+void msm_dsi_io_deinit(void)
+{
+ if (dsi_io_private) {
+ msm_dsi_clk_deinit();
+ msm_dsi_regulator_deinit();
+ kfree(dsi_io_private);
+ dsi_io_private = NULL;
+ }
+}
+
+int msm_dsi_clk_init(struct platform_device *dev)
+{
+ int rc = 0;
+
+ dsi_io_private->dsi_byte_clk = clk_get(&dev->dev, "byte_clk");
+ if (IS_ERR(dsi_io_private->dsi_byte_clk)) {
+ pr_err("can't find dsi byte_clk\n");
+ rc = PTR_ERR(dsi_io_private->dsi_byte_clk);
+ dsi_io_private->dsi_byte_clk = NULL;
+ return rc;
+ }
+
+ dsi_io_private->dsi_esc_clk = clk_get(&dev->dev, "esc_clk");
+ if (IS_ERR(dsi_io_private->dsi_esc_clk)) {
+ pr_err("can't find dsi esc_clk\n");
+ rc = PTR_ERR(dsi_io_private->dsi_esc_clk);
+ dsi_io_private->dsi_esc_clk = NULL;
+ return rc;
+ }
+
+ dsi_io_private->dsi_pixel_clk = clk_get(&dev->dev, "pixel_clk");
+ if (IS_ERR(dsi_io_private->dsi_pixel_clk)) {
+ pr_err("can't find dsi pixel\n");
+ rc = PTR_ERR(dsi_io_private->dsi_pixel_clk);
+ dsi_io_private->dsi_pixel_clk = NULL;
+ return rc;
+ }
+
+ dsi_io_private->dsi_ahb_clk = clk_get(&dev->dev, "iface_clk");
+ if (IS_ERR(dsi_io_private->dsi_ahb_clk)) {
+ pr_err("can't find dsi iface_clk\n");
+ rc = PTR_ERR(dsi_io_private->dsi_ahb_clk);
+ dsi_io_private->dsi_ahb_clk = NULL;
+ return rc;
+ }
+ clk_prepare(dsi_io_private->dsi_ahb_clk);
+
+ return 0;
+}
+
+void msm_dsi_clk_deinit(void)
+{
+ if (dsi_io_private->dsi_byte_clk) {
+ clk_put(dsi_io_private->dsi_byte_clk);
+ dsi_io_private->dsi_byte_clk = NULL;
+ }
+ if (dsi_io_private->dsi_esc_clk) {
+ clk_put(dsi_io_private->dsi_esc_clk);
+ dsi_io_private->dsi_esc_clk = NULL;
+ }
+ if (dsi_io_private->dsi_pixel_clk) {
+ clk_put(dsi_io_private->dsi_pixel_clk);
+ dsi_io_private->dsi_pixel_clk = NULL;
+ }
+ if (dsi_io_private->dsi_ahb_clk) {
+ clk_unprepare(dsi_io_private->dsi_ahb_clk);
+ clk_put(dsi_io_private->dsi_ahb_clk);
+ dsi_io_private->dsi_ahb_clk = NULL;
+ }
+}
+
+int msm_dsi_prepare_clocks(void)
+{
+ clk_prepare(dsi_io_private->dsi_byte_clk);
+ clk_prepare(dsi_io_private->dsi_esc_clk);
+ clk_prepare(dsi_io_private->dsi_pixel_clk);
+ return 0;
+}
+
+int msm_dsi_unprepare_clocks(void)
+{
+ clk_unprepare(dsi_io_private->dsi_esc_clk);
+ clk_unprepare(dsi_io_private->dsi_byte_clk);
+ clk_unprepare(dsi_io_private->dsi_pixel_clk);
+ return 0;
+}
+
+int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+ unsigned long pixel_rate)
+{
+ int rc;
+
+ rc = clk_set_rate(dsi_io_private->dsi_esc_clk, esc_rate);
+ if (rc) {
+ pr_err("dsi_esc_clk - clk_set_rate failed =%d\n", rc);
+ return rc;
+ }
+
+ rc = clk_set_rate(dsi_io_private->dsi_byte_clk, byte_rate);
+ if (rc) {
+ pr_err("dsi_byte_clk - clk_set_rate faile = %dd\n", rc);
+ return rc;
+ }
+
+ rc = clk_set_rate(dsi_io_private->dsi_pixel_clk, pixel_rate);
+ if (rc) {
+ pr_err("dsi_pixel_clk - clk_set_rate failed = %d\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+int msm_dsi_clk_enable(void)
+{
+ if (dsi_io_private->msm_dsi_clk_on) {
+ pr_debug("dsi_clks on already\n");
+ return 0;
+ }
+
+ clk_enable(dsi_io_private->dsi_esc_clk);
+ clk_enable(dsi_io_private->dsi_byte_clk);
+ clk_enable(dsi_io_private->dsi_pixel_clk);
+
+ dsi_io_private->msm_dsi_clk_on = 1;
+ return 0;
+}
+
+int msm_dsi_clk_disable(void)
+{
+ if (dsi_io_private->msm_dsi_clk_on == 0) {
+ pr_debug("mdss_dsi_clks already OFF\n");
+ return 0;
+ }
+
+ clk_disable(dsi_io_private->dsi_byte_clk);
+ clk_disable(dsi_io_private->dsi_esc_clk);
+ clk_disable(dsi_io_private->dsi_pixel_clk);
+
+ dsi_io_private->msm_dsi_clk_on = 0;
+ return 0;
+}
+
+int msm_dsi_regulator_init(struct platform_device *dev)
+{
+ int ret = 0;
+
+ dsi_io_private->vdda_vreg = devm_regulator_get(&dev->dev, "vdda");
+ if (IS_ERR(dsi_io_private->vdda_vreg)) {
+ ret = PTR_ERR(dsi_io_private->vdda_vreg);
+ pr_err("could not get vdda 8110_l4, ret=%d\n", ret);
+ return ret;
+ }
+
+ ret = regulator_set_voltage(dsi_io_private->vdda_vreg, DSI_VDDA_VOLTAGE,
+ DSI_VDDA_VOLTAGE);
+ if (ret)
+ pr_err("vdd_io_vreg->set_voltage failed, ret=%d\n", ret);
+
+ return ret;
+}
+
+void msm_dsi_regulator_deinit(void)
+{
+ if (dsi_io_private->vdda_vreg) {
+ devm_regulator_put(dsi_io_private->vdda_vreg);
+ dsi_io_private->vdda_vreg = NULL;
+ }
+}
+
+int msm_dsi_regulator_enable(void)
+{
+ int ret;
+
+ ret = regulator_enable(dsi_io_private->vdda_vreg);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator.\n", __func__);
+ return ret;
+ }
+ msleep(20); /*per DSI controller spec*/
+ return ret;
+}
+
+int msm_dsi_regulator_disable(void)
+{
+ int ret;
+
+ ret = regulator_disable(dsi_io_private->vdda_vreg);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator.\n", __func__);
+ return ret;
+ }
+ wmb();
+ msleep(20); /*per DSI controller spec*/
+
+ return ret;
+}
+
+static void msm_dsi_phy_strength_init(unsigned char *ctrl_base,
+ struct mdss_dsi_phy_ctrl *pd)
+{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_STRENGTH_CTRL_0, pd->strength[0]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_STRENGTH_CTRL_2, pd->strength[1]);
+}
+
+static void msm_dsi_phy_ctrl_init(unsigned char *ctrl_base,
+ struct mdss_panel_data *pdata)
+{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x5f);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_3, 0x10);
+}
+
+static void msm_dsi_phy_regulator_init(unsigned char *ctrl_base,
+ struct mdss_dsi_phy_ctrl *pd)
+{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_LDO_CNTRL, 0x04);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, pd->regulator[0]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_1, pd->regulator[1]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_2, pd->regulator[2]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_3, pd->regulator[3]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_4, pd->regulator[4]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CAL_PWR_CFG,
+ pd->regulator[5]);
+
+}
+
+static int msm_dsi_phy_calibration(unsigned char *ctrl_base)
+{
+ int i = 0, term_cnt = 5000, ret = 0, cal_busy;
+
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_SW_CFG2, 0x0);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG1, 0x5a);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG3, 0x10);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG4, 0x01);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_CFG0, 0x01);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_TRIGGER, 0x01);
+ usleep_range(5000, 5000); /*per DSI controller spec*/
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CAL_HW_TRIGGER, 0x00);
+
+ cal_busy = MIPI_INP(ctrl_base + DSI_DSIPHY_REGULATOR_CAL_STATUS0);
+ while (cal_busy & 0x10) {
+ i++;
+ if (i > term_cnt) {
+ ret = -EINVAL;
+ pr_err("msm_dsi_phy_calibration error\n");
+ break;
+ }
+ cal_busy = MIPI_INP(ctrl_base +
+ DSI_DSIPHY_REGULATOR_CAL_STATUS0);
+ }
+
+ return ret;
+}
+
+static void msm_dsi_phy_lane_init(unsigned char *ctrl_base,
+ struct mdss_dsi_phy_ctrl *pd)
+{
+ int ln, index;
+
+ /*CFG0, CFG1, CFG2, TEST_DATAPATH, TEST_STR0, TEST_STR1*/
+ for (ln = 0; ln < 5; ln++) {
+ unsigned char *off = ctrl_base + 0x0300 + (ln * 0x40);
+ index = ln * 6;
+ MIPI_OUTP(off, pd->laneCfg[index]);
+ MIPI_OUTP(off + 4, pd->laneCfg[index + 1]);
+ MIPI_OUTP(off + 8, pd->laneCfg[index + 2]);
+ MIPI_OUTP(off + 12, pd->laneCfg[index + 3]);
+ MIPI_OUTP(off + 20, pd->laneCfg[index + 4]);
+ MIPI_OUTP(off + 24, pd->laneCfg[index + 5]);
+ }
+ wmb();
+}
+
+static void msm_dsi_phy_timing_init(unsigned char *ctrl_base,
+ struct mdss_dsi_phy_ctrl *pd)
+{
+ int i, off = DSI_DSIPHY_TIMING_CTRL_0;
+ for (i = 0; i < 12; i++) {
+ MIPI_OUTP(ctrl_base + off, pd->timing[i]);
+ off += 4;
+ }
+ wmb();
+}
+
+static void msm_dsi_phy_bist_init(unsigned char *ctrl_base,
+ struct mdss_dsi_phy_ctrl *pd)
+{
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, pd->bistCtrl[4]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL1, pd->bistCtrl[1]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL0, pd->bistCtrl[0]);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_BIST_CTRL4, 0);
+ wmb();
+}
+
+int msm_dsi_phy_init(unsigned char *ctrl_base,
+ struct mdss_panel_data *pdata)
+{
+ struct mdss_dsi_phy_ctrl *pd;
+
+ pd = pdata->panel_info.mipi.dsi_phy_db;
+
+ msm_dsi_phy_strength_init(ctrl_base, pd);
+
+ msm_dsi_phy_ctrl_init(ctrl_base, pdata);
+
+ msm_dsi_phy_regulator_init(ctrl_base, pd);
+
+ msm_dsi_phy_calibration(ctrl_base);
+
+ msm_dsi_phy_lane_init(ctrl_base, pd);
+
+ msm_dsi_phy_timing_init(ctrl_base, pd);
+
+ msm_dsi_phy_bist_init(ctrl_base, pd);
+
+ return 0;
+}
+
+void msm_dsi_phy_sw_reset(unsigned char *ctrl_base)
+{
+ /* start phy sw reset */
+ MIPI_OUTP(ctrl_base + DSI_PHY_SW_RESET, 0x0001);
+ udelay(1000); /*per DSI controller spec*/
+ wmb();
+ /* end phy sw reset */
+ MIPI_OUTP(ctrl_base + DSI_PHY_SW_RESET, 0x0000);
+ udelay(100); /*per DSI controller spec*/
+ wmb();
+}
+
+void msm_dsi_phy_enable(unsigned char *ctrl_base, int on)
+{
+ if (on) {
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x050);
+ } else {
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_PLL_CTRL_5, 0x05f);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_REGULATOR_CTRL_0, 0x02);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_0, 0x00);
+ MIPI_OUTP(ctrl_base + DSI_DSIPHY_CTRL_1, 0x7f);
+ MIPI_OUTP(ctrl_base + DSI_CLK_CTRL, 0);
+ }
+}
diff --git a/drivers/video/msm/mdss/dsi_io_v2.h b/drivers/video/msm/mdss/dsi_io_v2.h
new file mode 100644
index 0000000..25ecd7f
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_io_v2.h
@@ -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.
+ *
+ */
+#ifndef DSI_IO_V2_H
+#define DSI_IO_V2_H
+
+#include "mdss_panel.h"
+
+void msm_dsi_ahb_ctrl(int enable);
+
+int msm_dsi_io_init(struct platform_device *dev);
+
+void msm_dsi_io_deinit(void);
+
+int msm_dsi_clk_init(struct platform_device *dev);
+
+void msm_dsi_clk_deinit(void);
+
+int msm_dsi_prepare_clocks(void);
+
+int msm_dsi_unprepare_clocks(void);
+
+int msm_dsi_clk_set_rate(unsigned long esc_rate, unsigned long byte_rate,
+ unsigned long pixel_rate);
+
+int msm_dsi_clk_enable(void);
+
+int msm_dsi_clk_disable(void);
+
+int msm_dsi_regulator_init(struct platform_device *dev);
+
+void msm_dsi_regulator_deinit(void);
+
+int msm_dsi_regulator_enable(void);
+
+int msm_dsi_regulator_disable(void);
+
+int msm_dsi_phy_init(unsigned char *ctrl_base,
+ struct mdss_panel_data *pdata);
+
+void msm_dsi_phy_sw_reset(unsigned char *ctrl_base);
+
+#endif /* DSI_IO_V2_H */
diff --git a/drivers/video/msm/mdss/dsi_panel_v2.c b/drivers/video/msm/mdss/dsi_panel_v2.c
new file mode 100644
index 0000000..6686de3
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_panel_v2.c
@@ -0,0 +1,753 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
+#include <linux/qpnp/pin.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/regulator/consumer.h>
+
+#include "dsi_v2.h"
+
+#define DT_CMD_HDR 6
+
+struct dsi_panel_private {
+ struct dsi_buf dsi_panel_tx_buf;
+ struct dsi_buf dsi_panel_rx_buf;
+
+ int rst_gpio;
+ int disp_en_gpio;
+ char bl_ctrl;
+
+ struct regulator *vddio_vreg;
+ struct regulator *vdda_vreg;
+
+ struct dsi_panel_cmds_list *on_cmds_list;
+ struct dsi_panel_cmds_list *off_cmds_list;
+ struct mdss_dsi_phy_ctrl phy_params;
+};
+
+static struct dsi_panel_private *panel_private;
+
+DEFINE_LED_TRIGGER(bl_led_trigger);
+
+int dsi_panel_init(void)
+{
+ int rc;
+
+ if (!panel_private) {
+ panel_private = kzalloc(sizeof(struct dsi_panel_private),
+ GFP_KERNEL);
+ if (!panel_private) {
+ pr_err("fail to alloc dsi panel private data\n");
+ return -ENOMEM;
+ }
+ }
+
+ rc = dsi_buf_alloc(&panel_private->dsi_panel_tx_buf,
+ ALIGN(DSI_BUF_SIZE,
+ SZ_4K));
+ if (rc)
+ return rc;
+
+ rc = dsi_buf_alloc(&panel_private->dsi_panel_rx_buf,
+ ALIGN(DSI_BUF_SIZE,
+ SZ_4K));
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+void dsi_panel_deinit(void)
+{
+ if (!panel_private)
+ return;
+
+ kfree(panel_private->dsi_panel_tx_buf.start);
+ kfree(panel_private->dsi_panel_rx_buf.start);
+
+ if (panel_private->vddio_vreg)
+ devm_regulator_put(panel_private->vddio_vreg);
+
+ if (panel_private->vdda_vreg)
+ devm_regulator_put(panel_private->vddio_vreg);
+
+ kfree(panel_private);
+ panel_private = NULL;
+}
+
+void dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
+{
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ if (!gpio_is_valid(panel_private->disp_en_gpio)) {
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+ }
+
+ if (!gpio_is_valid(panel_private->rst_gpio)) {
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+ return;
+ }
+
+ pr_debug("%s: enable = %d\n", __func__, enable);
+
+ if (enable) {
+ gpio_set_value(panel_private->rst_gpio, 1);
+ /*
+ * these delay values are by experiments currently, will need
+ * to move to device tree late
+ */
+ msleep(20);
+ gpio_set_value(panel_private->rst_gpio, 0);
+ udelay(200);
+ gpio_set_value(panel_private->rst_gpio, 1);
+ msleep(20);
+ if (gpio_is_valid(panel_private->disp_en_gpio))
+ gpio_set_value(panel_private->disp_en_gpio, 1);
+ } else {
+ gpio_set_value(panel_private->rst_gpio, 0);
+ if (gpio_is_valid(panel_private->disp_en_gpio))
+ gpio_set_value(panel_private->disp_en_gpio, 0);
+ }
+}
+
+static void dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
+ u32 bl_level)
+{
+ if (panel_private->bl_ctrl) {
+ switch (panel_private->bl_ctrl) {
+ case BL_WLED:
+ led_trigger_event(bl_led_trigger, bl_level);
+ break;
+
+ default:
+ pr_err("%s: Unknown bl_ctrl configuration\n",
+ __func__);
+ break;
+ }
+ } else
+ pr_err("%s:%d, bl_ctrl not configured", __func__, __LINE__);
+}
+
+static int dsi_panel_on(struct mdss_panel_data *pdata)
+{
+ struct mipi_panel_info *mipi;
+
+ mipi = &pdata->panel_info.mipi;
+
+ pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
+ mipi->mode);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+ panel_private->on_cmds_list->buf,
+ panel_private->on_cmds_list->size);
+ } else {
+ pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dsi_panel_off(struct mdss_panel_data *pdata)
+{
+ struct mipi_panel_info *mipi;
+ mipi = &pdata->panel_info.mipi;
+
+ pr_debug("%s:%d, debug info\n", __func__, __LINE__);
+
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ dsi_cmds_tx_v2(pdata, &panel_private->dsi_panel_tx_buf,
+ panel_private->off_cmds_list->buf,
+ panel_private->off_cmds_list->size);
+ } else {
+ pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dsi_panel_parse_gpio(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ panel_private->disp_en_gpio = of_get_named_gpio(np,
+ "qcom,enable-gpio", 0);
+ panel_private->rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
+ return 0;
+}
+
+static int dsi_panel_parse_regulator(struct platform_device *pdev)
+{
+ panel_private->vddio_vreg = devm_regulator_get(&pdev->dev, "vddio");
+ panel_private->vdda_vreg = devm_regulator_get(&pdev->dev, "vdda");
+ return 0;
+}
+
+static int dsi_panel_parse_timing(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ u32 res[6], tmp;
+ int rc;
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
+ if (rc) {
+ pr_err("%s:%d, panel resolution not specified\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ panel_data->panel_info.xres = (!rc ? res[0] : 480);
+ panel_data->panel_info.yres = (!rc ? res[1] : 800);
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
+ if (rc == 0) {
+ panel_data->panel_info.lcdc.xres_pad =
+ panel_data->panel_info.xres - res[0];
+ panel_data->panel_info.lcdc.yres_pad =
+ panel_data->panel_info.yres - res[1];
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
+ if (rc) {
+ pr_err("%s:%d, panel bpp not specified\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_data->panel_info.bpp = (!rc ? tmp : 24);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-porch-values", res, 6);
+ if (rc) {
+ pr_err("%s:%d, panel porch not specified\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ panel_data->panel_info.lcdc.h_back_porch = (!rc ? res[0] : 6);
+ panel_data->panel_info.lcdc.h_pulse_width = (!rc ? res[1] : 2);
+ panel_data->panel_info.lcdc.h_front_porch = (!rc ? res[2] : 6);
+ panel_data->panel_info.lcdc.v_back_porch = (!rc ? res[3] : 6);
+ panel_data->panel_info.lcdc.v_pulse_width = (!rc ? res[4] : 2);
+ panel_data->panel_info.lcdc.v_front_porch = (!rc ? res[5] : 6);
+
+ return 0;
+}
+
+static int dsi_panel_parse_phy(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ u32 res[6], tmp;
+ int i, len, rc;
+ const char *data;
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
+ panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
+ panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-h-power-stop", res, 3);
+ panel_data->panel_info.mipi.hbp_power_stop = (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.hsa_power_stop = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.hfp_power_stop = (!rc ? res[2] : false);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-bllp-power-stop", res, 2);
+ panel_data->panel_info.mipi.bllp_power_stop =
+ (!rc ? res[0] : false);
+ panel_data->panel_info.mipi.eof_bllp_power_stop =
+ (!rc ? res[1] : false);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-traffic-mode", &tmp);
+ panel_data->panel_info.mipi.traffic_mode =
+ (!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-dsi-dst-format", &tmp);
+ panel_data->panel_info.mipi.dst_format =
+ (!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-vc", &tmp);
+ panel_data->panel_info.mipi.vc = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-rgb-swap", &tmp);
+ panel_data->panel_info.mipi.rgb_swap = (!rc ? tmp : DSI_RGB_SWAP_RGB);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,mdss-pan-dsi-data-lanes", res, 4);
+ panel_data->panel_info.mipi.data_lane0 = (!rc ? res[0] : true);
+ panel_data->panel_info.mipi.data_lane1 = (!rc ? res[1] : false);
+ panel_data->panel_info.mipi.data_lane2 = (!rc ? res[2] : false);
+ panel_data->panel_info.mipi.data_lane3 = (!rc ? res[3] : false);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dlane-swap", &tmp);
+ panel_data->panel_info.mipi.dlane_swap = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-dsi-t-clk", res, 2);
+ panel_data->panel_info.mipi.t_clk_pre = (!rc ? res[0] : 0x24);
+ panel_data->panel_info.mipi.t_clk_post = (!rc ? res[1] : 0x03);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-stream", &tmp);
+ panel_data->panel_info.mipi.stream = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mdp-tr", &tmp);
+ panel_data->panel_info.mipi.mdp_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.mdp_trigger > 6) {
+ pr_err("%s:%d, Invalid mdp trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.mdp_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-dma-tr", &tmp);
+ panel_data->panel_info.mipi.dma_trigger =
+ (!rc ? tmp : DSI_CMD_TRIGGER_SW);
+ if (panel_data->panel_info.mipi.dma_trigger > 6) {
+ pr_err("%s:%d, Invalid dma trigger. Forcing to sw trigger",
+ __func__, __LINE__);
+ panel_data->panel_info.mipi.dma_trigger =
+ DSI_CMD_TRIGGER_SW;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
+ panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+
+ data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy regulator settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ panel_private->phy_params.regulator[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
+ if ((!data) || (len != 12)) {
+ pr_err("%s:%d, Unable to read Phy timing settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ panel_private->phy_params.timing[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
+ if ((!data) || (len != 2)) {
+ pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_private->phy_params.strength[0] = data[0];
+ panel_private->phy_params.strength[1] = data[1];
+
+ data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ panel_private->phy_params.bistCtrl[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
+ if ((!data) || (len != 30)) {
+ pr_err("%s:%d, Unable to read Phy lane configure settings",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ for (i = 0; i < len; i++)
+ panel_private->phy_params.laneCfg[i] = data[i];
+
+ panel_data->panel_info.mipi.dsi_phy_db = &panel_private->phy_params;
+ return 0;
+}
+
+static int dsi_panel_parse_init_cmds(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int i, len;
+ int cmd_plen, data_offset;
+ const char *data;
+ const char *on_cmds_state, *off_cmds_state;
+ char *on_cmds = NULL, *off_cmds = NULL;
+ int num_of_on_cmds = 0, num_of_off_cmds = 0;
+
+ data = of_get_property(np, "qcom,panel-on-cmds", &len);
+ if (!data) {
+ pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!on_cmds)
+ goto parse_init_cmds_error;
+
+ memcpy(on_cmds, data, len);
+
+ data_offset = 0;
+ cmd_plen = 0;
+ while ((len - data_offset) >= DT_CMD_HDR) {
+ data_offset += (DT_CMD_HDR - 1);
+ cmd_plen = on_cmds[data_offset++];
+ data_offset += cmd_plen;
+ num_of_on_cmds++;
+ }
+ if (!num_of_on_cmds) {
+ pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ panel_data->dsi_panel_on_cmds =
+ kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+ if (!panel_data->dsi_panel_on_cmds)
+ goto parse_init_cmds_error;
+
+ (panel_data->dsi_panel_on_cmds)->buf =
+ kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
+ GFP_KERNEL);
+ if (!(panel_data->dsi_panel_on_cmds)->buf)
+ goto parse_init_cmds_error;
+
+ data_offset = 0;
+ for (i = 0; i < num_of_on_cmds; i++) {
+ panel_data->dsi_panel_on_cmds->buf[i].dtype =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].last =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].vc =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].ack =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].wait =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].dlen =
+ on_cmds[data_offset++];
+ panel_data->dsi_panel_on_cmds->buf[i].payload =
+ &on_cmds[data_offset];
+ data_offset += (panel_data->dsi_panel_on_cmds->buf[i].dlen);
+ }
+
+ if (data_offset != len) {
+ pr_err("%s:%d, Incorrect ON command entries",
+ __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ (panel_data->dsi_panel_on_cmds)->size = num_of_on_cmds;
+
+ on_cmds_state = of_get_property(pdev->dev.of_node,
+ "qcom,on-cmds-dsi-state", NULL);
+ if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
+ (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+ } else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
+ (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_HS_MODE;
+ } else {
+ pr_debug("%s: ON cmds state not specified. Set Default\n",
+ __func__);
+ (panel_data->dsi_panel_on_cmds)->ctrl_state = DSI_LP_MODE;
+ }
+
+ panel_private->on_cmds_list = panel_data->dsi_panel_on_cmds;
+ data = of_get_property(np, "qcom,panel-off-cmds", &len);
+ if (!data) {
+ pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
+ if (!off_cmds)
+ goto parse_init_cmds_error;
+
+ memcpy(off_cmds, data, len);
+
+ data_offset = 0;
+ cmd_plen = 0;
+ while ((len - data_offset) >= DT_CMD_HDR) {
+ data_offset += (DT_CMD_HDR - 1);
+ cmd_plen = off_cmds[data_offset++];
+ data_offset += cmd_plen;
+ num_of_off_cmds++;
+ }
+ if (!num_of_off_cmds) {
+ pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ panel_data->dsi_panel_off_cmds =
+ kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
+ if (!panel_data->dsi_panel_off_cmds)
+ goto parse_init_cmds_error;
+
+ (panel_data->dsi_panel_off_cmds)->buf = kzalloc(num_of_off_cmds
+ * sizeof(struct dsi_cmd_desc),
+ GFP_KERNEL);
+ if (!(panel_data->dsi_panel_off_cmds)->buf)
+ goto parse_init_cmds_error;
+
+ data_offset = 0;
+ for (i = 0; i < num_of_off_cmds; i++) {
+ panel_data->dsi_panel_off_cmds->buf[i].dtype =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].last =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].vc =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].ack =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].wait =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].dlen =
+ off_cmds[data_offset++];
+ panel_data->dsi_panel_off_cmds->buf[i].payload =
+ &off_cmds[data_offset];
+ data_offset += (panel_data->dsi_panel_off_cmds->buf[i].dlen);
+ }
+
+ if (data_offset != len) {
+ pr_err("%s:%d, Incorrect OFF command entries",
+ __func__, __LINE__);
+ goto parse_init_cmds_error;
+ }
+
+ (panel_data->dsi_panel_off_cmds)->size = num_of_off_cmds;
+ off_cmds_state = of_get_property(pdev->dev.of_node,
+ "qcom,off-cmds-dsi-state", NULL);
+ if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
+ (panel_data->dsi_panel_off_cmds)->ctrl_state =
+ DSI_LP_MODE;
+ } else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
+ (panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_HS_MODE;
+ } else {
+ pr_debug("%s: ON cmds state not specified. Set Default\n",
+ __func__);
+ (panel_data->dsi_panel_off_cmds)->ctrl_state = DSI_LP_MODE;
+ }
+
+ panel_private->off_cmds_list = panel_data->dsi_panel_on_cmds;
+ kfree(on_cmds);
+ kfree(off_cmds);
+
+ return 0;
+parse_init_cmds_error:
+ if (panel_data->dsi_panel_on_cmds) {
+ kfree((panel_data->dsi_panel_on_cmds)->buf);
+ kfree(panel_data->dsi_panel_on_cmds);
+ panel_data->dsi_panel_on_cmds = NULL;
+ }
+ if (panel_data->dsi_panel_off_cmds) {
+ kfree((panel_data->dsi_panel_off_cmds)->buf);
+ kfree(panel_data->dsi_panel_off_cmds);
+ panel_data->dsi_panel_off_cmds = NULL;
+ }
+
+ kfree(on_cmds);
+ kfree(off_cmds);
+ return -EINVAL;
+}
+
+static int dsi_panel_parse_backlight(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data,
+ char *bl_ctrl)
+{
+ int rc;
+ u32 res[6];
+ static const char *bl_ctrl_type;
+
+ bl_ctrl_type = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pan-bl-ctrl", NULL);
+ if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
+ led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
+ pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
+ *bl_ctrl = BL_WLED;
+ }
+
+ rc = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,mdss-pan-bl-levels", res, 2);
+ panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
+ panel_data->panel_info.bl_max = (!rc ? res[1] : 255);
+ return rc;
+}
+
+static int dsi_panel_parse_other(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data)
+{
+ const char *pdest;
+ u32 tmp;
+ int rc;
+
+ pdest = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pan-dest", NULL);
+ if (strlen(pdest) != 9) {
+ pr_err("%s: Unknown pdest specified\n", __func__);
+ return -EINVAL;
+ }
+ if (!strncmp(pdest, "display_1", 9)) {
+ panel_data->panel_info.pdest = DISPLAY_1;
+ } else if (!strncmp(pdest, "display_2", 9)) {
+ panel_data->panel_info.pdest = DISPLAY_2;
+ } else {
+ pr_debug("%s: pdest not specified. Set Default\n",
+ __func__);
+ panel_data->panel_info.pdest = DISPLAY_1;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,mdss-pan-underflow-clr", &tmp);
+ panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+
+ return rc;
+}
+
+static int dsi_panel_parse_dt(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data,
+ char *bl_ctrl)
+{
+ int rc;
+
+ rc = dsi_panel_parse_gpio(pdev);
+ if (rc) {
+ pr_err("fail to parse panel GPIOs\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_regulator(pdev);
+ if (rc) {
+ pr_err("fail to parse panel regulators\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_timing(pdev, panel_data);
+ if (rc) {
+ pr_err("fail to parse panel timing\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_phy(pdev, panel_data);
+ if (rc) {
+ pr_err("fail to parse DSI PHY settings\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_backlight(pdev, panel_data, bl_ctrl);
+ if (rc) {
+ pr_err("fail to parse DSI backlight\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_other(pdev, panel_data);
+ if (rc) {
+ pr_err("fail to parse DSI panel destination\n");
+ return rc;
+ }
+
+ rc = dsi_panel_parse_init_cmds(pdev, panel_data);
+ if (rc) {
+ pr_err("fail to parse DSI init commands\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static int __devinit dsi_panel_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ static struct dsi_panel_common_pdata vendor_pdata;
+ static const char *panel_name;
+
+ pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ panel_name = of_get_property(pdev->dev.of_node, "label", NULL);
+ if (!panel_name)
+ pr_debug("%s:%d, panel name not specified\n",
+ __func__, __LINE__);
+ else
+ pr_debug("%s: Panel Name = %s\n", __func__, panel_name);
+
+ rc = dsi_panel_init();
+ if (rc) {
+ pr_err("dsi_panel_init failed %d\n", rc);
+ goto dsi_panel_probe_error;
+
+ }
+ rc = dsi_panel_parse_dt(pdev, &vendor_pdata, &panel_private->bl_ctrl);
+ if (rc) {
+ pr_err("dsi_panel_parse_dt failed %d\n", rc);
+ goto dsi_panel_probe_error;
+ }
+
+ vendor_pdata.on = dsi_panel_on;
+ vendor_pdata.off = dsi_panel_off;
+ vendor_pdata.bl_fnc = dsi_panel_bl_ctrl;
+
+ rc = dsi_panel_device_register_v2(pdev, &vendor_pdata,
+ panel_private->bl_ctrl);
+
+ if (rc) {
+ pr_err("dsi_panel_device_register_v2 failed %d\n", rc);
+ goto dsi_panel_probe_error;
+ }
+
+ return 0;
+dsi_panel_probe_error:
+ dsi_panel_deinit();
+ return rc;
+}
+
+static int __devexit dsi_panel_remove(struct platform_device *pdev)
+{
+ dsi_panel_deinit();
+ return 0;
+}
+
+
+static const struct of_device_id dsi_panel_match[] = {
+ {.compatible = "qcom,dsi-panel-v2"},
+ {}
+};
+
+static struct platform_driver this_driver = {
+ .probe = dsi_panel_probe,
+ .remove = __devexit_p(dsi_panel_remove),
+ .driver = {
+ .name = "dsi_v2_panel",
+ .of_match_table = dsi_panel_match,
+ },
+};
+
+static int __init dsi_panel_module_init(void)
+{
+ return platform_driver_register(&this_driver);
+}
+module_init(dsi_panel_module_init);
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
new file mode 100644
index 0000000..5e46bf5
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -0,0 +1,789 @@
+/* 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
+ * 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/delay.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.h>
+
+#include "mdss_panel.h"
+#include "dsi_v2.h"
+
+static struct dsi_panel_common_pdata *panel_common_data;
+static struct dsi_interface dsi_intf;
+
+static int dsi_off(struct mdss_panel_data *pdata)
+{
+ int rc = 0;
+ if (!panel_common_data || !pdata)
+ return -ENODEV;
+
+ if (dsi_intf.off)
+ rc = dsi_intf.off(pdata);
+
+ if (rc) {
+ pr_err("mdss_dsi_off DSI failed %d\n", rc);
+ return rc;
+ }
+
+ pr_debug("dsi_off reset\n");
+ if (panel_common_data->off)
+ panel_common_data->off(pdata);
+
+ return rc;
+}
+
+static int dsi_on(struct mdss_panel_data *pdata)
+{
+ int rc = 0;
+
+ pr_debug("dsi_on\n");
+
+ if (!panel_common_data || !pdata)
+ return -ENODEV;
+
+ if (panel_common_data->reset)
+ panel_common_data->reset(1);
+
+ pr_debug("dsi_on DSI controller ont\n");
+ if (dsi_intf.on)
+ rc = dsi_intf.on(pdata);
+
+ if (rc) {
+ pr_err("mdss_dsi_on DSI failed %d\n", rc);
+ return rc;
+ }
+
+ pr_debug("dsi_on DSI panel ont\n");
+ if (panel_common_data->on)
+ rc = panel_common_data->on(pdata);
+
+ if (rc) {
+ pr_err("mdss_dsi_on panel failed %d\n", rc);
+ return rc;
+ }
+ return rc;
+}
+
+static int dsi_event_handler(struct mdss_panel_data *pdata,
+ int event, void *arg)
+{
+ int rc = 0;
+
+ if (!pdata || !panel_common_data) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -ENODEV;
+ }
+
+ switch (event) {
+ case MDSS_EVENT_PANEL_ON:
+ rc = dsi_on(pdata);
+ break;
+ case MDSS_EVENT_PANEL_OFF:
+ rc = dsi_off(pdata);
+ break;
+ default:
+ pr_debug("%s: unhandled event=%d\n", __func__, event);
+ break;
+ }
+ return rc;
+}
+
+static struct platform_device *get_dsi_platform_device(
+ struct platform_device *dev)
+{
+ struct device_node *dsi_ctrl_np;
+ struct platform_device *ctrl_pdev;
+
+ dsi_ctrl_np = of_parse_phandle(dev->dev.of_node,
+ "qcom,dsi-ctrl-phandle", 0);
+
+ if (!dsi_ctrl_np)
+ return NULL;
+
+ ctrl_pdev = of_find_device_by_node(dsi_ctrl_np);
+ if (!ctrl_pdev)
+ return NULL;
+
+ return ctrl_pdev;
+}
+
+int dsi_panel_device_register_v2(struct platform_device *dev,
+ struct dsi_panel_common_pdata *panel_data,
+ char backlight_ctrl)
+{
+ struct mipi_panel_info *mipi;
+ struct platform_device *ctrl_pdev;
+ int rc;
+ u8 lanes = 0, bpp;
+ u32 h_period, v_period;
+ static struct mdss_panel_data dsi_panel_data;
+
+ h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
+ + (panel_data->panel_info.lcdc.h_back_porch)
+ + (panel_data->panel_info.xres)
+ + (panel_data->panel_info.lcdc.h_front_porch));
+
+ v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
+ + (panel_data->panel_info.lcdc.v_back_porch)
+ + (panel_data->panel_info.yres)
+ + (panel_data->panel_info.lcdc.v_front_porch));
+
+ mipi = &panel_data->panel_info.mipi;
+
+ panel_data->panel_info.type =
+ ((mipi->mode == DSI_VIDEO_MODE)
+ ? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
+
+ if (mipi->data_lane3)
+ lanes += 1;
+ if (mipi->data_lane2)
+ lanes += 1;
+ if (mipi->data_lane1)
+ lanes += 1;
+ if (mipi->data_lane0)
+ lanes += 1;
+
+
+ if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
+ bpp = 3;
+ else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
+ || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
+ bpp = 2;
+ else
+ bpp = 3; /* Default format set to RGB888 */
+
+ if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
+ !panel_data->panel_info.clk_rate) {
+ h_period += panel_data->panel_info.lcdc.xres_pad;
+ v_period += panel_data->panel_info.lcdc.yres_pad;
+
+ if (lanes > 0) {
+ panel_data->panel_info.clk_rate =
+ ((h_period * v_period * (mipi->frame_rate) * bpp * 8)
+ / lanes);
+ } else {
+ pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
+ panel_data->panel_info.clk_rate =
+ (h_period * v_period
+ * (mipi->frame_rate) * bpp * 8);
+ }
+ }
+
+ ctrl_pdev = get_dsi_platform_device(dev);
+ if (!ctrl_pdev)
+ return -EPROBE_DEFER;
+
+ dsi_panel_data.event_handler = dsi_event_handler;
+
+ dsi_panel_data.panel_info = panel_data->panel_info;
+
+ dsi_panel_data.set_backlight = panel_data->bl_fnc;
+ panel_common_data = panel_data;
+ /*
+ * register in mdp driver
+ */
+ rc = mdss_register_panel(ctrl_pdev, &dsi_panel_data);
+ if (rc) {
+ dev_err(&dev->dev, "unable to register MIPI DSI panel\n");
+ return rc;
+ }
+
+ pr_debug("%s: Panal data initialized\n", __func__);
+ return 0;
+}
+
+void dsi_register_interface(struct dsi_interface *intf)
+{
+ dsi_intf = *intf;
+}
+
+int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
+ int cnt)
+{
+ int rc = 0;
+
+ if (!dsi_intf.tx)
+ return -EINVAL;
+
+ rc = dsi_intf.tx(pdata, tp, cmds, cnt);
+ return rc;
+}
+
+int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int rlen)
+{
+ int rc = 0;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!dsi_intf.rx)
+ return -EINVAL;
+
+ rc = dsi_intf.rx(pdata, tp, rp, cmds, rlen);
+ return rc;
+}
+
+static char *dsi_buf_reserve(struct dsi_buf *dp, int len)
+{
+ dp->data += len;
+ return dp->data;
+}
+
+
+static char *dsi_buf_push(struct dsi_buf *dp, int len)
+{
+ dp->data -= len;
+ dp->len += len;
+ return dp->data;
+}
+
+static char *dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen)
+{
+ dp->hdr = (u32 *)dp->data;
+ return dsi_buf_reserve(dp, hlen);
+}
+
+char *dsi_buf_init(struct dsi_buf *dp)
+{
+ int off;
+
+ dp->data = dp->start;
+ off = (int)dp->data;
+ /* 8 byte align */
+ off &= 0x07;
+ if (off)
+ off = 8 - off;
+ dp->data += off;
+ dp->len = 0;
+ return dp->data;
+}
+
+int dsi_buf_alloc(struct dsi_buf *dp, int size)
+{
+ dp->start = kmalloc(size, GFP_KERNEL);
+ if (dp->start == NULL) {
+ pr_err("%s:%u\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ dp->end = dp->start + size;
+ dp->size = size;
+
+ if ((int)dp->start & 0x07) {
+ pr_err("%s: buf NOT 8 bytes aligned\n", __func__);
+ return -EINVAL;
+ }
+
+ dp->data = dp->start;
+ dp->len = 0;
+ return 0;
+}
+
+/*
+ * mipi dsi generic long write
+ */
+static int dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ u32 *hp;
+ int i, len;
+
+ bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /* fill up payload */
+ if (cm->payload) {
+ len = cm->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < cm->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi generic short write with 0, 1 2 parameters
+ */
+static int dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi gerneric read with 0, 1 2 parameters
+ */
+static int dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->dlen && cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (cm->dlen > 2) ? 2 : cm->dlen;
+
+ if (len == 1) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(0);
+ } else if (len == 2) {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ2);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+ } else {
+ *hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ);
+ *hp |= DSI_HDR_DATA1(0);
+ *hp |= DSI_HDR_DATA2(0);
+ }
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs long write
+ */
+static int dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ char *bp;
+ u32 *hp;
+ int i, len;
+
+ bp = dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+
+ /*
+ * fill up payload
+ * dcs command byte (first byte) followed by payload
+ */
+ if (cm->payload) {
+ len = cm->dlen;
+ len += 3;
+ len &= ~0x03; /* multipled by 4 */
+ for (i = 0; i < cm->dlen; i++)
+ *bp++ = cm->payload[i];
+
+ /* append 0xff to the end */
+ for (; i < len; i++)
+ *bp++ = 0xff;
+
+ dp->len += len;
+ }
+
+ /* fill up header */
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 0 parameters
+ */
+static int dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+ int len;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->ack)
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ len = (cm->dlen > 1) ? 1 : cm->dlen;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs short write with 1 parameters
+ */
+static int dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->dlen < 2 || cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ if (cm->ack)
+ *hp |= DSI_HDR_BTA;
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs comamnd byte */
+ *hp |= DSI_HDR_DATA2(cm->payload[1]); /* parameter */
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len;
+}
+
+/*
+ * mipi dsi dcs read with 0 parameters
+ */
+static int dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return -EINVAL;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_BTA;
+ *hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]); /* dcs command byte */
+ *hp |= DSI_HDR_DATA2(0);
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ if (cm->payload == 0) {
+ pr_err("%s: NO payload error\n", __func__);
+ return 0;
+ }
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ *hp |= DSI_HDR_DATA1(cm->payload[0]);
+ *hp |= DSI_HDR_DATA2(cm->payload[1]);
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+static int dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ u32 *hp;
+
+ dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
+ hp = dp->hdr;
+ *hp = 0;
+ *hp = DSI_HDR_WC(cm->dlen);
+ *hp |= DSI_HDR_LONG_PKT;
+ *hp |= DSI_HDR_VC(cm->vc);
+ *hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
+ if (cm->last)
+ *hp |= DSI_HDR_LAST;
+
+ dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
+
+ return dp->len; /* 4 bytes */
+}
+
+/*
+ * prepare cmd buffer to be txed
+ */
+int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
+{
+ int len = 0;
+
+ switch (cm->dtype) {
+ case DTYPE_GEN_WRITE:
+ case DTYPE_GEN_WRITE1:
+ case DTYPE_GEN_WRITE2:
+ len = dsi_generic_swrite(dp, cm);
+ break;
+ case DTYPE_GEN_LWRITE:
+ len = dsi_generic_lwrite(dp, cm);
+ break;
+ case DTYPE_GEN_READ:
+ case DTYPE_GEN_READ1:
+ case DTYPE_GEN_READ2:
+ len = dsi_generic_read(dp, cm);
+ break;
+ case DTYPE_DCS_LWRITE:
+ len = dsi_dcs_lwrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE:
+ len = dsi_dcs_swrite(dp, cm);
+ break;
+ case DTYPE_DCS_WRITE1:
+ len = dsi_dcs_swrite1(dp, cm);
+ break;
+ case DTYPE_DCS_READ:
+ len = dsi_dcs_read(dp, cm);
+ break;
+ case DTYPE_MAX_PKTSIZE:
+ len = dsi_set_max_pktsize(dp, cm);
+ break;
+ case DTYPE_NULL_PKT:
+ len = dsi_null_pkt(dp, cm);
+ break;
+ case DTYPE_BLANK_PKT:
+ len = dsi_blank_pkt(dp, cm);
+ break;
+ case DTYPE_CM_ON:
+ len = dsi_cm_on(dp, cm);
+ break;
+ case DTYPE_CM_OFF:
+ len = dsi_cm_off(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_ON:
+ len = dsi_peripheral_on(dp, cm);
+ break;
+ case DTYPE_PERIPHERAL_OFF:
+ len = dsi_peripheral_off(dp, cm);
+ break;
+ default:
+ pr_debug("%s: dtype=%x NOT supported\n",
+ __func__, cm->dtype);
+ break;
+
+ }
+
+ return len;
+}
+
+/*
+ * mdss_dsi_short_read1_resp: 1 parameter
+ */
+int dsi_short_read1_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 1;
+ return rp->len;
+}
+
+/*
+ * mdss_dsi_short_read2_resp: 2 parameter
+ */
+int dsi_short_read2_resp(struct dsi_buf *rp)
+{
+ /* strip out dcs type */
+ rp->data++;
+ rp->len = 2;
+ return rp->len;
+}
+
+int dsi_long_read_resp(struct dsi_buf *rp)
+{
+ short len;
+
+ len = rp->data[2];
+ len <<= 8;
+ len |= rp->data[1];
+ /* strip out dcs header */
+ rp->data += 4;
+ rp->len -= 4;
+ /* strip out 2 bytes of checksum */
+ rp->len -= 2;
+ return len;
+}
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
new file mode 100644
index 0000000..fa868ab
--- /dev/null
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -0,0 +1,237 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDSS_DSI_H
+#define MDSS_DSI_H
+
+#include <linux/list.h>
+#include <mach/scm-io.h>
+
+#include "mdss_panel.h"
+
+#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
+#define MIPI_INP(addr) readl_relaxed(addr)
+
+#define MIPI_DSI_PRIM 1
+#define MIPI_DSI_SECD 2
+
+#define MIPI_DSI_PANEL_VGA 0
+#define MIPI_DSI_PANEL_WVGA 1
+#define MIPI_DSI_PANEL_WVGA_PT 2
+#define MIPI_DSI_PANEL_FWVGA_PT 3
+#define MIPI_DSI_PANEL_WSVGA_PT 4
+#define MIPI_DSI_PANEL_QHD_PT 5
+#define MIPI_DSI_PANEL_WXGA 6
+#define MIPI_DSI_PANEL_WUXGA 7
+#define MIPI_DSI_PANEL_720P_PT 8
+#define DSI_PANEL_MAX 8
+
+enum {
+ DSI_VIDEO_MODE,
+ DSI_CMD_MODE,
+};
+
+enum {
+ ST_DSI_CLK_OFF,
+ ST_DSI_SUSPEND,
+ ST_DSI_RESUME,
+ ST_DSI_PLAYING,
+ ST_DSI_NUM
+};
+
+enum {
+ EV_DSI_UPDATE,
+ EV_DSI_DONE,
+ EV_DSI_TOUT,
+ EV_DSI_NUM
+};
+
+enum {
+ LANDSCAPE = 1,
+ PORTRAIT = 2,
+};
+
+enum {
+ DSI_CMD_MODE_DMA,
+ DSI_CMD_MODE_MDP,
+};
+
+enum {
+ BL_PWM,
+ BL_WLED,
+ BL_DCS_CMD,
+ UNKNOWN_CTRL,
+};
+
+enum {
+ DSI_LP_MODE,
+ DSI_HS_MODE,
+};
+
+#define DSI_NON_BURST_SYNCH_PULSE 0
+#define DSI_NON_BURST_SYNCH_EVENT 1
+#define DSI_BURST_MODE 2
+
+#define DSI_RGB_SWAP_RGB 0
+#define DSI_RGB_SWAP_RBG 1
+#define DSI_RGB_SWAP_BGR 2
+#define DSI_RGB_SWAP_BRG 3
+#define DSI_RGB_SWAP_GRB 4
+#define DSI_RGB_SWAP_GBR 5
+
+#define DSI_VIDEO_DST_FORMAT_RGB565 0
+#define DSI_VIDEO_DST_FORMAT_RGB666 1
+#define DSI_VIDEO_DST_FORMAT_RGB666_LOOSE 2
+#define DSI_VIDEO_DST_FORMAT_RGB888 3
+
+#define DSI_CMD_DST_FORMAT_RGB111 0
+#define DSI_CMD_DST_FORMAT_RGB332 3
+#define DSI_CMD_DST_FORMAT_RGB444 4
+#define DSI_CMD_DST_FORMAT_RGB565 6
+#define DSI_CMD_DST_FORMAT_RGB666 7
+#define DSI_CMD_DST_FORMAT_RGB888 8
+
+#define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */
+#define DSI_CMD_TRIGGER_TE 0x02
+#define DSI_CMD_TRIGGER_SW 0x04
+#define DSI_CMD_TRIGGER_SW_SEOF 0x05 /* cmd dma only */
+#define DSI_CMD_TRIGGER_SW_TE 0x06
+
+#define DSI_HOST_HDR_SIZE 4
+#define DSI_HDR_LAST BIT(31)
+#define DSI_HDR_LONG_PKT BIT(30)
+#define DSI_HDR_BTA BIT(29)
+#define DSI_HDR_VC(vc) (((vc) & 0x03) << 22)
+#define DSI_HDR_DTYPE(dtype) (((dtype) & 0x03f) << 16)
+#define DSI_HDR_DATA2(data) (((data) & 0x0ff) << 8)
+#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
+#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
+
+#define DSI_BUF_SIZE 1024
+#define DSI_MRPS 0x04 /* Maximum Return Packet Size */
+
+#define DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
+
+struct dsi_buf {
+ u32 *hdr; /* dsi host header */
+ char *start; /* buffer start addr */
+ char *end; /* buffer end addr */
+ int size; /* size of buffer */
+ char *data; /* buffer */
+ int len; /* data length */
+ dma_addr_t dmap; /* mapped dma addr */
+};
+
+/* dcs read/write */
+#define DTYPE_DCS_WRITE 0x05 /* short write, 0 parameter */
+#define DTYPE_DCS_WRITE1 0x15 /* short write, 1 parameter */
+#define DTYPE_DCS_READ 0x06 /* read */
+#define DTYPE_DCS_LWRITE 0x39 /* long write */
+
+/* generic read/write */
+#define DTYPE_GEN_WRITE 0x03 /* short write, 0 parameter */
+#define DTYPE_GEN_WRITE1 0x13 /* short write, 1 parameter */
+#define DTYPE_GEN_WRITE2 0x23 /* short write, 2 parameter */
+#define DTYPE_GEN_LWRITE 0x29 /* long write */
+#define DTYPE_GEN_READ 0x04 /* long read, 0 parameter */
+#define DTYPE_GEN_READ1 0x14 /* long read, 1 parameter */
+#define DTYPE_GEN_READ2 0x24 /* long read, 2 parameter */
+
+#define DTYPE_TEAR_ON 0x35 /* set tear on */
+#define DTYPE_MAX_PKTSIZE 0x37 /* set max packet size */
+#define DTYPE_NULL_PKT 0x09 /* null packet, no data */
+#define DTYPE_BLANK_PKT 0x19 /* blankiing packet, no data */
+
+#define DTYPE_CM_ON 0x02 /* color mode off */
+#define DTYPE_CM_OFF 0x12 /* color mode on */
+#define DTYPE_PERIPHERAL_OFF 0x22
+#define DTYPE_PERIPHERAL_ON 0x32
+
+/*
+ * dcs response
+ */
+#define DTYPE_ACK_ERR_RESP 0x02
+#define DTYPE_EOT_RESP 0x08 /* end of tx */
+#define DTYPE_GEN_READ1_RESP 0x11 /* 1 parameter, short */
+#define DTYPE_GEN_READ2_RESP 0x12 /* 2 parameter, short */
+#define DTYPE_GEN_LREAD_RESP 0x1a
+#define DTYPE_DCS_LREAD_RESP 0x1c
+#define DTYPE_DCS_READ1_RESP 0x21 /* 1 parameter, short */
+#define DTYPE_DCS_READ2_RESP 0x22 /* 2 parameter, short */
+
+struct dsi_cmd_desc {
+ int dtype;
+ int last;
+ int vc;
+ int ack; /* ask ACK from peripheral */
+ int wait;
+ int dlen;
+ char *payload;
+};
+
+struct dsi_panel_cmds_list {
+ struct dsi_cmd_desc *buf;
+ char size;
+ char ctrl_state;
+};
+
+struct dsi_panel_common_pdata {
+ struct mdss_panel_info panel_info;
+ int (*on) (struct mdss_panel_data *pdata);
+ int (*off) (struct mdss_panel_data *pdata);
+ void (*reset)(int enable);
+ void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
+ struct dsi_panel_cmds_list *dsi_panel_on_cmds;
+ struct dsi_panel_cmds_list *dsi_panel_off_cmds;
+};
+
+struct dsi_interface {
+ int (*on)(struct mdss_panel_data *pdata);
+ int (*off)(struct mdss_panel_data *pdata);
+ void (*op_mode_config)(int mode, struct mdss_panel_data *pdata);
+ int (*tx)(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt);
+ int (*rx)(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int len);
+ int index;
+ void *private;
+};
+
+int dsi_panel_device_register_v2(struct platform_device *pdev,
+ struct dsi_panel_common_pdata *panel_data,
+ char bl_ctrl);
+
+void dsi_register_interface(struct dsi_interface *intf);
+
+int dsi_cmds_rx_v2(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dsi_cmd_desc *cmds, int len);
+
+int dsi_cmds_tx_v2(struct mdss_panel_data *pdata,
+ struct dsi_buf *tp, struct dsi_cmd_desc *cmds,
+ int cnt);
+
+char *dsi_buf_init(struct dsi_buf *dp);
+
+int dsi_buf_alloc(struct dsi_buf *dp, int size);
+
+int dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
+
+int dsi_short_read1_resp(struct dsi_buf *rp);
+
+int dsi_short_read2_resp(struct dsi_buf *rp);
+
+int dsi_long_read_resp(struct dsi_buf *rp);
+
+#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
new file mode 100644
index 0000000..890b00b
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -0,0 +1,917 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iommu.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/memory_alloc.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+
+#include <mach/board.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/msm_memtypes.h>
+
+#include "mdp3.h"
+#include "mdss_fb.h"
+#include "mdp3_hwio.h"
+#include "mdp3_ctrl.h"
+
+#define MDP_CORE_HW_VERSION 0x03030304
+struct mdp3_hw_resource *mdp3_res;
+
+#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \
+ { \
+ .src = MSM_BUS_MASTER_MDP_PORT0, \
+ .dst = MSM_BUS_SLAVE_EBI_CH0, \
+ .ab = (ab_val), \
+ .ib = (ib_val), \
+ }
+
+static struct msm_bus_vectors mdp_bus_vectors[] = {
+ MDP_BUS_VECTOR_ENTRY(0, 0),
+ MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M),
+ MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M),
+};
+
+static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+
+static struct msm_bus_scale_pdata mdp_bus_scale_table = {
+ .usecase = mdp_bus_usecases,
+ .num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+ .name = "mdp3",
+};
+
+struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = {
+ [MDP3_IOMMU_DOMAIN] = {
+ .domain_type = MDP3_IOMMU_DOMAIN,
+ .client_name = "mdp_dma",
+ .partitions = {
+ {
+ .start = SZ_128K,
+ .size = SZ_1G - SZ_128K,
+ },
+ },
+ .npartitions = 1,
+ },
+};
+
+struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = {
+ [MDP3_IOMMU_CTX_PPP_0] = {
+ .ctx_type = MDP3_IOMMU_CTX_PPP_0,
+ .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .ctx_name = "mdpe_0",
+ .attached = 0,
+ },
+ [MDP3_IOMMU_CTX_PPP_1] = {
+ .ctx_type = MDP3_IOMMU_CTX_PPP_1,
+ .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .ctx_name = "mdpe_1",
+ .attached = 0,
+ },
+
+ [MDP3_IOMMU_CTX_DMA_0] = {
+ .ctx_type = MDP3_IOMMU_CTX_DMA_0,
+ .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .ctx_name = "mdps_0",
+ .attached = 0,
+ },
+
+ [MDP3_IOMMU_CTX_DMA_1] = {
+ .ctx_type = MDP3_IOMMU_CTX_DMA_1,
+ .domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN],
+ .ctx_name = "mdps_1",
+ .attached = 0,
+ },
+};
+
+static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
+{
+ int i = 0;
+ struct mdp3_hw_resource *mdata = (struct mdp3_hw_resource *)ptr;
+ u32 mdp_interrupt = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
+
+ MDP3_REG_WRITE(MDP3_REG_INTR_CLEAR, mdp_interrupt);
+ pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
+
+ spin_lock(&mdata->irq_lock);
+ mdp_interrupt &= mdata->irqMask;
+
+ while (mdp_interrupt && i < MDP3_MAX_INTR) {
+ if ((mdp_interrupt & 0x1) && mdata->callbacks[i].cb)
+ mdata->callbacks[i].cb(i, mdata->callbacks[i].data);
+ mdp_interrupt = mdp_interrupt >> 1;
+ i++;
+ }
+ spin_unlock(&mdata->irq_lock);
+
+ return IRQ_HANDLED;
+}
+
+void mdp3_irq_enable(int type)
+{
+ unsigned long flag;
+ int irqEnabled = 0;
+
+ pr_debug("mdp3_irq_enable type=%d\n", type);
+ spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+ if (mdp3_res->irqMask & BIT(type)) {
+ pr_debug("interrupt %d already enabled\n", type);
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+ return;
+ }
+ irqEnabled = mdp3_res->irqMask;
+ mdp3_res->irqMask |= BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+ if (!irqEnabled)
+ enable_irq(mdp3_res->irq);
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_disable(int type)
+{
+ unsigned long flag;
+
+ spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+ if (mdp3_res->irqMask & BIT(type)) {
+ mdp3_res->irqMask &= ~BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+ if (!mdp3_res->irqMask)
+ disable_irq(mdp3_res->irq);
+ } else {
+ pr_debug("interrupt %d not enabled\n", type);
+ }
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+}
+
+void mdp3_irq_disable_nosync(int type)
+{
+ if (mdp3_res->irqMask & BIT(type)) {
+ mdp3_res->irqMask &= ~BIT(type);
+ MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+ if (!mdp3_res->irqMask)
+ disable_irq_nosync(mdp3_res->irq);
+ } else {
+ pr_debug("interrupt %d not enabled\n", type);
+ }
+}
+
+int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb)
+{
+ unsigned long flag;
+
+ pr_debug("interrupt %d callback n", type);
+ spin_lock_irqsave(&mdp3_res->irq_lock, flag);
+ if (cb)
+ mdp3_res->callbacks[type] = *cb;
+ else
+ mdp3_res->callbacks[type].cb = NULL;
+
+ spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+ return 0;
+}
+
+static int mdp3_bus_scale_register(void)
+{
+ if (!mdp3_res->bus_handle) {
+ struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
+ int i;
+
+ for (i = 0; i < bus_pdata->num_usecases; i++) {
+ mdp_bus_usecases[i].num_paths = 1;
+ mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i];
+ }
+
+ mdp3_res->bus_handle = msm_bus_scale_register_client(bus_pdata);
+ if (!mdp3_res->bus_handle) {
+ pr_err("not able to get bus scale\n");
+ return -ENOMEM;
+ }
+ pr_debug("register bus_hdl=%x\n", mdp3_res->bus_handle);
+ }
+ return 0;
+}
+
+static void mdp3_bus_scale_unregister(void)
+{
+ pr_debug("unregister bus_handle=%x\n", mdp3_res->bus_handle);
+
+ if (mdp3_res->bus_handle)
+ msm_bus_scale_unregister_client(mdp3_res->bus_handle);
+}
+
+int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota)
+{
+ static int current_bus_idx;
+ int bus_idx;
+ int rc;
+
+ if (mdp3_res->bus_handle < 1) {
+ pr_err("invalid bus handle %d\n", mdp3_res->bus_handle);
+ return -EINVAL;
+ }
+
+ if ((ab_quota | ib_quota) == 0) {
+ bus_idx = 0;
+ } else {
+ int num_cases = mdp_bus_scale_table.num_usecases;
+ struct msm_bus_vectors *vect = NULL;
+
+ bus_idx = (current_bus_idx % (num_cases - 1)) + 1;
+
+ /* aligning to avoid performing updates for small changes */
+ ab_quota = ALIGN(ab_quota, SZ_64M);
+ ib_quota = ALIGN(ib_quota, SZ_64M);
+
+ vect = mdp_bus_scale_table.usecase[current_bus_idx].vectors;
+ if ((ab_quota == vect->ab) && (ib_quota == vect->ib)) {
+ pr_debug("skip bus scaling, no change in vectors\n");
+ return 0;
+ }
+
+ vect = mdp_bus_scale_table.usecase[bus_idx].vectors;
+ vect->ab = ab_quota;
+ vect->ib = ib_quota;
+
+ pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx,
+ vect->ab, vect->ib);
+ }
+ current_bus_idx = bus_idx;
+ rc = msm_bus_scale_client_update_request(mdp3_res->bus_handle, bus_idx);
+ return rc;
+}
+
+static int mdp3_clk_update(u32 clk_idx, u32 enable)
+{
+ int ret = -EINVAL;
+ struct clk *clk;
+ int count = 0;
+
+ if (clk_idx >= MDP3_MAX_CLK || !mdp3_res->clocks[clk_idx])
+ return -ENODEV;
+
+ clk = mdp3_res->clocks[clk_idx];
+
+ if (enable)
+ mdp3_res->clock_ref_count[clk_idx]++;
+ else
+ mdp3_res->clock_ref_count[clk_idx]--;
+
+ count = mdp3_res->clock_ref_count[clk_idx];
+ if (count == 1) {
+ pr_debug("clk=%d en=%d\n", clk_idx, enable);
+ ret = clk_prepare_enable(clk);
+ } else if (count == 0) {
+ pr_debug("clk=%d disable\n", clk_idx);
+ clk_disable_unprepare(clk);
+ ret = 0;
+ } else if (count < 0) {
+ pr_err("clk=%d count=%d\n", clk_idx, count);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+int mdp3_vsync_clk_enable(int enable)
+{
+ int ret = 0;
+
+ pr_debug("vsync clk enable=%d\n", enable);
+ mutex_lock(&mdp3_res->res_mutex);
+ mdp3_clk_update(MDP3_CLK_VSYNC, enable);
+ mutex_unlock(&mdp3_res->res_mutex);
+ return ret;
+}
+
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate)
+{
+ int ret = 0;
+ unsigned long rounded_rate;
+ struct clk *clk = mdp3_res->clocks[clk_type];
+
+ if (clk) {
+ mutex_lock(&mdp3_res->res_mutex);
+ rounded_rate = clk_round_rate(clk, clk_rate);
+ if (IS_ERR_VALUE(rounded_rate)) {
+ pr_err("unable to round rate err=%ld\n", rounded_rate);
+ mutex_unlock(&mdp3_res->res_mutex);
+ return -EINVAL;
+ }
+ if (rounded_rate != clk_get_rate(clk)) {
+ ret = clk_set_rate(clk, rounded_rate);
+ if (ret)
+ pr_err("clk_set_rate failed ret=%d\n", ret);
+ else
+ pr_debug("mdp clk rate=%lu\n", rounded_rate);
+ }
+ mutex_unlock(&mdp3_res->res_mutex);
+ } else {
+ pr_err("mdp src clk not setup properly\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+unsigned long mdp3_get_clk_rate(u32 clk_idx)
+{
+ unsigned long clk_rate = 0;
+ struct clk *clk;
+
+ if (clk_idx >= MDP3_MAX_CLK)
+ return -ENODEV;
+
+ clk = mdp3_res->clocks[clk_idx];
+
+ if (clk) {
+ mutex_lock(&mdp3_res->res_mutex);
+ clk_rate = clk_get_rate(clk);
+ mutex_unlock(&mdp3_res->res_mutex);
+ }
+ return clk_rate;
+}
+
+static int mdp3_clk_register(char *clk_name, int clk_idx)
+{
+ struct clk *tmp;
+
+ if (clk_idx >= MDP3_MAX_CLK) {
+ pr_err("invalid clk index %d\n", clk_idx);
+ return -EINVAL;
+ }
+
+ tmp = devm_clk_get(&mdp3_res->pdev->dev, clk_name);
+ if (IS_ERR(tmp)) {
+ pr_err("unable to get clk: %s\n", clk_name);
+ return PTR_ERR(tmp);
+ }
+
+ mdp3_res->clocks[clk_idx] = tmp;
+
+ return 0;
+}
+
+static int mdp3_clk_setup(void)
+{
+ int rc;
+
+ rc = mdp3_clk_register("iface_clk", MDP3_CLK_AHB);
+ if (rc)
+ return rc;
+
+ rc = mdp3_clk_register("core_clk", MDP3_CLK_CORE);
+ if (rc)
+ return rc;
+
+ rc = mdp3_clk_register("vsync_clk", MDP3_CLK_VSYNC);
+ if (rc)
+ return rc;
+
+ rc = mdp3_clk_register("lcdc_clk", MDP3_CLK_LCDC);
+ if (rc)
+ return rc;
+
+ return rc;
+}
+
+static void mdp3_clk_remove(void)
+{
+ clk_put(mdp3_res->clocks[MDP3_CLK_AHB]);
+ clk_put(mdp3_res->clocks[MDP3_CLK_CORE]);
+ clk_put(mdp3_res->clocks[MDP3_CLK_VSYNC]);
+ clk_put(mdp3_res->clocks[MDP3_CLK_LCDC]);
+}
+
+int mdp3_clk_enable(int enable)
+{
+ int rc;
+
+ pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
+
+ mutex_lock(&mdp3_res->res_mutex);
+ rc = mdp3_clk_update(MDP3_CLK_AHB, enable);
+ rc |= mdp3_clk_update(MDP3_CLK_CORE, enable);
+ rc |= mdp3_clk_update(MDP3_CLK_VSYNC, enable);
+ mutex_unlock(&mdp3_res->res_mutex);
+ return rc;
+}
+
+static int mdp3_irq_setup(void)
+{
+ int ret;
+
+ ret = devm_request_irq(&mdp3_res->pdev->dev,
+ mdp3_res->irq,
+ mdp3_irq_handler,
+ IRQF_DISABLED, "MDP", mdp3_res);
+ if (ret) {
+ pr_err("mdp request_irq() failed!\n");
+ return ret;
+ }
+ disable_irq(mdp3_res->irq);
+ return 0;
+}
+
+static int mdp3_iommu_fault_handler(struct iommu_domain *domain,
+ struct device *dev, unsigned long iova, int flags, void *token)
+{
+ pr_err("MDP IOMMU page fault: iova 0x%lx\n", iova);
+ return 0;
+}
+
+int mdp3_iommu_attach(int context)
+{
+ struct mdp3_iommu_ctx_map *context_map;
+ struct mdp3_iommu_domain_map *domain_map;
+
+ if (context >= MDP3_IOMMU_CTX_MAX)
+ return -EINVAL;
+
+ context_map = mdp3_res->iommu_contexts + context;
+ if (context_map->attached) {
+ pr_warn("mdp iommu already attached\n");
+ return 0;
+ }
+
+ domain_map = context_map->domain;
+
+ iommu_attach_device(domain_map->domain, context_map->ctx);
+
+ context_map->attached = true;
+ return 0;
+}
+
+int mdp3_iommu_dettach(int context)
+{
+ struct mdp3_iommu_ctx_map *context_map;
+ struct mdp3_iommu_domain_map *domain_map;
+
+ if (context >= MDP3_IOMMU_CTX_MAX)
+ return -EINVAL;
+
+ context_map = mdp3_res->iommu_contexts + context;
+ if (!context_map->attached) {
+ pr_warn("mdp iommu not attached\n");
+ return 0;
+ }
+
+ domain_map = context_map->domain;
+ iommu_detach_device(domain_map->domain, context_map->ctx);
+ context_map->attached = false;
+
+ return 0;
+}
+
+int mdp3_iommu_domain_init(void)
+{
+ struct msm_iova_layout layout;
+ int i;
+
+ if (mdp3_res->domains) {
+ pr_warn("iommu domain already initialized\n");
+ return 0;
+ }
+
+ for (i = 0; i < MDP3_IOMMU_DOMAIN_MAX; i++) {
+ int domain_idx;
+ layout.client_name = mdp3_iommu_domains[i].client_name;
+ layout.partitions = mdp3_iommu_domains[i].partitions;
+ layout.npartitions = mdp3_iommu_domains[i].npartitions;
+ layout.is_secure = false;
+
+ domain_idx = msm_register_domain(&layout);
+ if (IS_ERR_VALUE(domain_idx))
+ return -EINVAL;
+
+ mdp3_iommu_domains[i].domain_idx = domain_idx;
+ mdp3_iommu_domains[i].domain = msm_get_iommu_domain(domain_idx);
+ if (!mdp3_iommu_domains[i].domain) {
+ pr_err("unable to get iommu domain(%d)\n",
+ domain_idx);
+ return -EINVAL;
+ }
+ iommu_set_fault_handler(mdp3_iommu_domains[i].domain,
+ mdp3_iommu_fault_handler,
+ NULL);
+ }
+
+ mdp3_res->domains = mdp3_iommu_domains;
+
+ return 0;
+}
+
+int mdp3_iommu_context_init(void)
+{
+ int i;
+
+ if (mdp3_res->iommu_contexts) {
+ pr_warn("iommu context already initialized\n");
+ return 0;
+ }
+
+ for (i = 0; i < MDP3_IOMMU_CTX_MAX; i++) {
+ mdp3_iommu_contexts[i].ctx =
+ msm_iommu_get_ctx(mdp3_iommu_contexts[i].ctx_name);
+
+ if (!mdp3_iommu_contexts[i].ctx) {
+ pr_warn("unable to get iommu ctx(%s)\n",
+ mdp3_iommu_contexts[i].ctx_name);
+ return -EINVAL;
+ }
+ }
+
+ mdp3_res->iommu_contexts = mdp3_iommu_contexts;
+
+ return 0;
+}
+
+int mdp3_iommu_init(void)
+{
+ int ret;
+
+ ret = mdp3_iommu_domain_init();
+ if (ret) {
+ pr_err("mdp3 iommu domain init fails\n");
+ return ret;
+ }
+
+ ret = mdp3_iommu_context_init();
+ if (ret) {
+ pr_err("mdp3 iommu context init fails\n");
+ return ret;
+ }
+ return ret;
+}
+
+static int mdp3_check_version(void)
+{
+ int rc;
+
+ rc = mdp3_clk_update(MDP3_CLK_AHB, 1);
+ if (rc)
+ return rc;
+
+ mdp3_res->mdp_rev = MDP3_REG_READ(MDP3_REG_HW_VERSION);
+
+ rc = mdp3_clk_update(MDP3_CLK_AHB, 0);
+ if (rc)
+ pr_err("fail to turn off the MDP3_CLK_AHB clk\n");
+
+ if (mdp3_res->mdp_rev != MDP_CORE_HW_VERSION) {
+ pr_err("mdp_hw_revision=%x mismatch\n", mdp3_res->mdp_rev);
+ rc = -ENODEV;
+ }
+ return rc;
+}
+
+static int mdp3_hw_init(void)
+{
+ int i;
+
+ for (i = MDP3_DMA_P; i < MDP3_DMA_MAX; i++) {
+ mdp3_res->dma[i].dma_sel = i;
+ mdp3_res->dma[i].capability = MDP3_DMA_CAP_ALL;
+ mdp3_res->dma[i].in_use = 0;
+ mdp3_res->dma[i].available = 1;
+ }
+ mdp3_res->dma[MDP3_DMA_S].capability = MDP3_DMA_CAP_DITHER;
+ mdp3_res->dma[MDP3_DMA_E].available = 0;
+
+ for (i = MDP3_DMA_OUTPUT_SEL_AHB; i < MDP3_DMA_OUTPUT_SEL_MAX; i++) {
+ mdp3_res->intf[i].cfg.type = i;
+ mdp3_res->intf[i].active = 0;
+ mdp3_res->intf[i].in_use = 0;
+ mdp3_res->intf[i].available = 1;
+ }
+ mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_AHB].available = 0;
+ mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_LCDC].available = 0;
+
+ return 0;
+}
+
+static int mdp3_res_init(void)
+{
+ int rc = 0;
+
+ rc = mdp3_irq_setup();
+ if (rc)
+ return rc;
+
+ rc = mdp3_clk_setup();
+ if (rc)
+ return rc;
+
+ mdp3_res->ion_client = msm_ion_client_create(-1, mdp3_res->pdev->name);
+ if (IS_ERR_OR_NULL(mdp3_res->ion_client)) {
+ pr_err("msm_ion_client_create() return error (%p)\n",
+ mdp3_res->ion_client);
+ mdp3_res->ion_client = NULL;
+ return -EINVAL;
+ }
+
+ rc = mdp3_iommu_init();
+ if (rc)
+ return rc;
+
+ rc = mdp3_iommu_attach(MDP3_IOMMU_CTX_DMA_0);
+ if (rc) {
+ pr_err("fail to attach DMA-P context 0\n");
+ return rc;
+ }
+ rc = mdp3_bus_scale_register();
+ if (rc) {
+ pr_err("unable to register bus scaling\n");
+ return rc;
+ }
+
+ rc = mdp3_hw_init();
+
+ return rc;
+}
+
+static int mdp3_parse_dt(struct platform_device *pdev)
+{
+ struct resource *res;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
+ if (!res) {
+ pr_err("unable to get MDP base address\n");
+ return -EINVAL;
+ }
+
+ mdp3_res->mdp_reg_size = resource_size(res);
+ mdp3_res->mdp_base = devm_ioremap(&pdev->dev, res->start,
+ mdp3_res->mdp_reg_size);
+ if (unlikely(!mdp3_res->mdp_base)) {
+ pr_err("unable to map MDP base\n");
+ return -ENOMEM;
+ }
+
+ pr_debug("MDP HW Base phy_Address=0x%x virt=0x%x\n",
+ (int) res->start,
+ (int) mdp3_res->mdp_base);
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ pr_err("unable to get MDSS irq\n");
+ return -EINVAL;
+ }
+ mdp3_res->irq = res->start;
+
+ return 0;
+}
+
+static int mdp3_init(struct msm_fb_data_type *mfd)
+{
+ return mdp3_ctrl_init(mfd);
+}
+
+u32 mdp3_fb_stride(u32 fb_index, u32 xres, int bpp)
+{
+ /*
+ * The adreno GPU hardware requires that the pitch be aligned to
+ * 32 pixels for color buffers, so for the cases where the GPU
+ * is writing directly to fb0, the framebuffer pitch
+ * also needs to be 32 pixel aligned
+ */
+
+ if (fb_index == 0)
+ return ALIGN(xres, 32) * bpp;
+ else
+ return xres * bpp;
+}
+
+/*
+ * physical contiguous memory should be allocated in mdss_fb, and SMMU
+ * virtual address mapping can be done in the MDP h/w specific code. It
+ * should have a reference count, if none is current mapped, the SMMU context
+ * can bedetached, thus allowing power saving in SMMU.
+ */
+static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
+{
+ int dom;
+ void *virt = NULL;
+ unsigned long phys = 0;
+ size_t size;
+ u32 yres = mfd->fbi->var.yres_virtual;
+
+ size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
+ if (mfd->index == 0) {
+ virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+ if (!virt) {
+ pr_err("unable to alloc fbmem size=%u\n", size);
+ return -ENOMEM;
+ }
+ phys = memory_pool_node_paddr(virt);
+ dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+ msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
+ &mfd->iova);
+
+ pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
+ size, virt, phys, mfd->index);
+ } else {
+ size = 0;
+ }
+
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = size;
+ return 0;
+}
+
+struct mdp3_dma *mdp3_get_dma_pipe(int capability)
+{
+ int i;
+
+ for (i = MDP3_DMA_P; i < MDP3_DMA_MAX; i++) {
+ if (!mdp3_res->dma[i].in_use && mdp3_res->dma[i].available &&
+ mdp3_res->dma[i].capability & capability) {
+ mdp3_res->dma[i].in_use = true;
+ return &mdp3_res->dma[i];
+ }
+ }
+ return NULL;
+}
+
+struct mdp3_intf *mdp3_get_display_intf(int type)
+{
+ int i;
+
+ for (i = MDP3_DMA_OUTPUT_SEL_AHB; i < MDP3_DMA_OUTPUT_SEL_MAX; i++) {
+ if (!mdp3_res->intf[i].in_use && mdp3_res->intf[i].available &&
+ mdp3_res->intf[i].cfg.type == type) {
+ mdp3_res->intf[i].in_use = true;
+ return &mdp3_res->intf[i];
+ }
+ }
+ return NULL;
+}
+
+static int mdp3_probe(struct platform_device *pdev)
+{
+ int rc;
+ static struct msm_mdp_interface mdp3_interface = {
+ .init_fnc = mdp3_init,
+ .fb_mem_alloc_fnc = mdp3_fbmem_alloc,
+ .fb_stride = mdp3_fb_stride,
+ };
+
+ if (!pdev->dev.of_node) {
+ pr_err("MDP driver only supports device tree probe\n");
+ return -ENOTSUPP;
+ }
+
+ if (mdp3_res) {
+ pr_err("MDP already initialized\n");
+ return -EINVAL;
+ }
+
+ mdp3_res = devm_kzalloc(&pdev->dev, sizeof(struct mdp3_hw_resource),
+ GFP_KERNEL);
+ if (mdp3_res == NULL)
+ return -ENOMEM;
+
+ pdev->id = 0;
+ mdp3_res->pdev = pdev;
+ mutex_init(&mdp3_res->res_mutex);
+ spin_lock_init(&mdp3_res->irq_lock);
+ platform_set_drvdata(pdev, mdp3_res);
+
+ rc = mdp3_parse_dt(pdev);
+ if (rc)
+ goto probe_done;
+
+ rc = mdp3_res_init();
+ if (rc) {
+ pr_err("unable to initialize mdp3 resources\n");
+ goto probe_done;
+ }
+
+ rc = mdp3_check_version();
+ if (rc) {
+ pr_err("mdp3 check version failed\n");
+ goto probe_done;
+ }
+
+ rc = mdss_fb_register_mdp_instance(&mdp3_interface);
+ if (rc)
+ pr_err("unable to register mdp instance\n");
+
+probe_done:
+ if (IS_ERR_VALUE(rc)) {
+ devm_kfree(&pdev->dev, mdp3_res);
+ mdp3_res = NULL;
+ }
+
+ return rc;
+}
+
+static int mdp3_suspend_sub(struct mdp3_hw_resource *mdata)
+{
+ return 0;
+}
+
+static int mdp3_resume_sub(struct mdp3_hw_resource *mdata)
+{
+ return 0;
+}
+
+static int mdp3_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+ if (!mdata)
+ return -ENODEV;
+
+ pr_debug("display suspend\n");
+
+ return mdp3_suspend_sub(mdata);
+}
+
+static int mdp3_resume(struct platform_device *pdev)
+{
+ struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+ if (!mdata)
+ return -ENODEV;
+
+ pr_debug("display resume\n");
+
+ return mdp3_resume_sub(mdata);
+}
+
+static int mdp3_remove(struct platform_device *pdev)
+{
+ struct mdp3_hw_resource *mdata = platform_get_drvdata(pdev);
+
+ if (!mdata)
+ return -ENODEV;
+ pm_runtime_disable(&pdev->dev);
+ mdp3_bus_scale_unregister();
+ mdp3_clk_remove();
+ return 0;
+}
+
+static const struct of_device_id mdp3_dt_match[] = {
+ { .compatible = "qcom,mdss_mdp3",},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mdp3_dt_match);
+EXPORT_COMPAT("qcom,mdss_mdp3");
+
+static struct platform_driver mdp3_driver = {
+ .probe = mdp3_probe,
+ .remove = mdp3_remove,
+ .suspend = mdp3_suspend,
+ .resume = mdp3_resume,
+ .shutdown = NULL,
+ .driver = {
+ .name = "mdp3",
+ .of_match_table = mdp3_dt_match,
+ },
+};
+
+static int __init mdp3_driver_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&mdp3_driver);
+ if (ret) {
+ pr_err("register mdp3 driver failed!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+module_init(mdp3_driver_init);
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
new file mode 100644
index 0000000..c853664
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -0,0 +1,123 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef MDP3_H
+#define MDP3_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/earlysuspend.h>
+
+#include <mach/iommu_domains.h>
+
+#include "mdp3_dma.h"
+
+enum {
+ MDP3_CLK_AHB,
+ MDP3_CLK_CORE,
+ MDP3_CLK_VSYNC,
+ MDP3_CLK_LCDC,
+ MDP3_MAX_CLK
+};
+
+enum {
+ MDP3_IOMMU_DOMAIN,
+ MDP3_IOMMU_DOMAIN_MAX
+};
+
+enum {
+ MDP3_IOMMU_CTX_PPP_0,
+ MDP3_IOMMU_CTX_PPP_1,
+ MDP3_IOMMU_CTX_DMA_0,
+ MDP3_IOMMU_CTX_DMA_1,
+ MDP3_IOMMU_CTX_MAX
+};
+
+enum {
+ MDP3_BW_CLIENT_DMA_P,
+ MDP3_BW_CLIENT_DMA_S,
+ MDP3_BW_CLIENT_DMA_E,
+ MDP3_BW_CLIENT_PPP,
+};
+
+struct mdp3_iommu_domain_map {
+ u32 domain_type;
+ char *client_name;
+ struct msm_iova_partition partitions[1];
+ int npartitions;
+ int domain_idx;
+ struct iommu_domain *domain;
+};
+
+struct mdp3_iommu_ctx_map {
+ u32 ctx_type;
+ struct mdp3_iommu_domain_map *domain;
+ char *ctx_name;
+ struct device *ctx;
+ int attached;
+};
+
+#define MDP3_MAX_INTR 28
+
+struct mdp3_intr_cb {
+ void (*cb)(int type, void *);
+ void *data;
+};
+
+struct mdp3_hw_resource {
+ struct platform_device *pdev;
+ u32 mdp_rev;
+
+ struct mutex res_mutex;
+
+ struct clk *clocks[MDP3_MAX_CLK];
+ int clock_ref_count[MDP3_MAX_CLK];
+
+ char __iomem *mdp_base;
+ size_t mdp_reg_size;
+
+ u32 irq;
+ u32 bus_handle;
+
+ struct ion_client *ion_client;
+ struct mdp3_iommu_domain_map *domains;
+ struct mdp3_iommu_ctx_map *iommu_contexts;
+
+ struct mdp3_dma dma[MDP3_DMA_MAX];
+ struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
+
+ spinlock_t irq_lock;
+ u32 irqMask;
+ struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
+
+ struct early_suspend suspend_handler;
+};
+
+extern struct mdp3_hw_resource *mdp3_res;
+
+struct mdp3_dma *mdp3_get_dma_pipe(int capability);
+struct mdp3_intf *mdp3_get_display_intf(int type);
+void mdp3_irq_enable(int type);
+void mdp3_irq_disable(int type);
+void mdp3_irq_disable_nosync(int type);
+int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
+int mdp3_clk_enable(int enable);
+int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
+
+#define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
+#define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
+
+#endif /* MDP3_H */
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
new file mode 100644
index 0000000..e07c0a4
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -0,0 +1,511 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+
+#include "mdp3_ctrl.h"
+#include "mdp3.h"
+
+#define MDP_VSYNC_CLK_RATE 19200000
+#define VSYNC_PERIOD 16
+
+void vsync_notify_handler(void *arg)
+{
+ struct mdp3_session_data *session = (struct mdp3_session_data *)session;
+ complete(&session->vsync_comp);
+}
+
+static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
+{
+ struct mdp3_session_data *mdp3_session;
+ struct mdp3_vsync_notification vsync_client;
+
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf)
+ return -ENODEV;
+
+ vsync_client.handler = vsync_notify_handler;
+ vsync_client.arg = mdp3_session;
+
+ mutex_lock(&mdp3_session->lock);
+ if (!mdp3_session->status) {
+ pr_debug("fb%d is not on yet", mfd->index);
+ mutex_unlock(&mdp3_session->lock);
+ return -EINVAL;
+ }
+
+ mdp3_session->dma->vsync_enable(mdp3_session->dma, &vsync_client);
+ mutex_unlock(&mdp3_session->lock);
+ return 0;
+}
+
+static ssize_t mdp3_vsync_show_event(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fb_info *fbi = dev_get_drvdata(dev);
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ struct mdp3_session_data *mdp3_session = NULL;
+ u64 vsync_ticks;
+ ktime_t vsync_time;
+ int rc;
+
+ if (!mfd || !mfd->mdp.private1)
+ return 0;
+
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+
+ rc = wait_for_completion_interruptible_timeout(
+ &mdp3_session->vsync_comp,
+ msecs_to_jiffies(VSYNC_PERIOD * 5));
+ if (rc <= 0) {
+ pr_warn("vsync wait on fb%d interrupted (%d)\n",
+ mfd->index, rc);
+ return -EBUSY;
+ }
+
+ vsync_time = mdp3_session->dma->get_vsync_time(mdp3_session->dma);
+ vsync_ticks = ktime_to_ns(vsync_time);
+
+ pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
+ rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
+ return rc;
+}
+
+static DEVICE_ATTR(vsync_event, S_IRUGO, mdp3_vsync_show_event, NULL);
+
+static struct attribute *vsync_fs_attrs[] = {
+ &dev_attr_vsync_event.attr,
+ NULL,
+};
+
+static struct attribute_group vsync_fs_attr_group = {
+ .attrs = vsync_fs_attrs,
+};
+
+static int mdp3_ctrl_res_req_dma(struct msm_fb_data_type *mfd, int status)
+{
+ int rc = 0;
+ if (status) {
+ struct mdss_panel_info *panel_info = mfd->panel_info;
+ int ab = 0;
+ int ib = 0;
+ unsigned long core_clk = 0;
+ int vtotal = 0;
+ ab = panel_info->xres * panel_info->yres * 4;
+ ab *= panel_info->mipi.frame_rate;
+ ib = (ab * 3) / 2;
+ vtotal = panel_info->lcdc.v_back_porch +
+ panel_info->lcdc.v_front_porch +
+ panel_info->lcdc.v_pulse_width +
+ panel_info->yres;
+ core_clk = panel_info->xres * panel_info->yres;
+ core_clk *= panel_info->mipi.frame_rate;
+ core_clk = (core_clk / panel_info->yres) * vtotal;
+ mdp3_clk_set_rate(MDP3_CLK_CORE, core_clk);
+ mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE);
+
+ rc = mdp3_clk_enable(true);
+ if (rc)
+ return rc;
+
+ mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib);
+ } else {
+ rc = mdp3_clk_enable(false);
+ rc |= mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0);
+ }
+ return rc;
+}
+
+static int mdp3_ctrl_get_intf_type(struct msm_fb_data_type *mfd)
+{
+ int type;
+ switch (mfd->panel.type) {
+ case MIPI_VIDEO_PANEL:
+ type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+ break;
+ case MIPI_CMD_PANEL:
+ type = MDP3_DMA_OUTPUT_SEL_DSI_CMD;
+ break;
+ case LCDC_PANEL:
+ type = MDP3_DMA_OUTPUT_SEL_LCDC;
+ break;
+ default:
+ type = MDP3_DMA_OUTPUT_SEL_MAX;
+ }
+ return type;
+}
+
+static int mdp3_ctrl_get_source_format(struct msm_fb_data_type *mfd)
+{
+ int format;
+ switch (mfd->fb_imgType) {
+ case MDP_RGB_565:
+ format = MDP3_DMA_IBUF_FORMAT_RGB565;
+ break;
+ case MDP_RGB_888:
+ format = MDP3_DMA_IBUF_FORMAT_RGB888;
+ break;
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ format = MDP3_DMA_IBUF_FORMAT_XRGB8888;
+ break;
+ default:
+ format = MDP3_DMA_IBUF_FORMAT_UNDEFINED;
+ }
+ return format;
+}
+
+static int mdp3_ctrl_get_pack_pattern(struct msm_fb_data_type *mfd)
+{
+ int packPattern = MDP3_DMA_OUTPUT_PACK_PATTERN_RGB;
+ if (mfd->fb_imgType == MDP_RGBA_8888)
+ packPattern = MDP3_DMA_OUTPUT_PACK_PATTERN_BGR;
+ return packPattern;
+}
+
+static int mdp3_ctrl_intf_init(struct msm_fb_data_type *mfd,
+ struct mdp3_intf *intf)
+{
+ int rc;
+ struct mdp3_intf_cfg cfg;
+ struct mdp3_video_intf_cfg *video = &cfg.video;
+ struct mdss_panel_info *p = mfd->panel_info;
+ int h_back_porch = p->lcdc.h_back_porch;
+ int h_front_porch = p->lcdc.h_front_porch;
+ int w = p->xres;
+ int v_back_porch = p->lcdc.v_back_porch;
+ int v_front_porch = p->lcdc.v_front_porch;
+ int h = p->yres;
+ int h_sync_skew = p->lcdc.hsync_skew;
+ int h_pulse_width = p->lcdc.h_pulse_width;
+ int v_pulse_width = p->lcdc.v_pulse_width;
+ int hsync_period = h_front_porch + h_back_porch + w + h_pulse_width;
+ int vsync_period = v_front_porch + v_back_porch + h + v_pulse_width;
+ vsync_period *= hsync_period;
+
+ cfg.type = mdp3_ctrl_get_intf_type(mfd);
+ if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ video->hsync_period = hsync_period;
+ video->hsync_pulse_width = h_pulse_width;
+ video->vsync_period = vsync_period;
+ video->vsync_pulse_width = v_pulse_width * hsync_period;
+ video->display_start_x = h_back_porch + h_pulse_width;
+ video->display_end_x = hsync_period - h_front_porch - 1;
+ video->display_start_y =
+ (v_back_porch + v_pulse_width) * hsync_period;
+ video->display_end_y =
+ vsync_period - v_front_porch * hsync_period - 1;
+ video->active_start_x = video->display_start_x;
+ video->active_end_x = video->display_end_x;
+ video->active_h_enable = true;
+ video->active_start_y = video->display_start_y;
+ video->active_end_y = video->display_end_y;
+ video->active_v_enable = true;
+ video->hsync_skew = h_sync_skew;
+ video->hsync_polarity = 1;
+ video->vsync_polarity = 1;
+ video->de_polarity = 1;
+ } else if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ cfg.dsi_cmd.primary_dsi_cmd_id = 0;
+ cfg.dsi_cmd.secondary_dsi_cmd_id = 1;
+ cfg.dsi_cmd.dsi_cmd_tg_intf_sel = 0;
+ } else
+ return -EINVAL;
+ rc = mdp3_intf_init(intf, &cfg);
+ return rc;
+}
+
+static int mdp3_ctrl_dma_init(struct msm_fb_data_type *mfd,
+ struct mdp3_dma *dma)
+{
+ int rc;
+ struct mdss_panel_info *panel_info = mfd->panel_info;
+ struct fb_info *fbi = mfd->fbi;
+ struct fb_fix_screeninfo *fix;
+ struct fb_var_screeninfo *var;
+ struct mdp3_dma_output_config outputConfig;
+ struct mdp3_dma_source sourceConfig;
+
+ fix = &fbi->fix;
+ var = &fbi->var;
+
+ sourceConfig.format = mdp3_ctrl_get_source_format(mfd);
+ sourceConfig.width = panel_info->xres;
+ sourceConfig.height = panel_info->yres;
+ sourceConfig.x = 0;
+ sourceConfig.y = 0;
+ sourceConfig.stride = fix->line_length;
+ sourceConfig.buf = (void *)mfd->iova;
+
+ outputConfig.dither_en = 0;
+ outputConfig.out_sel = mdp3_ctrl_get_intf_type(mfd);
+ outputConfig.bit_mask_polarity = 0;
+ outputConfig.color_components_flip = 0;
+ outputConfig.pack_pattern = mdp3_ctrl_get_pack_pattern(mfd);
+ outputConfig.pack_align = MDP3_DMA_OUTPUT_PACK_ALIGN_LSB;
+ outputConfig.color_comp_out_bits = (MDP3_DMA_OUTPUT_COMP_BITS_8 << 4) |
+ (MDP3_DMA_OUTPUT_COMP_BITS_8 << 2)|
+ MDP3_DMA_OUTPUT_COMP_BITS_8;
+
+ rc = mdp3_dma_init(dma, &sourceConfig, &outputConfig);
+ return rc;
+}
+
+static int mdp3_ctrl_on(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session;
+ struct mdss_panel_data *panel;
+
+ pr_debug("mdp3_ctrl_on\n");
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf) {
+ pr_err("mdp3_ctrl_on no device");
+ return -ENODEV;
+ }
+ mutex_lock(&mdp3_session->lock);
+ if (mdp3_session->status) {
+ pr_info("fb%d is on already", mfd->index);
+ goto on_error;
+ }
+
+ rc = mdp3_ctrl_res_req_dma(mfd, 1);
+ if (rc) {
+ pr_err("resource request for dma on failed\n");
+ goto on_error;
+ }
+
+ rc = mdp3_ctrl_dma_init(mfd, mdp3_session->dma);
+ if (rc) {
+ pr_err("dma init failed\n");
+ goto on_error;
+ }
+
+ rc = mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+ if (rc) {
+ pr_err("display interface init failed\n");
+ goto on_error;
+ }
+
+ panel = mdp3_session->panel;
+
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+
+ if (rc) {
+ pr_err("fail to turn on the panel\n");
+ goto on_error;
+ }
+
+ rc = mdp3_session->dma->start(mdp3_session->dma, mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to start the MDP display interface\n");
+ goto on_error;
+ }
+
+on_error:
+ if (!rc)
+ mdp3_session->status = 1;
+
+ mutex_unlock(&mdp3_session->lock);
+ return rc;
+}
+
+static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session;
+ struct mdss_panel_data *panel;
+
+ pr_debug("mdp3_ctrl_off\n");
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf) {
+ pr_err("mdp3_ctrl_on no device");
+ return -ENODEV;
+ }
+
+ mutex_lock(&mdp3_session->lock);
+
+ if (!mdp3_session->status) {
+ pr_info("fb%d is off already", mfd->index);
+ goto off_error;
+ }
+
+ panel = mdp3_session->panel;
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
+
+ if (rc)
+ pr_err("fail to turn off the panel\n");
+
+ rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+
+ if (rc)
+ pr_err("fail to stop the MDP3 dma\n");
+
+ rc = mdp3_ctrl_res_req_dma(mfd, 0);
+ if (rc)
+ pr_err("resource release for dma on failed\n");
+
+off_error:
+ mdp3_session->status = 0;
+
+ mutex_unlock(&mdp3_session->lock);
+ return 0;
+}
+
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
+{
+ struct fb_info *fbi;
+ struct mdp3_session_data *mdp3_session;
+ u32 offset;
+ int bpp;
+
+ pr_debug("mdp3_ctrl_pan_display\n");
+ if (!mfd || !mfd->mdp.private1)
+ return;
+
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->dma)
+ return;
+
+ if (!mdp3_session->status) {
+ pr_err("mdp3_ctrl_pan_display, display off!\n");
+ return;
+ }
+
+ mutex_lock(&mdp3_session->lock);
+ fbi = mfd->fbi;
+
+ bpp = fbi->var.bits_per_pixel / 8;
+ offset = fbi->var.xoffset * bpp +
+ fbi->var.yoffset * fbi->fix.line_length;
+
+ if (offset > fbi->fix.smem_len) {
+ pr_err("invalid fb offset=%u total length=%u\n",
+ offset, fbi->fix.smem_len);
+ goto pan_error;
+ }
+
+ mdp3_session->dma->update(mdp3_session->dma,
+ (void *)mfd->iova + offset);
+pan_error:
+ mutex_unlock(&mdp3_session->lock);
+}
+
+static int mdp3_ctrl_ioctl_handler(struct msm_fb_data_type *mfd,
+ u32 cmd, void __user *argp)
+{
+ int rc = -EINVAL;
+ struct mdp3_session_data *mdp3_session;
+ int val;
+
+ pr_debug("mdp3_ctrl_ioctl_handler\n");
+
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session)
+ return -ENODEV;
+
+ if (!mdp3_session->status) {
+ pr_err("mdp3_ctrl_ioctl_handler, display off!\n");
+ return -EINVAL;
+ }
+
+ switch (cmd) {
+ case MSMFB_VSYNC_CTRL:
+ case MSMFB_OVERLAY_VSYNC_CTRL:
+ if (!copy_from_user(&val, argp, sizeof(val))) {
+ rc = mdp3_ctrl_vsync_enable(mfd, val);
+ if (!val)
+ init_completion(&mdp3_session->vsync_comp);
+ } else {
+ pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
+ rc = -EFAULT;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+int mdp3_ctrl_init(struct msm_fb_data_type *mfd)
+{
+ struct device *dev = mfd->fbi->dev;
+ struct msm_mdp_interface *mdp3_interface = &mfd->mdp;
+ struct mdp3_session_data *mdp3_session = NULL;
+ u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+ int rc;
+
+ pr_debug("mdp3_ctrl_init\n");
+ mdp3_interface->on_fnc = mdp3_ctrl_on;
+ mdp3_interface->off_fnc = mdp3_ctrl_off;
+ mdp3_interface->do_histogram = NULL;
+ mdp3_interface->cursor_update = NULL;
+ mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
+ mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
+ mdp3_interface->kickoff_fnc = NULL;
+
+ mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
+ if (!mdp3_session) {
+ pr_err("fail to allocate mdp3 private data structure");
+ return -ENOMEM;
+ }
+ memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
+ mutex_init(&mdp3_session->lock);
+ init_completion(&mdp3_session->vsync_comp);
+ mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
+ if (!mdp3_session->dma) {
+ rc = -ENODEV;
+ goto init_done;
+ }
+
+ intf_type = mdp3_ctrl_get_intf_type(mfd);
+ mdp3_session->intf = mdp3_get_display_intf(intf_type);
+ if (!mdp3_session->intf) {
+ rc = -ENODEV;
+ goto init_done;
+ }
+
+ mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
+ mdp3_session->status = 0;
+
+ mfd->mdp.private1 = mdp3_session;
+
+ rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
+ if (rc) {
+ pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
+ goto init_done;
+ }
+
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
+ pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
+
+init_done:
+ if (IS_ERR_VALUE(rc))
+ kfree(mdp3_session);
+
+ return rc;
+}
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
new file mode 100644
index 0000000..d42ece7
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_CTRL_H
+#define MDP3_CTRL_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+
+#include "mdp3_dma.h"
+#include "mdss_fb.h"
+#include "mdss_panel.h"
+
+struct mdp3_session_data {
+ struct mutex lock;
+ int status;
+ struct mdp3_dma *dma;
+ struct mdss_panel_data *panel;
+ struct mdp3_intf *intf;
+ struct msm_fb_data_type *mfd;
+ struct completion vsync_comp;
+};
+
+int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
+
+#endif /* MDP3_CTRL_H */
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
new file mode 100644
index 0000000..69e3d7e
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -0,0 +1,914 @@
+/* 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/bitops.h>
+#include <linux/iopoll.h>
+
+#include "mdp3.h"
+#include "mdp3_dma.h"
+#include "mdp3_hwio.h"
+
+#define DMA_STOP_POLL_SLEEP_US 1000
+#define DMA_STOP_POLL_TIMEOUT_US 16000
+
+static ktime_t mdp3_get_vsync_time(struct mdp3_dma *dma)
+{
+ unsigned long flag;
+ ktime_t time;
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ time = dma->vsync_time;
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+ return time;
+}
+
+static void mdp3_vsync_intr_handler(int type, void *arg)
+{
+ struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+ struct mdp3_vsync_notification vsync_client;
+
+ pr_debug("mdp3_vsync_intr_handler\n");
+ spin_lock(&dma->dma_lock);
+ vsync_client = dma->vsync_client;
+ if (!vsync_client.handler)
+ dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_VSYNC;
+ dma->vsync_time = ktime_get();
+ complete(&dma->vsync_comp);
+ if (vsync_client.handler)
+ vsync_client.handler(vsync_client.arg);
+ spin_unlock(&dma->dma_lock);
+
+ if (!vsync_client.handler)
+ mdp3_irq_disable_nosync(type);
+}
+
+static void mdp3_dma_done_intr_handler(int type, void *arg)
+{
+ struct mdp3_dma *dma = (struct mdp3_dma *)arg;
+
+ pr_debug("mdp3_dma_done_intr_handler\n");
+ spin_lock(&dma->dma_lock);
+ dma->busy = false;
+ dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+ spin_unlock(&dma->dma_lock);
+ complete(&dma->dma_comp);
+ mdp3_irq_disable_nosync(type);
+}
+
+void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type)
+{
+ int irq_bit;
+ unsigned long flag;
+
+ pr_debug("mdp3_dma_callback_enable type=%d\n", type);
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (dma->cb_type & type) {
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+ return;
+ } else {
+ dma->cb_type |= type;
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+ }
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
+ mdp3_irq_enable(MDP3_INTR_LCDC_START_OF_FRAME);
+ } else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
+ irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+ irq_bit += dma->dma_sel;
+ mdp3_irq_enable(irq_bit);
+ }
+
+ if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
+ irq_bit = MDP3_INTR_DMA_P_DONE;
+ if (dma->dma_sel == MDP3_DMA_S)
+ irq_bit = MDP3_INTR_DMA_S_DONE;
+ mdp3_irq_enable(irq_bit);
+ }
+ } else {
+ pr_err("mdp3_dma_callback_enable not supported interface\n");
+ }
+}
+
+void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type)
+{
+ int irq_bit;
+ unsigned long flag;
+
+ pr_debug("mdp3_dma_callback_disable type=%d\n", type);
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if ((dma->cb_type & type) == 0) {
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+ return;
+ } else {
+ dma->cb_type &= ~type;
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+ }
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
+ mdp3_irq_disable(MDP3_INTR_LCDC_START_OF_FRAME);
+ } else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC) {
+ irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+ irq_bit += dma->dma_sel;
+ mdp3_irq_disable(irq_bit);
+ }
+
+ if (type & MDP3_DMA_CALLBACK_TYPE_DMA_DONE) {
+ irq_bit = MDP3_INTR_DMA_P_DONE;
+ if (dma->dma_sel == MDP3_DMA_S)
+ irq_bit = MDP3_INTR_DMA_S_DONE;
+ mdp3_irq_disable(irq_bit);
+ }
+ }
+}
+
+static int mdp3_dma_callback_setup(struct mdp3_dma *dma)
+{
+ int rc;
+ struct mdp3_intr_cb vsync_cb = {
+ .cb = mdp3_vsync_intr_handler,
+ .data = dma,
+ };
+
+ struct mdp3_intr_cb dma_cb = {
+ .cb = mdp3_dma_done_intr_handler,
+ .data = dma,
+ };
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC)
+ rc = mdp3_set_intr_callback(MDP3_INTR_LCDC_START_OF_FRAME,
+ &vsync_cb);
+ else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ int irq_bit = MDP3_INTR_SYNC_PRIMARY_LINE;
+ irq_bit += dma->dma_sel;
+ rc = mdp3_set_intr_callback(irq_bit, &vsync_cb);
+ irq_bit = MDP3_INTR_DMA_P_DONE;
+ if (dma->dma_sel == MDP3_DMA_S)
+ irq_bit = MDP3_INTR_DMA_S_DONE;
+ rc |= mdp3_set_intr_callback(irq_bit, &dma_cb);
+ } else {
+ pr_err("mdp3_dma_callback_setup not suppported interface\n");
+ rc = -ENODEV;
+ }
+ return rc;
+}
+
+static void mdp3_dma_vsync_enable(struct mdp3_dma *dma,
+ struct mdp3_vsync_notification *vsync_client)
+{
+ unsigned long flag;
+ int updated = 0;
+ int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+ pr_debug("mdp3_dma_vsync_enable\n");
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (vsync_client) {
+ if (dma->vsync_client.handler != vsync_client->handler) {
+ dma->vsync_client = *vsync_client;
+ updated = 1;
+ }
+ } else {
+ if (!dma->vsync_client.handler) {
+ dma->vsync_client.handler = NULL;
+ dma->vsync_client.arg = NULL;
+ updated = 1;
+ }
+ }
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ if (updated) {
+ if (vsync_client && vsync_client->handler)
+ mdp3_dma_callback_enable(dma, cb_type);
+ else
+ mdp3_dma_callback_disable(dma, cb_type);
+ }
+}
+
+static int mdp3_dmap_config(struct mdp3_dma *dma,
+ struct mdp3_dma_source *source_config,
+ struct mdp3_dma_output_config *output_config)
+{
+ u32 dma_p_cfg_reg, dma_p_size, dma_p_out_xy;
+
+ dma_p_cfg_reg = source_config->format << 25;
+ if (output_config->dither_en)
+ dma_p_cfg_reg |= BIT(24);
+ dma_p_cfg_reg |= output_config->out_sel << 19;
+ dma_p_cfg_reg |= output_config->bit_mask_polarity << 18;
+ dma_p_cfg_reg |= output_config->color_components_flip << 14;
+ dma_p_cfg_reg |= output_config->pack_pattern << 8;
+ dma_p_cfg_reg |= output_config->pack_align << 7;
+ dma_p_cfg_reg |= output_config->color_comp_out_bits;
+
+ dma_p_size = source_config->width | (source_config->height << 16);
+ dma_p_out_xy = source_config->x | (source_config->y << 16);
+
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)source_config->buf);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_OUT_XY, dma_p_out_xy);
+
+ /*
+ * NOTE: MDP_DMA_P_FETCH_CFG: max_burst_size need to use value 4, not
+ * the default 16 for MDP hang issue workaround
+ */
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_FETCH_CFG, 0x10);
+ MDP3_REG_WRITE(MDP3_REG_PRIMARY_RD_PTR_IRQ, 0x10);
+
+ dma->source_config = *source_config;
+ dma->output_config = *output_config;
+
+ mdp3_dma_callback_setup(dma);
+ return 0;
+}
+
+static int mdp3_dmas_config(struct mdp3_dma *dma,
+ struct mdp3_dma_source *source_config,
+ struct mdp3_dma_output_config *output_config)
+{
+ u32 dma_s_cfg_reg, dma_s_size, dma_s_out_xy;
+
+ dma_s_cfg_reg = source_config->format << 25;
+ if (output_config->dither_en)
+ dma_s_cfg_reg |= BIT(24);
+ dma_s_cfg_reg |= output_config->out_sel << 19;
+ dma_s_cfg_reg |= output_config->bit_mask_polarity << 18;
+ dma_s_cfg_reg |= output_config->color_components_flip << 14;
+ dma_s_cfg_reg |= output_config->pack_pattern << 8;
+ dma_s_cfg_reg |= output_config->pack_align << 7;
+ dma_s_cfg_reg |= output_config->color_comp_out_bits;
+
+ dma_s_size = source_config->width | (source_config->height << 16);
+ dma_s_out_xy = source_config->x | (source_config->y << 16);
+
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_CONFIG, dma_s_cfg_reg);
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_SIZE, dma_s_size);
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)source_config->buf);
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_Y_STRIDE, source_config->stride);
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_OUT_XY, dma_s_out_xy);
+
+ MDP3_REG_WRITE(MDP3_REG_SECONDARY_RD_PTR_IRQ, 0x10);
+
+ dma->source_config = *source_config;
+ dma->output_config = *output_config;
+
+ mdp3_dma_callback_setup(dma);
+ return 0;
+}
+
+static int mdp3_dmap_cursor_config(struct mdp3_dma *dma,
+ struct mdp3_dma_cursor *cursor)
+{
+ u32 cursor_size, cursor_pos, blend_param, trans_mask;
+
+ cursor_size = cursor->width | (cursor->height << 16);
+ cursor_pos = cursor->x | (cursor->y << 16);
+ trans_mask = 0;
+ if (cursor->blend_config.mode == MDP3_DMA_CURSOR_BLEND_CONSTANT_ALPHA) {
+ blend_param = cursor->blend_config.constant_alpha << 24;
+ } else if (cursor->blend_config.mode ==
+ MDP3_DMA_CURSOR_BLEND_COLOR_KEYING) {
+ blend_param = cursor->blend_config.transparent_color;
+ trans_mask = cursor->blend_config.transparency_mask;
+ } else {
+ blend_param = 0;
+ }
+
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_FORMAT, cursor->format);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_SIZE, cursor_size);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BUF_ADDR, (u32)cursor->buf);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_CONFIG,
+ cursor->blend_config.mode);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_PARAM, blend_param);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_BLEND_TRANS_MASK, trans_mask);
+ dma->cursor = *cursor;
+ return 0;
+}
+
+static int mdp3_dmap_ccs_config(struct mdp3_dma *dma,
+ struct mdp3_dma_color_correct_config *config,
+ struct mdp3_dma_ccs *ccs,
+ struct mdp3_dma_lut *lut)
+{
+ int i;
+ u32 addr, cc_config, color;
+
+ cc_config = config->lut_enable;
+ if (config->ccs_enable)
+ cc_config |= BIT(3);
+ cc_config |= config->lut_position << 4;
+ cc_config |= config->ccs_sel << 5;
+ cc_config |= config->pre_bias_sel << 6;
+ cc_config |= config->post_bias_sel << 7;
+ cc_config |= config->pre_limit_sel << 8;
+ cc_config |= config->post_limit_sel << 9;
+ cc_config |= config->lut_sel << 10;
+
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG, cc_config);
+
+ if (config->ccs_enable && ccs) {
+ if (ccs->mv1) {
+ addr = MDP3_REG_DMA_P_CSC_MV1;
+ for (i = 0; i < 9; i++) {
+ MDP3_REG_WRITE(addr, ccs->mv1[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->mv2) {
+ addr = MDP3_REG_DMA_P_CSC_MV2;
+ for (i = 0; i < 9; i++) {
+ MDP3_REG_WRITE(addr, ccs->mv2[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->pre_bv1) {
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV1;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_bv1[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->pre_bv2) {
+ addr = MDP3_REG_DMA_P_CSC_PRE_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_bv2[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->post_bv1) {
+ addr = MDP3_REG_DMA_P_CSC_POST_BV1;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_bv1[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->post_bv2) {
+ addr = MDP3_REG_DMA_P_CSC_POST_BV2;
+ for (i = 0; i < 3; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_bv2[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->pre_lv1) {
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV1;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_lv1[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->pre_lv2) {
+ addr = MDP3_REG_DMA_P_CSC_PRE_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->pre_lv2[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->post_lv1) {
+ addr = MDP3_REG_DMA_P_CSC_POST_LV1;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_lv1[i]);
+ addr += 4;
+ }
+ }
+
+ if (ccs->post_lv2) {
+ addr = MDP3_REG_DMA_P_CSC_POST_LV2;
+ for (i = 0; i < 6; i++) {
+ MDP3_REG_WRITE(addr, ccs->post_lv2[i]);
+ addr += 4;
+ }
+ }
+ }
+
+ if (config->lut_enable && lut) {
+ if (lut->color0_lut1 && lut->color1_lut1 && lut->color2_lut1) {
+ addr = MDP3_REG_DMA_P_CSC_LUT1;
+ for (i = 0; i < 256; i++) {
+ color = lut->color0_lut1[i];
+ color |= lut->color1_lut1[i] << 8;
+ color |= lut->color2_lut1[i] << 16;
+ MDP3_REG_WRITE(addr, color);
+ addr += 4;
+ }
+ }
+
+ if (lut->color0_lut2 && lut->color1_lut2 && lut->color2_lut2) {
+ addr = MDP3_REG_DMA_P_CSC_LUT2;
+ for (i = 0; i < 256; i++) {
+ color = lut->color0_lut2[i];
+ color |= lut->color1_lut2[i] << 8;
+ color |= lut->color2_lut2[i] << 16;
+ MDP3_REG_WRITE(addr, color);
+ addr += 4;
+ }
+ }
+ }
+
+ dma->ccs_config = *config;
+ return 0;
+}
+
+static int mdp3_dmap_histo_config(struct mdp3_dma *dma,
+ struct mdp3_dma_histogram_config *histo_config)
+{
+ u32 hist_bit_mask, hist_control;
+
+ if (histo_config->bit_mask_polarity)
+ hist_bit_mask = BIT(31);
+ hist_bit_mask |= histo_config->bit_mask;
+
+ if (histo_config->auto_clear_en)
+ hist_control = BIT(0);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_FRAME_CNT,
+ histo_config->frame_count);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_BIT_MASK, hist_bit_mask);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CONTROL, hist_control);
+ return 0;
+}
+
+static int mdp3_dmap_update(struct mdp3_dma *dma, void *buf)
+{
+ int wait_for_dma_done = 0;
+ unsigned long flag;
+ int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+ pr_debug("mdp3_dmap_update\n");
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (dma->busy)
+ wait_for_dma_done = 1;
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ if (wait_for_dma_done)
+ wait_for_completion_killable(&dma->dma_comp);
+ }
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, (u32)buf);
+ dma->source_config.buf = buf;
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_START, 1);
+ dma->busy = true;
+ }
+ wmb();
+ init_completion(&dma->vsync_comp);
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ mdp3_dma_callback_enable(dma, cb_type);
+ pr_debug("mdp3_dmap_update wait for vsync_comp in\n");
+ wait_for_completion_killable(&dma->vsync_comp);
+ pr_debug("mdp3_dmap_update wait for vsync_comp out\n");
+ return 0;
+}
+
+static int mdp3_dmas_update(struct mdp3_dma *dma, void *buf)
+{
+ int wait_for_dma_done = 0;
+ unsigned long flag;
+ int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (dma->busy)
+ wait_for_dma_done = 1;
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ if (wait_for_dma_done)
+ wait_for_completion_killable(&dma->dma_comp);
+ }
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_ADDR, (u32)buf);
+ dma->source_config.buf = buf;
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ MDP3_REG_WRITE(MDP3_REG_DMA_S_START, 1);
+ dma->busy = true;
+ }
+ wmb();
+ init_completion(&dma->vsync_comp);
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ mdp3_dma_callback_enable(dma, cb_type);
+ wait_for_completion_killable(&dma->vsync_comp);
+ return 0;
+}
+
+static int mdp3_dmap_cursor_update(struct mdp3_dma *dma, int x, int y)
+{
+ u32 cursor_pos;
+
+ cursor_pos = x | (y << 16);
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_CURSOR_POS, cursor_pos);
+ dma->cursor.x = x;
+ dma->cursor.y = y;
+ return 0;
+}
+
+static int mdp3_dmap_histo_get(struct mdp3_dma *dma,
+ struct mdp3_dma_histogram_data *data)
+{
+ int i;
+ u32 addr, extra;
+
+ addr = MDP3_REG_DMA_P_HIST_R_DATA;
+ for (i = 0; i < 32; i++) {
+ data->r_data[i] = MDP3_REG_READ(addr);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_HIST_G_DATA;
+ for (i = 0; i < 32; i++) {
+ data->g_data[i] = MDP3_REG_READ(addr);
+ addr += 4;
+ }
+
+ addr = MDP3_REG_DMA_P_HIST_B_DATA;
+ for (i = 0; i < 32; i++) {
+ data->b_data[i] = MDP3_REG_READ(addr);
+ addr += 4;
+ }
+
+ extra = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_0);
+ data->r_min_value = (extra & 0x1F0000) >> 16;
+ data->r_max_value = (extra & 0x1F000000) >> 24;
+ extra = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_EXTRA_INFO_1);
+ data->g_min_value = extra & 0x1F;
+ data->g_max_value = (extra & 0x1F00) >> 8;
+ data->b_min_value = (extra & 0x1F0000) >> 16;
+ data->b_max_value = (extra & 0x1F000000) >> 24;
+ return 0;
+}
+
+static int mdp3_dmap_histo_op(struct mdp3_dma *dma, u32 op)
+{
+ switch (op) {
+ case MDP3_DMA_HISTO_OP_START:
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_START, 1);
+ break;
+ case MDP3_DMA_HISTO_OP_STOP:
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_STOP_REQ, 1);
+ break;
+ case MDP3_DMA_HISTO_OP_CANCEL:
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_CANCEL_REQ, 1);
+ break;
+ case MDP3_DMA_HISTO_OP_RESET:
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_RESET_SEQ_START, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int mdp3_dmap_histo_intr_status(struct mdp3_dma *dma, int *status)
+{
+ *status = MDP3_REG_READ(MDP3_REG_DMA_P_HIST_INTR_STATUS);
+ return 0;
+}
+
+static int mdp3_dmap_histo_intr_enable(struct mdp3_dma *dma, u32 mask)
+{
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_ENABLE, mask);
+ return 0;
+}
+
+static int mdp3_dmap_histo_intr_clear(struct mdp3_dma *dma, u32 mask)
+{
+ MDP3_REG_WRITE(MDP3_REG_DMA_P_HIST_INTR_CLEAR, mask);
+ return 0;
+}
+
+static int mdp3_dma_start(struct mdp3_dma *dma, struct mdp3_intf *intf)
+{
+ unsigned long flag;
+ int cb_type = MDP3_DMA_CALLBACK_TYPE_VSYNC;
+ u32 dma_start_offset = MDP3_REG_DMA_P_START;
+
+ if (dma->dma_sel == MDP3_DMA_P)
+ dma_start_offset = MDP3_REG_DMA_P_START;
+ else if (dma->dma_sel == MDP3_DMA_S)
+ dma_start_offset = MDP3_REG_DMA_S_START;
+ else
+ return -EINVAL;
+
+ spin_lock_irqsave(&dma->dma_lock, flag);
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
+ cb_type |= MDP3_DMA_CALLBACK_TYPE_DMA_DONE;
+ MDP3_REG_WRITE(dma_start_offset, 1);
+ dma->busy = true;
+ }
+
+ intf->start(intf);
+ wmb();
+ init_completion(&dma->vsync_comp);
+ spin_unlock_irqrestore(&dma->dma_lock, flag);
+
+ mdp3_dma_callback_enable(dma, cb_type);
+ pr_debug("mdp3_dma_start wait for vsync_comp in\n");
+ wait_for_completion_killable(&dma->vsync_comp);
+ pr_debug("mdp3_dma_start wait for vsync_comp out\n");
+ return 0;
+}
+
+static int mdp3_dma_stop(struct mdp3_dma *dma, struct mdp3_intf *intf)
+{
+ int ret = 0;
+ u32 status, display_status_bit;
+
+ if (dma->dma_sel == MDP3_DMA_P)
+ display_status_bit = BIT(6);
+ else if (dma->dma_sel == MDP3_DMA_S)
+ display_status_bit = BIT(7);
+ else
+ return -EINVAL;
+
+ if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+ display_status_bit |= BIT(11);
+
+ intf->stop(intf);
+ ret = readl_poll_timeout((mdp3_res->mdp_base + MDP3_REG_DISPLAY_STATUS),
+ status,
+ ((status & display_status_bit) == 0),
+ DMA_STOP_POLL_SLEEP_US,
+ DMA_STOP_POLL_TIMEOUT_US);
+
+ mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_VSYNC |
+ MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
+
+ dma->busy = false;
+ return ret;
+}
+
+int mdp3_dma_init(struct mdp3_dma *dma,
+ struct mdp3_dma_source *source_config,
+ struct mdp3_dma_output_config *output_config)
+{
+ int ret = 0;
+
+ pr_debug("mdp3_dma_init\n");
+ switch (dma->dma_sel) {
+ case MDP3_DMA_P:
+ dma->busy = 0;
+
+ ret = mdp3_dmap_config(dma, source_config, output_config);
+ if (ret < 0)
+ return ret;
+
+ dma->config_cursor = mdp3_dmap_cursor_config;
+ dma->config_ccs = mdp3_dmap_ccs_config;
+ dma->config_histo = mdp3_dmap_histo_config;
+ dma->update = mdp3_dmap_update;
+ dma->update_cursor = mdp3_dmap_cursor_update;
+ dma->get_histo = mdp3_dmap_histo_get;
+ dma->histo_op = mdp3_dmap_histo_op;
+ dma->histo_intr_status = mdp3_dmap_histo_intr_status;
+ dma->histo_intr_enable = mdp3_dmap_histo_intr_enable;
+ dma->histo_intr_clear = mdp3_dmap_histo_intr_clear;
+ dma->vsync_enable = mdp3_dma_vsync_enable;
+ dma->get_vsync_time = mdp3_get_vsync_time;
+ dma->start = mdp3_dma_start;
+ dma->stop = mdp3_dma_stop;
+ break;
+ case MDP3_DMA_S:
+ dma->busy = 0;
+ ret = mdp3_dmas_config(dma, source_config, output_config);
+ if (ret < 0)
+ return ret;
+
+ dma->config_cursor = NULL;
+ dma->config_ccs = NULL;
+ dma->config_histo = NULL;
+ dma->update = mdp3_dmas_update;
+ dma->update_cursor = NULL;
+ dma->get_histo = NULL;
+ dma->histo_op = NULL;
+ dma->histo_intr_status = NULL;
+ dma->histo_intr_enable = NULL;
+ dma->histo_intr_clear = NULL;
+ dma->vsync_enable = mdp3_dma_vsync_enable;
+ dma->get_vsync_time = mdp3_get_vsync_time;
+ dma->start = mdp3_dma_start;
+ dma->stop = mdp3_dma_stop;
+ break;
+ case MDP3_DMA_E:
+ default:
+ ret = -ENODEV;
+ break;
+ }
+
+ spin_lock_init(&dma->dma_lock);
+ init_completion(&dma->vsync_comp);
+ init_completion(&dma->dma_comp);
+ dma->cb_type = 0;
+ dma->vsync_client.handler = NULL;
+ dma->vsync_client.arg = NULL;
+
+ memset(&dma->cursor, 0, sizeof(dma->cursor));
+ memset(&dma->ccs_config, 0, sizeof(dma->ccs_config));
+ memset(&dma->histogram_config, 0, sizeof(dma->histogram_config));
+
+ return ret;
+}
+
+int lcdc_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+ u32 temp;
+ struct mdp3_video_intf_cfg *v = &cfg->video;
+ temp = v->hsync_pulse_width | (v->hsync_period << 16);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_CTL, temp);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PERIOD, v->vsync_period);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_VSYNC_PULSE_WIDTH, v->vsync_pulse_width);
+ temp = v->display_start_x | (v->display_end_x << 16);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_HCTL, temp);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_START, v->display_start_y);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_DISPLAY_V_END, v->display_end_y);
+ temp = v->active_start_x | (v->active_end_x);
+ if (v->active_h_enable)
+ temp |= BIT(31);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_HCTL, temp);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_START, v->active_start_y);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_ACTIVE_V_END, v->active_end_y);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_HSYNC_SKEW, v->hsync_skew);
+ temp = 0;
+ if (!v->hsync_polarity)
+ temp = BIT(0);
+ if (!v->vsync_polarity)
+ temp = BIT(1);
+ if (!v->de_polarity)
+ temp = BIT(2);
+ MDP3_REG_WRITE(MDP3_REG_LCDC_CTL_POLARITY, temp);
+
+ return 0;
+}
+
+int lcdc_start(struct mdp3_intf *intf)
+{
+ MDP3_REG_WRITE(MDP3_REG_LCDC_EN, BIT(0));
+ wmb();
+ intf->active = true;
+ return 0;
+}
+
+int lcdc_stop(struct mdp3_intf *intf)
+{
+ MDP3_REG_WRITE(MDP3_REG_LCDC_EN, 0);
+ wmb();
+ intf->active = false;
+ return 0;
+}
+
+int dsi_video_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+ u32 temp;
+ struct mdp3_video_intf_cfg *v = &cfg->video;
+
+ pr_debug("dsi_video_config\n");
+
+ temp = v->hsync_pulse_width | (v->hsync_period << 16);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_CTL, temp);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PERIOD, v->vsync_period);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_VSYNC_PULSE_WIDTH,
+ v->vsync_pulse_width);
+ temp = v->display_start_x | (v->display_end_x << 16);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_HCTL, temp);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_START, v->display_start_y);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_DISPLAY_V_END, v->display_end_y);
+ temp = v->active_start_x | (v->active_end_x << 16);
+ if (v->active_h_enable)
+ temp |= BIT(31);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_HCTL, temp);
+
+ temp = v->active_start_y;
+ if (v->active_v_enable)
+ temp |= BIT(31);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_START, temp);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_ACTIVE_V_END, v->active_end_y);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_HSYNC_SKEW, v->hsync_skew);
+ temp = 0;
+ if (!v->hsync_polarity)
+ temp |= BIT(0);
+ if (!v->vsync_polarity)
+ temp |= BIT(1);
+ if (!v->de_polarity)
+ temp |= BIT(2);
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_CTL_POLARITY, temp);
+
+ return 0;
+}
+
+int dsi_video_start(struct mdp3_intf *intf)
+{
+ pr_debug("dsi_video_start\n");
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, BIT(0));
+ wmb();
+ intf->active = true;
+ return 0;
+}
+
+int dsi_video_stop(struct mdp3_intf *intf)
+{
+ pr_debug("dsi_video_stop\n");
+ MDP3_REG_WRITE(MDP3_REG_DSI_VIDEO_EN, 0);
+ wmb();
+ intf->active = false;
+ return 0;
+}
+
+int dsi_cmd_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+ u32 id_map = 0;
+ u32 trigger_en = 0;
+
+ if (cfg->dsi_cmd.primary_dsi_cmd_id)
+ id_map = BIT(0);
+ if (cfg->dsi_cmd.secondary_dsi_cmd_id)
+ id_map = BIT(4);
+
+ if (cfg->dsi_cmd.dsi_cmd_tg_intf_sel)
+ trigger_en = BIT(4);
+
+ MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_ID_MAP, id_map);
+ MDP3_REG_WRITE(MDP3_REG_DSI_CMD_MODE_TRIGGER_EN, trigger_en);
+
+ return 0;
+}
+
+int dsi_cmd_start(struct mdp3_intf *intf)
+{
+ intf->active = true;
+ return 0;
+}
+
+int dsi_cmd_stop(struct mdp3_intf *intf)
+{
+ intf->active = false;
+ return 0;
+}
+
+int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+ int ret = 0;
+ switch (cfg->type) {
+ case MDP3_DMA_OUTPUT_SEL_LCDC:
+ intf->config = lcdc_config;
+ intf->start = lcdc_start;
+ intf->stop = lcdc_stop;
+ break;
+ case MDP3_DMA_OUTPUT_SEL_DSI_VIDEO:
+ intf->config = dsi_video_config;
+ intf->start = dsi_video_start;
+ intf->stop = dsi_video_stop;
+ break;
+ case MDP3_DMA_OUTPUT_SEL_DSI_CMD:
+ intf->config = dsi_cmd_config;
+ intf->start = dsi_cmd_start;
+ intf->stop = dsi_cmd_stop;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ intf->active = false;
+ if (intf->config)
+ ret = intf->config(intf, cfg);
+
+ if (ret) {
+ pr_err("MDP interface initialization failed\n");
+ return ret;
+ }
+
+ intf->cfg = *cfg;
+ return 0;
+}
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
new file mode 100644
index 0000000..2fb8427
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -0,0 +1,336 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_DMA_H
+#define MDP3_DMA_H
+
+#include <linux/sched.h>
+
+enum {
+ MDP3_DMA_P,
+ MDP3_DMA_S,
+ MDP3_DMA_E,
+ MDP3_DMA_MAX
+};
+
+enum {
+ MDP3_DMA_CAP_CURSOR = 0x1,
+ MDP3_DMA_CAP_COLOR_CORRECTION = 0x2,
+ MDP3_DMA_CAP_HISTOGRAM = 0x4,
+ MDP3_DMA_CAP_GAMMA_CORRECTION = 0x8,
+ MDP3_DMA_CAP_DITHER = 0x10,
+ MDP3_DMA_CAP_ALL = 0x1F
+};
+
+enum {
+ MDP3_DMA_OUTPUT_SEL_AHB,
+ MDP3_DMA_OUTPUT_SEL_DSI_CMD,
+ MDP3_DMA_OUTPUT_SEL_LCDC,
+ MDP3_DMA_OUTPUT_SEL_DSI_VIDEO,
+ MDP3_DMA_OUTPUT_SEL_MAX
+};
+
+enum {
+ MDP3_DMA_IBUF_FORMAT_RGB888,
+ MDP3_DMA_IBUF_FORMAT_RGB565,
+ MDP3_DMA_IBUF_FORMAT_XRGB8888,
+ MDP3_DMA_IBUF_FORMAT_UNDEFINED
+};
+
+enum {
+ MDP3_DMA_OUTPUT_PACK_PATTERN_RGB = 0x21,
+ MDP3_DMA_OUTPUT_PACK_PATTERN_RBG = 0x24,
+ MDP3_DMA_OUTPUT_PACK_PATTERN_BGR = 0x12,
+ MDP3_DMA_OUTPUT_PACK_PATTERN_BRG = 0x18,
+ MDP3_DMA_OUTPUT_PACK_PATTERN_GBR = 0x06,
+ MDP3_DMA_OUTPUT_PACK_PATTERN_GRB = 0x09,
+};
+
+enum {
+ MDP3_DMA_OUTPUT_PACK_ALIGN_LSB,
+ MDP3_DMA_OUTPUT_PACK_ALIGN_MSB
+};
+
+enum {
+ MDP3_DMA_OUTPUT_COMP_BITS_4, /*4 bits per color component*/
+ MDP3_DMA_OUTPUT_COMP_BITS_5,
+ MDP3_DMA_OUTPUT_COMP_BITS_6,
+ MDP3_DMA_OUTPUT_COMP_BITS_8,
+};
+
+enum {
+ MDP3_DMA_CURSOR_FORMAT_ARGB888,
+};
+
+enum {
+ MDP3_DMA_COLOR_CORRECT_SET_1,
+ MDP3_DMA_COLOR_CORRECT_SET_2
+};
+
+enum {
+ MDP3_DMA_LUT_POSITION_PRE,
+ MDP3_DMA_LUT_POSITION_POST
+};
+
+enum {
+ MDP3_DMA_LUT_DISABLE = 0x0,
+ MDP3_DMA_LUT_ENABLE_C0 = 0x01,
+ MDP3_DMA_LUT_ENABLE_C1 = 0x02,
+ MDP3_DMA_LUT_ENABLE_C2 = 0x04,
+ MDP3_DMA_LUT_ENABLE_ALL = 0x07,
+};
+
+enum {
+ MDP3_DMA_HISTOGRAM_BIT_MASK_NONE = 0X0,
+ MDP3_DMA_HISTOGRAM_BIT_MASK_ONE_MSB = 0x1,
+ MDP3_DMA_HISTOGRAM_BIT_MASK_TWO_MSB = 0x2,
+ MDP3_DMA_HISTOGRAM_BIT_MASK_THREE_MSB = 0x3
+};
+
+enum {
+ MDP3_DMA_COLOR_FLIP_NONE,
+ MDP3_DMA_COLOR_FLIP_COMP1 = 0x1,
+ MDP3_DMA_COLOR_FLIP_COMP2 = 0x2,
+ MDP3_DMA_COLOR_FLIP_COMP3 = 0x4,
+};
+
+enum {
+ MDP3_DMA_CURSOR_BLEND_NONE = 0x0,
+ MDP3_DMA_CURSOR_BLEND_PER_PIXEL_ALPHA = 0x3,
+ MDP3_DMA_CURSOR_BLEND_CONSTANT_ALPHA = 0x5,
+ MDP3_DMA_CURSOR_BLEND_COLOR_KEYING = 0x9
+};
+
+enum {
+ MDP3_DMA_HISTO_OP_START,
+ MDP3_DMA_HISTO_OP_STOP,
+ MDP3_DMA_HISTO_OP_CANCEL,
+ MDP3_DMA_HISTO_OP_RESET
+};
+
+enum {
+ MDP3_DMA_CALLBACK_TYPE_VSYNC = 0x01,
+ MDP3_DMA_CALLBACK_TYPE_DMA_DONE = 0x02,
+};
+
+struct mdp3_dma_source {
+ u32 format;
+ int width;
+ int height;
+ int x;
+ int y;
+ void *buf;
+ int stride;
+};
+
+struct mdp3_dma_output_config {
+ int dither_en;
+ u32 out_sel;
+ u32 bit_mask_polarity;
+ u32 color_components_flip;
+ u32 pack_pattern;
+ u32 pack_align;
+ u32 color_comp_out_bits;
+};
+
+struct mdp3_dma_cursor_blend_config {
+ u32 mode;
+ u32 transparent_color; /*color keying*/
+ u32 transparency_mask;
+ u32 constant_alpha;
+};
+
+struct mdp3_dma_cursor {
+ int enable; /* enable cursor or not*/
+ u32 format;
+ int width;
+ int height;
+ int x;
+ int y;
+ void *buf;
+ struct mdp3_dma_cursor_blend_config blend_config;
+};
+
+struct mdp3_dma_ccs {
+ u32 *mv1; /*set1 matrix vector, 3x3 */
+ u32 *mv2;
+ u32 *pre_bv1; /*pre-bias vector for set1, 1x3*/
+ u32 *pre_bv2;
+ u32 *post_bv1; /*post-bias vecotr for set1, */
+ u32 *post_bv2;
+ u32 *pre_lv1; /*pre-limit vector for set 1, 1x6*/
+ u32 *pre_lv2;
+ u32 *post_lv1;
+ u32 *post_lv2;
+};
+
+struct mdp3_dma_lut {
+ uint8_t *color0_lut1;
+ uint8_t *color1_lut1;
+ uint8_t *color2_lut1;
+ uint8_t *color0_lut2;
+ uint8_t *color1_lut2;
+ uint8_t *color2_lut2;
+};
+
+struct mdp3_dma_color_correct_config {
+ int ccs_enable;
+ int lut_enable;
+ u32 lut_sel;
+ u32 post_limit_sel;
+ u32 pre_limit_sel;
+ u32 post_bias_sel;
+ u32 pre_bias_sel;
+ u32 ccs_sel;
+ u32 lut_position;
+};
+
+struct mdp3_dma_histogram_config {
+ int frame_count;
+ u32 bit_mask_polarity;
+ u32 bit_mask;
+ int auto_clear_en;
+};
+
+struct mdp3_dma_histogram_data {
+ uint8_t r_max_value;
+ uint8_t r_min_value;
+ uint8_t b_max_value;
+ uint8_t b_min_value;
+ uint8_t g_max_value;
+ uint8_t g_min_value;
+ uint8_t r_data[32];
+ uint8_t g_data[32];
+ uint8_t b_data[32];
+};
+
+struct mdp3_vsync_notification {
+ void (*handler)(void *arg);
+ void *arg;
+};
+
+struct mdp3_intf;
+
+struct mdp3_dma {
+ u32 dma_sel;
+ u32 capability;
+ int in_use;
+ int available;
+ int busy;
+
+ spinlock_t dma_lock;
+ struct completion vsync_comp;
+ struct completion dma_comp;
+ ktime_t vsync_time;
+ struct mdp3_vsync_notification vsync_client;
+ u32 cb_type;
+
+ struct mdp3_dma_output_config output_config;
+ struct mdp3_dma_source source_config;
+
+ struct mdp3_dma_cursor cursor;
+ struct mdp3_dma_color_correct_config ccs_config;
+ struct mdp3_dma_histogram_config histogram_config;
+
+ int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf);
+
+ int (*stop)(struct mdp3_dma *dma, struct mdp3_intf *intf);
+
+ int (*config_cursor)(struct mdp3_dma *dma,
+ struct mdp3_dma_cursor *cursor);
+
+ int (*config_ccs)(struct mdp3_dma *dma,
+ struct mdp3_dma_color_correct_config *config,
+ struct mdp3_dma_ccs *ccs,
+ struct mdp3_dma_lut *lut);
+
+ int (*update)(struct mdp3_dma *dma, void *buf);
+
+ int (*update_cursor)(struct mdp3_dma *dma, int x, int y);
+
+ int (*get_histo)(struct mdp3_dma *dma,
+ struct mdp3_dma_histogram_data *data);
+
+ int (*config_histo)(struct mdp3_dma *dma,
+ struct mdp3_dma_histogram_config *histo_config);
+
+ int (*histo_op)(struct mdp3_dma *dma,
+ u32 op);
+
+ int (*histo_intr_status)(struct mdp3_dma *dma, int *status);
+
+ int (*histo_intr_enable)(struct mdp3_dma *dma, u32 mask);
+
+ int (*histo_intr_clear)(struct mdp3_dma *dma, u32 mask);
+
+ void (*vsync_enable)(struct mdp3_dma *dma,
+ struct mdp3_vsync_notification *vsync_client);
+
+ ktime_t (*get_vsync_time)(struct mdp3_dma *dma);
+
+};
+
+struct mdp3_video_intf_cfg {
+ int hsync_period;
+ int hsync_pulse_width;
+ int vsync_period;
+ int vsync_pulse_width;
+ int display_start_x;
+ int display_end_x;
+ int display_start_y;
+ int display_end_y;
+ int active_start_x;
+ int active_end_x;
+ int active_h_enable;
+ int active_start_y;
+ int active_end_y;
+ int active_v_enable;
+ int hsync_skew;
+ int hsync_polarity;
+ int vsync_polarity;
+ int de_polarity;
+};
+
+struct mdp3_dsi_cmd_intf_cfg {
+ int primary_dsi_cmd_id;
+ int secondary_dsi_cmd_id;
+ int dsi_cmd_tg_intf_sel;
+};
+
+struct mdp3_intf_cfg {
+ u32 type;
+ struct mdp3_video_intf_cfg video;
+ struct mdp3_dsi_cmd_intf_cfg dsi_cmd;
+};
+
+struct mdp3_intf {
+ struct mdp3_intf_cfg cfg;
+ int active;
+ int available;
+ int in_use;
+ int (*config)(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+ int (*start)(struct mdp3_intf *intf);
+ int (*stop)(struct mdp3_intf *intf);
+};
+
+int mdp3_dma_init(struct mdp3_dma *dma,
+ struct mdp3_dma_source *source_config,
+ struct mdp3_dma_output_config *output_config);
+
+int mdp3_intf_init(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg);
+
+void mdp3_dma_callback_enable(struct mdp3_dma *dma, int type);
+
+void mdp3_dma_callback_disable(struct mdp3_dma *dma, int type);
+
+#endif /* MDP3_DMA_H */
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
new file mode 100644
index 0000000..2763f46
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef MDP3_HWIO_H
+#define MDP3_HWIO_H
+
+#include <linux/bitops.h>
+
+/*synchronization*/
+#define MDP3_REG_SYNC_CONFIG_0 0x0300
+#define MDP3_REG_SYNC_CONFIG_1 0x0304
+#define MDP3_REG_SYNC_CONFIG_2 0x0308
+#define MDP3_REG_SYNC_STATUS_0 0x030c
+#define MDP3_REG_SYNC_STATUS_1 0x0310
+#define MDP3_REG_SYNC_STATUS_2 0x0314
+#define MDP3_REG_PRIMARY_VSYNC_OUT_CTRL 0x0318
+#define MDP3_REG_SECONDARY_VSYNC_OUT_CTRL 0x031c
+#define MDP3_REG_EXTERNAL_VSYNC_OUT_CTRL 0x0320
+#define MDP3_REG_VSYNC_SEL 0x0324
+
+/*interrupt*/
+#define MDP3_REG_INTR_ENABLE 0x0020
+#define MDP3_REG_INTR_STATUS 0x0024
+#define MDP3_REG_INTR_CLEAR 0x0028
+
+#define MDP3_REG_PRIMARY_RD_PTR_IRQ 0x021C
+#define MDP3_REG_SECONDARY_RD_PTR_IRQ 0x0220
+
+/*operation control*/
+#define MDP3_REG_DMA_P_START 0x0044
+#define MDP3_REG_DMA_S_START 0x0048
+#define MDP3_REG_DMA_E_START 0x004c
+
+#define MDP3_REG_DISPLAY_STATUS 0x0038
+
+#define MDP3_REG_HW_VERSION 0x0070
+#define MDP3_REG_SW_RESET 0x0074
+
+/*EBI*/
+#define MDP3_REG_EBI2_LCD0 0x003c
+#define MDP3_REG_EBI2_LCD0_YSTRIDE 0x0050
+
+/*DMA_P*/
+#define MDP3_REG_DMA_P_CONFIG 0x90000
+#define MDP3_REG_DMA_P_SIZE 0x90004
+#define MDP3_REG_DMA_P_IBUF_ADDR 0x90008
+#define MDP3_REG_DMA_P_IBUF_Y_STRIDE 0x9000C
+#define MDP3_REG_DMA_P_PROFILE_EN 0x90020
+#define MDP3_REG_DMA_P_OUT_XY 0x90010
+#define MDP3_REG_DMA_P_CURSOR_FORMAT 0x90040
+#define MDP3_REG_DMA_P_CURSOR_SIZE 0x90044
+#define MDP3_REG_DMA_P_CURSOR_BUF_ADDR 0x90048
+#define MDP3_REG_DMA_P_CURSOR_POS 0x9004c
+#define MDP3_REG_DMA_P_CURSOR_BLEND_CONFIG 0x90060
+#define MDP3_REG_DMA_P_CURSOR_BLEND_PARAM 0x90064
+#define MDP3_REG_DMA_P_CURSOR_BLEND_TRANS_MASK 0x90068
+#define MDP3_REG_DMA_P_COLOR_CORRECT_CONFIG 0x90070
+#define MDP3_REG_DMA_P_CSC_BYPASS 0X93004
+#define MDP3_REG_DMA_P_CSC_MV1 0x93400
+#define MDP3_REG_DMA_P_CSC_MV2 0x93440
+#define MDP3_REG_DMA_P_CSC_PRE_BV1 0x93500
+#define MDP3_REG_DMA_P_CSC_PRE_BV2 0x93540
+#define MDP3_REG_DMA_P_CSC_POST_BV1 0x93580
+#define MDP3_REG_DMA_P_CSC_POST_BV2 0x935c0
+#define MDP3_REG_DMA_P_CSC_PRE_LV1 0x93600
+#define MDP3_REG_DMA_P_CSC_PRE_LV2 0x93640
+#define MDP3_REG_DMA_P_CSC_POST_LV1 0x93680
+#define MDP3_REG_DMA_P_CSC_POST_LV2 0x936c0
+#define MDP3_REG_DMA_P_CSC_LUT1 0x93800
+#define MDP3_REG_DMA_P_CSC_LUT2 0x93c00
+#define MDP3_REG_DMA_P_HIST_START 0x94000
+#define MDP3_REG_DMA_P_HIST_FRAME_CNT 0x94004
+#define MDP3_REG_DMA_P_HIST_BIT_MASK 0x94008
+#define MDP3_REG_DMA_P_HIST_RESET_SEQ_START 0x9400c
+#define MDP3_REG_DMA_P_HIST_CONTROL 0x94010
+#define MDP3_REG_DMA_P_HIST_INTR_STATUS 0x94014
+#define MDP3_REG_DMA_P_HIST_INTR_CLEAR 0x94018
+#define MDP3_REG_DMA_P_HIST_INTR_ENABLE 0x9401c
+#define MDP3_REG_DMA_P_HIST_STOP_REQ 0x94020
+#define MDP3_REG_DMA_P_HIST_CANCEL_REQ 0x94024
+#define MDP3_REG_DMA_P_HIST_EXTRA_INFO_0 0x94028
+#define MDP3_REG_DMA_P_HIST_EXTRA_INFO_1 0x9402c
+#define MDP3_REG_DMA_P_HIST_R_DATA 0x94100
+#define MDP3_REG_DMA_P_HIST_G_DATA 0x94200
+#define MDP3_REG_DMA_P_HIST_B_DATA 0x94300
+#define MDP3_REG_DMA_P_FETCH_CFG 0x90074
+#define MDP3_REG_DMA_P_DCVS_CTRL 0x90080
+#define MDP3_REG_DMA_P_DCVS_STATUS 0x90084
+
+/*DMA_S*/
+#define MDP3_REG_DMA_S_CONFIG 0x90000
+#define MDP3_REG_DMA_S_SIZE 0x90004
+#define MDP3_REG_DMA_S_IBUF_ADDR 0x90008
+#define MDP3_REG_DMA_S_IBUF_Y_STRIDE 0x9000C
+#define MDP3_REG_DMA_S_OUT_XY 0x90010
+
+/*interface*/
+#define MDP3_REG_LCDC_EN 0xE0000
+#define MDP3_REG_LCDC_HSYNC_CTL 0xE0004
+#define MDP3_REG_LCDC_VSYNC_PERIOD 0xE0008
+#define MDP3_REG_LCDC_VSYNC_PULSE_WIDTH 0xE000C
+#define MDP3_REG_LCDC_DISPLAY_HCTL 0xE0010
+#define MDP3_REG_LCDC_DISPLAY_V_START 0xE0014
+#define MDP3_REG_LCDC_DISPLAY_V_END 0xE0018
+#define MDP3_REG_LCDC_ACTIVE_HCTL 0xE001C
+#define MDP3_REG_LCDC_ACTIVE_V_START 0xE0020
+#define MDP3_REG_LCDC_ACTIVE_V_END 0xE0024
+#define MDP3_REG_LCDC_BORDER_COLOR 0xE0028
+#define MDP3_REG_LCDC_UNDERFLOW_CTL 0xE002C
+#define MDP3_REG_LCDC_HSYNC_SKEW 0xE0030
+#define MDP3_REG_LCDC_TEST_CTL 0xE0034
+#define MDP3_REG_LCDC_CTL_POLARITY 0xE0038
+#define MDP3_REG_LCDC_TEST_COL_VAR1 0xE003C
+#define MDP3_REG_LCDC_TEST_COL_VAR2 0xE0040
+#define MDP3_REG_LCDC_UFLOW_HIDING_CTL 0xE0044
+#define MDP3_REG_LCDC_LOST_PIXEL_CNT_VALUE 0xE0048
+
+#define MDP3_REG_DSI_VIDEO_EN 0xF0000
+#define MDP3_REG_DSI_VIDEO_HSYNC_CTL 0xF0004
+#define MDP3_REG_DSI_VIDEO_VSYNC_PERIOD 0xF0008
+#define MDP3_REG_DSI_VIDEO_VSYNC_PULSE_WIDTH 0xF000C
+#define MDP3_REG_DSI_VIDEO_DISPLAY_HCTL 0xF0010
+#define MDP3_REG_DSI_VIDEO_DISPLAY_V_START 0xF0014
+#define MDP3_REG_DSI_VIDEO_DISPLAY_V_END 0xF0018
+#define MDP3_REG_DSI_VIDEO_ACTIVE_HCTL 0xF001C
+#define MDP3_REG_DSI_VIDEO_ACTIVE_V_START 0xF0020
+#define MDP3_REG_DSI_VIDEO_ACTIVE_V_END 0xF0024
+#define MDP3_REG_DSI_VIDEO_BORDER_COLOR 0xF0028
+#define MDP3_REG_DSI_VIDEO_UNDERFLOW_CTL 0xF002C
+#define MDP3_REG_DSI_VIDEO_HSYNC_SKEW 0xF0030
+#define MDP3_REG_DSI_VIDEO_TEST_CTL 0xF0034
+#define MDP3_REG_DSI_VIDEO_CTL_POLARITY 0xF0038
+#define MDP3_REG_DSI_VIDEO_TEST_COL_VAR1 0xF003C
+#define MDP3_REG_DSI_VIDEO_TEST_COL_VAR2 0xF0040
+#define MDP3_REG_DSI_VIDEO_UFLOW_HIDING_CTL 0xF0044
+#define MDP3_REG_DSI_VIDEO_LOST_PIXEL_CNT_VALUE 0xF0048
+
+#define MDP3_REG_DSI_CMD_MODE_ID_MAP 0xF1000
+#define MDP3_REG_DSI_CMD_MODE_TRIGGER_EN 0xF1004
+
+/*interrupt mask*/
+
+#define MDP3_INTR_DP0_ROI_DONE_BIT BIT(0)
+#define MDP3_INTR_DP1_ROI_DONE_BIT BIT(1)
+#define MDP3_INTR_DMA_S_DONE_BIT BIT(2)
+#define MDP3_INTR_DMA_E_DONE_BIT BIT(3)
+#define MDP3_INTR_DP0_TERMINAL_FRAME_DONE_BIT BIT(4)
+#define MDP3_INTR_DP1_TERMINAL_FRAME_DONE_BIT BIT(5)
+#define MDP3_INTR_DMA_TV_DONE_BIT BIT(6)
+#define MDP3_INTR_TV_ENCODER_UNDER_RUN_BIT BIT(7)
+#define MDP3_INTR_SYNC_PRIMARY_LINE_BIT BIT(8)
+#define MDP3_INTR_SYNC_SECONDARY_LINE_BIT BIT(9)
+#define MDP3_INTR_SYNC_EXTERNAL_LINE_BIT BIT(10)
+#define MDP3_INTR_DP0_FETCH_DONE_BIT BIT(11)
+#define MDP3_INTR_DP1_FETCH_DONE_BIT BIT(12)
+#define MDP3_INTR_TV_OUT_FRAME_START_BIT BIT(13)
+#define MDP3_INTR_DMA_P_DONE_BIT BIT(14)
+#define MDP3_INTR_LCDC_START_OF_FRAME_BIT BIT(15)
+#define MDP3_INTR_LCDC_UNDERFLOW_BIT BIT(16)
+#define MDP3_INTR_DMA_P_LINE_BIT BIT(17)
+#define MDP3_INTR_DMA_S_LINE_BIT BIT(18)
+#define MDP3_INTR_DMA_E_LINE_BIT BIT(19)
+#define MDP3_INTR_DMA_P_HISTO_BIT BIT(20)
+#define MDP3_INTR_DTV_OUT_DONE_BIT BIT(21)
+#define MDP3_INTR_DTV_OUT_START_OF_FRAME_BIT BIT(22)
+#define MDP3_INTR_DTV_OUT_UNDERFLOW_BIT BIT(23)
+#define MDP3_INTR_DTV_OUT_LINE_BIT BIT(24)
+#define MDP3_INTR_DMA_P_AUTO_FREFRESH_START_BIT BIT(25)
+#define MDP3_INTR_DMA_S_AUTO_FREFRESH_START_BIT BIT(26)
+#define MDP3_INTR_QPIC_EOF_ENABLE_BIT BIT(27)
+
+enum {
+ MDP3_INTR_DP0_ROI_DONE,
+ MDP3_INTR_DP1_ROI_DONE,
+ MDP3_INTR_DMA_S_DONE,
+ MDP3_INTR_DMA_E_DONE,
+ MDP3_INTR_DP0_TERMINAL_FRAME_DONE,
+ MDP3_INTR_DP1_TERMINAL_FRAME_DONE,
+ MDP3_INTR_DMA_TV_DONE,
+ MDP3_INTR_TV_ENCODER_UNDER_RUN,
+ MDP3_INTR_SYNC_PRIMARY_LINE,
+ MDP3_INTR_SYNC_SECONDARY_LINE,
+ MDP3_INTR_SYNC_EXTERNAL_LINE,
+ MDP3_INTR_DP0_FETCH_DONE,
+ MDP3_INTR_DP1_FETCH_DONE,
+ MDP3_INTR_TV_OUT_FRAME_START,
+ MDP3_INTR_DMA_P_DONE,
+ MDP3_INTR_LCDC_START_OF_FRAME,
+ MDP3_INTR_LCDC_UNDERFLOW,
+ MDP3_INTR_DMA_P_LINE,
+ MDP3_INTR_DMA_S_LINE,
+ MDP3_INTR_DMA_E_LINE,
+ MDP3_INTR_DMA_P_HISTO,
+ MDP3_INTR_DTV_OUT_DONE,
+ MDP3_INTR_DTV_OUT_START_OF_FRAME,
+ MDP3_INTR_DTV_OUT_UNDERFLOW,
+ MDP3_INTR_DTV_OUT_LINE,
+ MDP3_INTR_DMA_P_AUTO_FREFRESH_START,
+ MDP3_INTR_DMA_S_AUTO_FREFRESH_START,
+ MDP3_INTR_QPIC_EOF_ENABLE,
+};
+
+#define MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT BIT(0)
+#define MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT BIT(1)
+
+#endif /* MDP3_HWIO_H */
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 7dc4f49..0b2a7c0 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -24,7 +24,7 @@
#include "mdss_mdp.h"
#include "mdss_debug.h"
-#define DEFAULT_BASE_REG_CNT 128
+#define DEFAULT_BASE_REG_CNT 0x100
#define GROUP_BYTES 4
#define ROW_BYTES 16
@@ -67,7 +67,8 @@
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct mdss_debug_base *dbg = file->private_data;
- u32 off, cnt;
+ u32 off = 0;
+ u32 cnt = DEFAULT_BASE_REG_CNT;
char buf[24];
if (!dbg)
@@ -81,14 +82,11 @@
buf[count] = 0; /* end of string */
- sscanf(buf, "%5x %d", &off, &cnt);
+ sscanf(buf, "%5x %x", &off, &cnt);
if (off > dbg->max_offset)
return -EINVAL;
- if (cnt <= 0)
- cnt = DEFAULT_BASE_REG_CNT;
-
if (cnt > (dbg->max_offset - off))
cnt = dbg->max_offset - off;
@@ -113,7 +111,7 @@
if (*ppos)
return 0; /* the end */
- len = snprintf(buf, sizeof(buf), "0x%08x %d\n", dbg->off, dbg->off);
+ len = snprintf(buf, sizeof(buf), "0x%08x %x\n", dbg->off, dbg->cnt);
if (len < 0)
return 0;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 94c0da2..66936e5 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -397,13 +397,133 @@
return ret;
} /* hdmi_tx_sysfs_wta_hpd */
+static ssize_t hdmi_tx_sysfs_wta_vendor_name(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret;
+ u8 *s = (u8 *) buf;
+ u8 *d = NULL;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ d = hdmi_ctrl->spd_vendor_name;
+ ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 8) ? 8 : ret;
+
+ memset(hdmi_ctrl->spd_vendor_name, 0, 8);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (u8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_rda_vendor_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", hdmi_ctrl->spd_vendor_name);
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+ return ret;
+} /* hdmi_tx_sysfs_rda_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_wta_product_description(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret;
+ u8 *s = (u8 *) buf;
+ u8 *d = NULL;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ d = hdmi_ctrl->spd_product_description;
+ ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 16) ? 16 : ret;
+
+ memset(hdmi_ctrl->spd_product_description, 0, 16);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (u8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_product_description */
+
+static ssize_t hdmi_tx_sysfs_rda_product_description(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ hdmi_ctrl->spd_product_description);
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+ return ret;
+} /* hdmi_tx_sysfs_rda_product_description */
+
static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
hdmi_tx_sysfs_wta_hpd);
+static DEVICE_ATTR(vendor_name, S_IRUGO | S_IWUSR,
+ hdmi_tx_sysfs_rda_vendor_name, hdmi_tx_sysfs_wta_vendor_name);
+static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
+ hdmi_tx_sysfs_rda_product_description,
+ hdmi_tx_sysfs_wta_product_description);
static struct attribute *hdmi_tx_fs_attrs[] = {
&dev_attr_connected.attr,
&dev_attr_hpd.attr,
+ &dev_attr_vendor_name.attr,
+ &dev_attr_product_description.attr,
NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 2745c96..8be64b2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -184,14 +184,15 @@
static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
{
struct mdss_hw *hw;
+ int rc = -ENODEV;
spin_lock(&mdss_lock);
hw = mdss_irq_handlers[hw_ndx];
- spin_unlock(&mdss_lock);
if (hw)
- return hw->irq_handler(irq, hw->ptr);
+ rc = hw->irq_handler(irq, hw->ptr);
+ spin_unlock(&mdss_lock);
- return -ENODEV;
+ return rc;
}
static irqreturn_t mdss_irq_handler(int irq, void *ptr)
@@ -204,8 +205,11 @@
mdata->irq_buzy = true;
- if (intr & MDSS_INTR_MDP)
+ if (intr & MDSS_INTR_MDP) {
+ spin_lock(&mdp_lock);
mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr);
+ spin_unlock(&mdp_lock);
+ }
if (intr & MDSS_INTR_DSI0)
mdss_irq_dispatch(MDSS_HW_DSI0, irq, ptr);
@@ -284,6 +288,7 @@
}
EXPORT_SYMBOL(mdss_disable_irq);
+/* called from interrupt context */
void mdss_disable_irq_nosync(struct mdss_hw *hw)
{
u32 ndx_bit;
@@ -296,7 +301,6 @@
pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx,
mdss_res->irq_ena, mdss_res->irq_mask);
- spin_lock(&mdss_lock);
if (!(mdss_res->irq_mask & ndx_bit)) {
pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n",
hw->hw_ndx, mdss_res->mdp_irq_mask,
@@ -309,7 +313,6 @@
disable_irq_nosync(mdss_res->irq);
}
}
- spin_unlock(&mdss_lock);
}
EXPORT_SYMBOL(mdss_disable_irq_nosync);
@@ -390,6 +393,21 @@
return 1 << (intr_type + intf_num);
}
+/* function assumes that mdp is clocked to access hw registers */
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+ u32 intr_type, u32 intf_num)
+{
+ unsigned long irq_flags;
+ u32 irq;
+
+ irq = mdss_mdp_irq_mask(intr_type, intf_num);
+
+ pr_debug("clearing mdp irq mask=%x\n", irq);
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
+ spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
{
u32 irq;
@@ -482,13 +500,13 @@
spin_unlock_irqrestore(&mdp_lock, irq_flags);
}
+/* called from interrupt context */
void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num)
{
u32 irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
- spin_lock(&mdp_lock);
if (!(mdss_res->mdp_irq_mask & irq)) {
pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
irq, mdss_res->mdp_irq_mask);
@@ -500,7 +518,6 @@
(mdss_res->mdp_hist_irq_mask == 0))
mdss_disable_irq_nosync(&mdss_mdp_hw);
}
- spin_unlock(&mdp_lock);
}
static inline struct clk *mdss_mdp_get_clk(u32 clk_idx)
@@ -593,6 +610,9 @@
}
mdata->clk_ena = enable;
+ if (enable)
+ pm_runtime_get_sync(&mdata->pdev->dev);
+
pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
mb();
@@ -604,6 +624,9 @@
if (mdata->vsync_ena)
mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);
+ if (!enable)
+ pm_runtime_put(&mdata->pdev->dev);
+
mutex_unlock(&mdp_clk_lock);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index df5e5d3..07b083a 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -330,6 +330,8 @@
irqreturn_t mdss_mdp_isr(int irq, void *ptr);
int mdss_iommu_attach(struct mdss_data_type *mdata);
int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata);
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+ u32 intr_type, u32 intf_num);
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num);
void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num);
int mdss_mdp_hist_irq_enable(u32 irq);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 8c57c8c..0426784 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -182,6 +182,9 @@
if (atomic_inc_return(&ctx->vsync_ref) == 1)
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+ else
+ mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
+ ctl->intf_num);
}
static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
@@ -197,6 +200,7 @@
{
struct mdss_mdp_video_ctx *ctx;
unsigned long flags;
+ int need_update;
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
if (!ctx) {
@@ -205,14 +209,18 @@
}
spin_lock_irqsave(&ctx->vsync_lock, flags);
- if (!ctx->vsync_handler && vsync_handler)
- video_vsync_irq_enable(ctl);
- else if (ctx->vsync_handler && !vsync_handler)
- video_vsync_irq_disable(ctl);
-
+ need_update = (!ctx->vsync_handler && vsync_handler) ||
+ (ctx->vsync_handler && !vsync_handler);
ctx->vsync_handler = vsync_handler;
spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+ if (need_update) {
+ if (vsync_handler)
+ video_vsync_irq_enable(ctl);
+ else
+ video_vsync_irq_disable(ctl);
+ }
+
return 0;
}
@@ -335,8 +343,8 @@
if (!ctx->wait_pending) {
ctx->wait_pending++;
- INIT_COMPLETION(ctx->vsync_comp);
video_vsync_irq_enable(ctl);
+ INIT_COMPLETION(ctx->vsync_comp);
} else {
WARN(1, "commit without wait! ctl=%d", ctl->num);
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 75fb7d6..2c0d5e0 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -524,7 +524,7 @@
struct mdss_data_type *mdata;
mdata = mdss_mdp_get_mdata();
- if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102)
+ if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102 && pipe->src_fmt->is_yuv)
filter_mode = MDSS_MDP_SCALE_FILTER_CA;
else
filter_mode = MDSS_MDP_SCALE_FILTER_BIL;
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 5c15d9a..f5d7947 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -800,9 +800,9 @@
if (resource_context.vidc_platform_data->enable_ion) {
if (res_trk_check_for_sec_session()) {
if (resource_context.res_mem_type != DDL_FW_MEM)
- flags |= ION_SECURE;
+ flags |= ION_FLAG_SECURE;
else if (res_trk_is_cp_enabled())
- flags |= ION_SECURE;
+ flags |= ION_FLAG_SECURE;
}
}
return flags;
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index ddcd354..de8b4cb 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -209,7 +209,8 @@
if (!new_transaction)
goto alloc_transaction;
write_lock(&journal->j_state_lock);
- if (!journal->j_running_transaction) {
+ if (!journal->j_running_transaction &&
+ !journal->j_barrier_count) {
jbd2_get_transaction(journal, new_transaction);
new_transaction = NULL;
}
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 6e50578..19face8 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -153,7 +153,7 @@
* DMX_EVENT_NEW_REC_CHUNK will be triggered.
* When new recorded data is received with size
* equal or larger than this value a new event
- * will be triggered. This is relevent when
+ * will be triggered. This is relevant when
* output is DMX_OUT_TS_TAP or DMX_OUT_TSDEMUX_TAP,
* size must be at least DMX_REC_BUFF_CHUNK_MIN_SIZE
* and smaller than buffer size.
@@ -210,7 +210,18 @@
DMX_EVENT_EOS = 0x00000040,
/* New Elementary Stream data is ready */
- DMX_EVENT_NEW_ES_DATA = 0x00000080
+ DMX_EVENT_NEW_ES_DATA = 0x00000080,
+
+ /* Data markers */
+ DMX_EVENT_MARKER = 0x00000100
+};
+
+enum dmx_oob_cmd {
+ /* End-of-stream, no more data from this filter */
+ DMX_OOB_CMD_EOS,
+
+ /* Data markers */
+ DMX_OOB_CMD_MARKER,
};
/* Flags passed in filter events */
@@ -360,6 +371,12 @@
__u32 ts_dropped_bytes;
};
+/* Marker details associated with DMX_EVENT_MARKER event */
+struct dmx_marker_event_info {
+ /* Marker id */
+ __u64 id;
+};
+
/*
* Filter's event returned through DMX_GET_EVENT.
* poll with POLLPRI would block until events are available.
@@ -373,6 +390,7 @@
struct dmx_rec_chunk_event_info recording_chunk;
struct dmx_pcr_event_info pcr;
struct dmx_es_data_event_info es_data;
+ struct dmx_marker_event_info marker;
} params;
};
@@ -406,6 +424,15 @@
#define DMX_BUFFER_LINEAR_GROUP_SUPPORT 0x10
};
+/* Out-of-band (OOB) command */
+struct dmx_oob_command {
+ enum dmx_oob_cmd type;
+
+ union {
+ struct dmx_marker_event_info marker;
+ } params;
+};
+
typedef struct dmx_caps {
__u32 caps;
@@ -641,6 +668,6 @@
#define DMX_SET_SECURE_MODE _IOW('o', 65, struct dmx_secure_mode)
#define DMX_SET_EVENTS_MASK _IOW('o', 66, struct dmx_events_mask)
#define DMX_GET_EVENTS_MASK _IOR('o', 67, struct dmx_events_mask)
-
+#define DMX_PUSH_OOB_COMMAND _IOW('o', 68, struct dmx_oob_command)
#endif /*_DVBDMX_H_*/
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 56616d7..f90f59e 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -55,6 +55,7 @@
unsigned reset_gpio;
unsigned panel_x;
unsigned panel_y;
+ const char *fw_image_name;
int (*gpio_config)(unsigned gpio, bool configure);
struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
};
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 7c54004..67b5e6c 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -33,14 +33,12 @@
* @ION_HEAP_TYPE_CP: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous. Used for content protection.
- * @ION_HEAP_TYPE_DMA: memory allocated via DMA API
* @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
- ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS,
@@ -49,7 +47,6 @@
#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
/**
* heap flags - the lower 16 bits are used by core ion, the upper 16
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
index f27ceca..df9569b 100644
--- a/include/linux/mfd/pm8xxx/batterydata-lib.h
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -91,6 +91,8 @@
* compensate for battery capacitance.
* @rbatt_capacitve_mohm: the resistance to be added to compensate for
* battery capacitance
+ * @flat_ocv_threshold_uv: the voltage where the battery's discharge curve
+ * starts flattening out.
*/
struct bms_battery_data {
@@ -103,6 +105,7 @@
int default_rbatt_mohm;
int delta_rbatt_mohm;
int rbatt_capacitive_mohm;
+ int flat_ocv_threshold_uv;
};
#if defined(CONFIG_PM8921_BMS) || \
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 05271ba..3b5742e 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -21,6 +21,8 @@
struct mmc_ios {
unsigned int clock; /* clock rate */
+ unsigned int old_rate; /* saved clock rate */
+ unsigned long clk_ts; /* time stamp of last updated clock */
unsigned short vdd;
/* vdd stores the bit number of the selected voltage range from below. */
diff --git a/include/linux/msm_audio_ion.h b/include/linux/msm_audio_ion.h
new file mode 100644
index 0000000..83e5dff
--- /dev/null
+++ b/include/linux/msm_audio_ion.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _LINUX_MSM_AUDIO_ION_H
+#define _LINUX_MSM_AUDIO_ION_H
+
+#include <linux/msm_ion.h>
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+ struct ion_handle **handle, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
+
+
+bool msm_audio_ion_is_smmu_available(void);
+
+#ifdef CONFIG_SND_SOC_QDSP6V2
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name);
+void msm_audio_ion_client_destroy(struct ion_client *client);
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle);
+#else
+static struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name)
+{ return NULL; }
+static void msm_audio_ion_client_destroy(struct ion_client *client)
+{}
+static int msm_audio_ion_import_legacy(const char *name,
+ struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{ return 0; }
+static int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle)
+{ return 0; }
+
+#endif /* CONFIG_MSM_QDSP6V2_CODECS */
+#endif /* _LINUX_MSM_AUDIO_ION_H */
+
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 4fd77d2..3c3c7a9 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -6,6 +6,7 @@
enum msm_ion_heap_types {
ION_HEAP_TYPE_MSM_START = ION_HEAP_TYPE_CUSTOM + 1,
ION_HEAP_TYPE_IOMMU = ION_HEAP_TYPE_MSM_START,
+ ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CP,
ION_HEAP_TYPE_SECURE_DMA,
};
@@ -37,7 +38,7 @@
ION_MM_FIRMWARE_HEAP_ID = 29,
ION_SYSTEM_HEAP_ID = 30,
- ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */
+ ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
};
enum ion_fixed_position {
@@ -56,18 +57,25 @@
};
#define ION_HEAP_CP_MASK (1 << ION_HEAP_TYPE_CP)
+#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
/**
* Flag to use when allocating to indicate that a heap is secure.
*/
-#define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
+#define ION_FLAG_SECURE (1 << ION_HEAP_ID_RESERVED)
/**
* Flag for clients to force contiguous memort allocation
*
* Use of this flag is carefully monitored!
*/
-#define ION_FORCE_CONTIGUOUS (1 << 30)
+#define ION_FLAG_FORCE_CONTIGUOUS (1 << 30)
+
+/**
+* Deprecated! Please use the corresponding ION_FLAG_*
+*/
+#define ION_SECURE ION_FLAG_SECURE
+#define ION_FORCE_CONTIGUOUS ION_FLAG_FORCE_CONTIGUOUS
/**
* Macro should be used with ion_heap_ids defined above.
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 5837094..e40f301 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,5 +41,5 @@
int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
int msm_tsens_early_init(struct tsens_platform_data *pdata);
-
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
#endif /*MSM_TSENS_H */
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index d29d2fd..c399b81 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -6,7 +6,7 @@
#define MAX_ION_FD 4
#define MAX_APP_NAME_SIZE 32
-
+#define QSEECOM_HASH_SIZE 32
/*
* struct qseecom_register_listener_req -
* for register listener ioctl request
@@ -125,6 +125,19 @@
unsigned int resp_len; /* in/out */
};
+enum qseecom_key_management_usage_type {
+ QSEOS_KM_USAGE_DISK_ENCRYPTION = 0x01,
+};
+
+struct qseecom_create_key_req {
+ unsigned char hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_key_management_usage_type usage;
+};
+
+struct qseecom_wipe_key_req {
+ enum qseecom_key_management_usage_type usage;
+};
+
#define QSEECOM_IOC_MAGIC 0x97
@@ -176,5 +189,11 @@
#define QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ \
_IOWR(QSEECOM_IOC_MAGIC, 16, struct qseecom_send_svc_cmd_req)
+#define QSEECOM_IOCTL_CREATE_KEY_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 17, struct qseecom_create_key_req)
+
+#define QSEECOM_IOCTL_WIPE_KEY_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req)
+
#endif /* __QSEECOM_H_ */
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
index 538ad15..b6fc091 100644
--- a/include/linux/regulator/cpr-regulator.h
+++ b/include/linux/regulator/cpr-regulator.h
@@ -54,6 +54,21 @@
NUM_APC_PVS,
};
+/**
+ * enum vdd_mx_vmin_method - Method to determine vmin for vdd-mx
+ * %VDD_MX_VMIN_APC: Equal to APC voltage
+ * %VDD_MX_VMIN_APC_CORNER_CEILING: Equal to PVS corner ceiling voltage
+ * %VDD_MX_VMIN_APC_SLOW_CORNER_CEILING:
+ * Equal to slow speed corner ceiling
+ * %VDD_MX_VMIN_MX_VMAX: Equal to specified vdd-mx-vmax voltage
+ */
+enum vdd_mx_vmin_method {
+ VDD_MX_VMIN_APC,
+ VDD_MX_VMIN_APC_CORNER_CEILING,
+ VDD_MX_VMIN_APC_SLOW_CORNER_CEILING,
+ VDD_MX_VMIN_MX_VMAX,
+};
+
#ifdef CONFIG_MSM_CPR_REGULATOR
int __init cpr_regulator_init(void);
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index bf6847a..c8a20da 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -402,6 +402,7 @@
unsigned strobe;
unsigned data;
bool ignore_cal_pad_config;
+ bool phy_sof_workaround;
int strobe_pad_offset;
int data_pad_offset;
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 7f70a01..6fb1a65 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -109,6 +109,7 @@
struct msm_vfe_rdi_cfg rdi_cfg;
} d;
enum msm_vfe_input_src input_src;
+ uint32_t input_pix_clk;
};
struct msm_vfe_axi_plane_cfg {
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
index f0f015e..c9eb12a 100644
--- a/include/media/msmb_ispif.h
+++ b/include/media/msmb_ispif.h
@@ -20,6 +20,8 @@
RDI2,
INTF_MAX
};
+#define MAX_PARAM_ENTRIES (INTF_MAX * 2)
+
#define PIX0_MASK (1 << PIX0)
#define PIX1_MASK (1 << PIX1)
#define RDI0_MASK (1 << RDI0)
@@ -76,7 +78,7 @@
struct msm_ispif_param_data {
uint32_t num;
- struct msm_ispif_params_entry entries[INTF_MAX];
+ struct msm_ispif_params_entry entries[MAX_PARAM_ENTRIES];
};
struct msm_isp_info {
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 04e683f..fa4dedc 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -335,6 +335,7 @@
/* Payload an #ADM_CMD_GET_PP_PARAMS_V5 command.
*/
struct adm_cmd_get_pp_params_v5 {
+ struct apr_hdr hdr;
u32 data_payload_addr_lsw;
/* LSW of parameter data payload address.*/
@@ -2593,6 +2594,14 @@
} __packed;
+/* @brief Dolby Digital Plus end point configuration structure
+ */
+struct asm_dec_ddp_endp_param_v2 {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param encdec;
+ int endp_param_value;
+} __packed;
+
/* @brief Multichannel PCM encoder configuration structure used
* in the #ASM_STREAM_CMD_OPEN_READ_V2 command.
*/
@@ -6913,4 +6922,7 @@
struct afe_port_cmd_set_param_v2 param;
} __packed;
+/* Dolby DAP topology */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID 0x0001033B
+
#endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index b95fa3c..f5ab179 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -89,6 +89,8 @@
#define SND_AUDIOCODEC_PASS_THROUGH ((__u32) 0x00000015)
#define SND_AUDIOCODEC_MP2 ((__u32) 0x00000016)
#define SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH ((__u32) 0x00000017)
+#define SND_AUDIOCODEC_EAC3 ((__u32) 0x00000018)
+#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_EAC3
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
@@ -337,7 +339,12 @@
__u32 modelIdLength;
__u8 *modelId;
};
-
+struct snd_dec_ddp {
+ __u32 params_length;
+ __u8 *params;
+ __u32 params_id[18];
+ __u32 params_value[18];
+};
union snd_codec_options {
struct snd_enc_wma wma;
struct snd_enc_vorbis vorbis;
@@ -345,6 +352,7 @@
struct snd_enc_flac flac;
struct snd_enc_generic generic;
struct snd_dec_dts dts;
+ struct snd_dec_ddp ddp;
};
/** struct snd_codec_desc - description of codec capabilities
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 77a805c..4bea1e1 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,6 +32,12 @@
int adm_open(int port, int path, int rate, int mode, int topology,
bool perf_mode, uint16_t bits_per_sample);
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+ uint32_t params_length, char *params);
+
+int adm_dolby_dap_send_params(int port_id, char *params,
+ uint32_t params_length);
+
int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
int topology, bool perf_mode, uint16_t bits_per_sample);
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 9c86e1d..2a740f4 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -81,6 +81,8 @@
IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 39,
IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 40,
IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
+ IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
+ IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
IDX_GLOBAL_CFG,
AFE_MAX_PORTS
};
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0d0670e..0dd14e6 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -41,6 +41,8 @@
#define FORMAT_AMR_WB_PLUS 0x0010
#define FORMAT_MPEG4_MULTI_AAC 0x0011
#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
+#define FORMAT_AC3 0x0013
+#define FORMAT_EAC3 0x0014
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -295,6 +297,10 @@
int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
struct asm_amrwbplus_cfg *cfg);
+
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+ int param_id, int param_value);
+
/* PP specific */
int q6asm_equalizer(struct audio_client *ac, void *eq);
diff --git a/include/trace/events/mmc.h b/include/trace/events/mmc.h
new file mode 100644
index 0000000..37115c4
--- /dev/null
+++ b/include/trace/events/mmc.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mmc
+
+#if !defined(_TRACE_MMC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MMC_H
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(mmc_clk,
+ TP_PROTO(char *print_info),
+
+ TP_ARGS(print_info),
+
+ TP_STRUCT__entry(
+ __string(print_info, print_info)
+ ),
+
+ TP_fast_assign(
+ __assign_str(print_info, print_info);
+ ),
+
+ TP_printk("%s",
+ __get_str(print_info)
+ )
+);
+
+#endif /* if !defined(_TRACE_MMC_H) || defined(TRACE_HEADER_MULTI_READ) */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d6dd07a..69b9521 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1128,7 +1128,7 @@
#ifdef CONFIG_CMA
if (migratetype == MIGRATE_MOVABLE && !zone->cma_alloc)
page = __rmqueue_smallest(zone, order, MIGRATE_CMA);
- else
+ if (!page)
#endif
retry_reserve :
page = __rmqueue_smallest(zone, order, migratetype);
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 36d5d6b..866f524 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4850,8 +4850,10 @@
if (sitar) {
codec = sitar->codec;
- if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ if ((sitar->hphlocp_cnt < SITAR_OCP_ATTEMPT) &&
+ (!sitar->hphrocp_cnt)) {
pr_info("%s: retry\n", __func__);
+ sitar->hphlocp_cnt++;
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
0x00);
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4859,7 +4861,6 @@
} else {
wcd9xxx_disable_irq(codec->control_data,
WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
- sitar->hphlocp_cnt = 0;
sitar->hph_status |= SND_JACK_OC_HPHL;
if (sitar->mbhc_cfg.headset_jack)
sitar_snd_soc_jack_report(sitar,
@@ -4883,8 +4884,10 @@
if (sitar) {
codec = sitar->codec;
- if (sitar->hphrocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ if ((sitar->hphrocp_cnt < SITAR_OCP_ATTEMPT) &&
+ (!sitar->hphlocp_cnt)) {
pr_info("%s: retry\n", __func__);
+ sitar->hphrocp_cnt++;
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
0x00);
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4892,7 +4895,6 @@
} else {
wcd9xxx_disable_irq(codec->control_data,
WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
- sitar->hphrocp_cnt = 0;
sitar->hph_status |= SND_JACK_OC_HPHR;
if (sitar->mbhc_cfg.headset_jack)
sitar_snd_soc_jack_report(sitar,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 08167ca..8f63250 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -1074,6 +1074,21 @@
40, digital_gain),
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
taiko_put_anc_slot),
@@ -1388,7 +1403,7 @@
"ZERO", "EAR_HPH_L", "EAR_LINE_1",
};
-static const char * const iir1_inp1_text[] = {
+static const char * const iir_inp1_text[] = {
"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
};
@@ -1536,7 +1551,10 @@
SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
static const struct soc_enum iir1_inp1_mux_enum =
- SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
+
+static const struct soc_enum iir2_inp1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
static const struct snd_kcontrol_new rx_mix1_inp1_mux =
SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -1760,6 +1778,9 @@
static const struct snd_kcontrol_new iir1_inp1_mux =
SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+static const struct snd_kcontrol_new iir2_inp1_mux =
+ SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
+
static const struct snd_kcontrol_new anc1_mux =
SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
@@ -3372,6 +3393,7 @@
{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP1", "IIR2", "IIR2"},
{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3380,6 +3402,7 @@
{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "IIR2", "IIR2"},
{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
@@ -3395,6 +3418,7 @@
{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP1", "IIR2", "IIR2"},
{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3403,6 +3427,7 @@
{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "IIR2", "IIR2"},
{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3411,6 +3436,7 @@
{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "IIR2", "IIR2"},
{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3419,6 +3445,7 @@
{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "IIR2", "IIR2"},
{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3427,6 +3454,7 @@
{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP1", "IIR2", "IIR2"},
{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3435,6 +3463,7 @@
{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP2", "IIR2", "IIR2"},
{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3443,6 +3472,7 @@
{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP1", "IIR2", "IIR2"},
{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3451,6 +3481,7 @@
{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP2", "IIR2", "IIR2"},
{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3459,6 +3490,7 @@
{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP1", "IIR2", "IIR2"},
{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3467,6 +3499,7 @@
{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP2", "IIR2", "IIR2"},
{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3475,6 +3508,7 @@
{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX7 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP1", "IIR2", "IIR2"},
{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3489,6 +3523,13 @@
{"RX2 MIX2 INP2", "IIR1", "IIR1"},
{"RX7 MIX2 INP1", "IIR1", "IIR1"},
{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP2", "IIR2", "IIR2"},
+ {"RX1 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX1 MIX2 INP2", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP2", "IIR2", "IIR2"},
+ {"RX7 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX7 MIX2 INP2", "IIR2", "IIR2"},
/* Decimator Inputs */
{"DEC1 MUX", "DMIC1", "DMIC1"},
@@ -3561,6 +3602,18 @@
{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
+ {"IIR2", NULL, "IIR2 INP1 MUX"},
+ {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
+ {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
+ {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
+ {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
+ {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
+ {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
+ {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
+ {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
+
{"MIC BIAS1 Internal1", NULL, "LDO_H"},
{"MIC BIAS1 Internal2", NULL, "LDO_H"},
{"MIC BIAS1 External", NULL, "LDO_H"},
@@ -5114,6 +5167,9 @@
SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
+
/* AUX PGA */
SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 35a9646..66c475f 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -163,6 +163,16 @@
OCMEM gets exercised for low-power
audio and voice use cases.
+config DOLBY_DAP
+ bool "Enable Dolby DAP"
+ depends on SND_SOC_MSM8974
+ help
+ To add support for dolby DAP post processing.
+ This support is to configure the post processing parameters
+ to DSP. The configuration includes sending the end point
+ device, end point dependent post processing parameters and
+ the various posrt processing parameters
+
config SND_SOC_MSM8974
tristate "SoC Machine driver for MSM8974 boards"
depends on ARCH_MSM8974
@@ -173,6 +183,7 @@
select SND_SOC_MSM_HDMI_CODEC_RX
select SND_DYNAMIC_MINORS
select AUDIO_OCMEM
+ select DOLBY_DAP
help
To add support for SoC audio on MSM8974.
This will enable sound soc drivers which
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 734bd39..8db13f6 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -25,7 +25,7 @@
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
- 96000
+ 96000, 192000
};
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@@ -53,14 +53,14 @@
.playback = {
.stream_name = "Multimedia1 Playback",
.aif_name = "MM_DL1",
- .rates = (SNDRV_PCM_RATE_8000_96000|
+ .rates = (SNDRV_PCM_RATE_8000_192000|
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "Multimedia1 Capture",
@@ -80,14 +80,14 @@
.playback = {
.stream_name = "Multimedia2 Playback",
.aif_name = "MM_DL2",
- .rates = (SNDRV_PCM_RATE_8000_96000|
+ .rates = (SNDRV_PCM_RATE_8000_192000|
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "Multimedia2 Capture",
@@ -157,14 +157,14 @@
.playback = {
.stream_name = "MultiMedia3 Playback",
.aif_name = "MM_DL3",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 6,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia3",
@@ -173,14 +173,14 @@
.playback = {
.stream_name = "MultiMedia4 Playback",
.aif_name = "MM_DL4",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "MultiMedia4 Capture",
@@ -200,14 +200,14 @@
.playback = {
.stream_name = "MultiMedia5 Playback",
.aif_name = "MM_DL5",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "MultiMedia5 Capture",
@@ -227,14 +227,14 @@
.playback = {
.stream_name = "MultiMedia6 Playback",
.aif_name = "MM_DL6",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia6",
@@ -243,14 +243,14 @@
.playback = {
.stream_name = "MultiMedia7 Playback",
.aif_name = "MM_DL7",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia7",
@@ -259,14 +259,14 @@
.playback = {
.stream_name = "MultiMedia8 Playback",
.aif_name = "MM_DL8",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia8",
@@ -276,7 +276,7 @@
.playback = {
.stream_name = "SLIMBUS0 Hostless Playback",
.aif_name = "SLIM0_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
@@ -301,13 +301,13 @@
.playback = {
.stream_name = "SLIMBUS1 Hostless Playback",
.aif_name = "SLIM1_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS1 Hostless Capture",
@@ -326,13 +326,13 @@
.playback = {
.stream_name = "SLIMBUS3 Hostless Playback",
.aif_name = "SLIM3_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS3 Hostless Capture",
@@ -351,13 +351,13 @@
.playback = {
.stream_name = "SLIMBUS4 Hostless Playback",
.aif_name = "SLIM4_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS4 Hostless Capture",
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 2bd5c88..737317c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -63,6 +63,7 @@
static int clk_users;
static int msm8930_headset_gpios_configured;
+static struct mutex cdc_mclk_mutex;
static struct snd_soc_jack hs_jack;
static struct snd_soc_jack button_jack;
@@ -265,35 +266,42 @@
struct snd_soc_codec *codec, int enable,
bool dapm)
{
+ int r = 0;
pr_debug("%s: enable = %d\n", __func__, enable);
+
+ mutex_lock(&cdc_mclk_mutex);
if (enable) {
clk_users++;
pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users != 1)
- return 0;
-
- if (codec_clk) {
- clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
- clk_prepare_enable(codec_clk);
- sitar_mclk_enable(codec, 1, dapm);
- } else {
- pr_err("%s: Error setting Sitar MCLK\n", __func__);
- clk_users--;
- return -EINVAL;
+ if (clk_users == 1) {
+ if (codec_clk) {
+ clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
+ clk_prepare_enable(codec_clk);
+ sitar_mclk_enable(codec, 1, dapm);
+ } else {
+ pr_err("%s: Error setting Sitar MCLK\n",
+ __func__);
+ clk_users--;
+ r = -EINVAL;
+ }
}
} else {
- pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users == 0)
- return 0;
- clk_users--;
- if (!clk_users) {
- pr_debug("%s: disabling MCLK. clk_users = %d\n",
+ if (clk_users > 0) {
+ clk_users--;
+ pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+ if (clk_users == 0) {
+ pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
- sitar_mclk_enable(codec, 0, dapm);
- clk_disable_unprepare(codec_clk);
+ sitar_mclk_enable(codec, 0, dapm);
+ clk_disable_unprepare(codec_clk);
+ }
+ } else {
+ pr_err("%s: Error releasing Sitar MCLK\n", __func__);
+ r = -EINVAL;
}
}
- return 0;
+ mutex_unlock(&cdc_mclk_mutex);
+ return r;
}
static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
@@ -1378,6 +1386,7 @@
msm8930_headset_gpios_configured = 1;
atomic_set(&auxpcm_rsc_ref, 0);
+ mutex_init(&cdc_mclk_mutex);
return ret;
}
@@ -1392,6 +1401,7 @@
msm8930_free_headset_mic_gpios();
platform_device_unregister(msm8930_snd_device);
kfree(mbhc_cfg.calibration);
+ mutex_destroy(&cdc_mclk_mutex);
}
module_exit(msm8930_audio_exit);
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 30e9629..9ff968f 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -48,6 +48,7 @@
#define SAMPLING_RATE_48KHZ 48000
#define SAMPLING_RATE_96KHZ 96000
+#define SAMPLING_RATE_192KHZ 192000
static int msm8974_auxpcm_rate = 8000;
#define LO_1_SPK_AMP 0x1
@@ -137,19 +138,28 @@
u32 mclk_freq;
int us_euro_gpio;
struct msm_auxpcm_ctrl *pri_auxpcm_ctrl;
+ struct msm_auxpcm_ctrl *sec_auxpcm_ctrl;
};
#define GPIO_NAME_INDEX 0
#define DT_PARSE_INDEX 1
-static char *msm_auxpcm_gpio_name[][2] = {
- {"PRIM_AUXPCM_CLK", "prim-auxpcm-gpio-clk"},
- {"PRIM_AUXPCM_SYNC", "prim-auxpcm-gpio-sync"},
- {"PRIM_AUXPCM_DIN", "prim-auxpcm-gpio-din"},
- {"PRIM_AUXPCM_DOUT", "prim-auxpcm-gpio-dout"},
+static char *msm_prim_auxpcm_gpio_name[][2] = {
+ {"PRIM_AUXPCM_CLK", "qcom,prim-auxpcm-gpio-clk"},
+ {"PRIM_AUXPCM_SYNC", "qcom,prim-auxpcm-gpio-sync"},
+ {"PRIM_AUXPCM_DIN", "qcom,prim-auxpcm-gpio-din"},
+ {"PRIM_AUXPCM_DOUT", "qcom,prim-auxpcm-gpio-dout"},
+};
+
+static char *msm_sec_auxpcm_gpio_name[][2] = {
+ {"SEC_AUXPCM_CLK", "qcom,sec-auxpcm-gpio-clk"},
+ {"SEC_AUXPCM_SYNC", "qcom,sec-auxpcm-gpio-sync"},
+ {"SEC_AUXPCM_DIN", "qcom,sec-auxpcm-gpio-din"},
+ {"SEC_AUXPCM_DOUT", "qcom,sec-auxpcm-gpio-dout"},
};
void *lpaif_pri_muxsel_virt_addr;
+void *lpaif_sec_muxsel_virt_addr;
struct msm8974_liquid_dock_dev {
int dock_plug_gpio;
@@ -187,7 +197,8 @@
static struct mutex cdc_mclk_mutex;
static struct q_clkdiv *codec_clk;
static int clk_users;
-static atomic_t auxpcm_rsc_ref;
+static atomic_t prim_auxpcm_rsc_ref;
+static atomic_t sec_auxpcm_rsc_ref;
static int msm8974_liquid_ext_spk_power_amp_init(void)
@@ -577,13 +588,8 @@
static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
"Six", "Seven", "Eight"};
static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE"};
-static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96"};
-
-static const struct soc_enum msm_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, spk_function),
- SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
- SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
-};
+static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+ "KHZ_192"};
static const char *const btsco_rate_text[] = {"8000", "16000"};
static const struct soc_enum msm_btsco_enum[] = {
@@ -596,6 +602,10 @@
int sample_rate_val = 0;
switch (slim0_rx_sample_rate) {
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 2;
+ break;
+
case SAMPLING_RATE_96KHZ:
sample_rate_val = 1;
break;
@@ -620,6 +630,9 @@
ucontrol->value.integer.value[0]);
switch (ucontrol->value.integer.value[0]) {
+ case 2:
+ slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
+ break;
case 1:
slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
break;
@@ -891,30 +904,13 @@
return 0;
}
-static int msm_aux_pcm_get_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_get_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
struct msm_auxpcm_gpio *pin_data = NULL;
int ret = 0;
int i;
int j;
- if (pdata == NULL) {
- pr_err("%s: pdata is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
-
- auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
-
- if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
- pr_err("%s: Ctrl pointers are NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
pin_data = auxpcm_ctrl->pin_data;
for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
ret = gpio_request(pin_data->gpio_no,
@@ -930,31 +926,17 @@
/* Release all GPIOs on failure */
for (j = i; j >= 0; j--)
gpio_free(pin_data->gpio_no);
- goto err;
+ return ret;
}
}
-
-err:
- return ret;
+ return 0;
}
-static int msm_aux_pcm_free_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_free_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
struct msm_auxpcm_gpio *pin_data = NULL;
- int ret = 0;
int i;
-
- if (pdata == NULL) {
- pr_err("%s: pdata is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
-
- auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+ int ret = 0;
if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
pr_err("%s: Ctrl pointers are NULL\n", __func__);
@@ -973,40 +955,115 @@
return ret;
}
-static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
+static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
int ret = 0;
- pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
- __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+ pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
- if (atomic_inc_return(&auxpcm_rsc_ref) == 1) {
+ auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+ if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+ pr_err("%s: Ctrl pointers are NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (atomic_inc_return(&prim_auxpcm_rsc_ref) == 1) {
if (lpaif_pri_muxsel_virt_addr != NULL)
iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
lpaif_pri_muxsel_virt_addr);
else
pr_err("%s lpaif_pri_muxsel_virt_addr is NULL\n",
__func__);
- ret = msm_aux_pcm_get_gpios(substream);
+ ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
}
if (ret < 0) {
pr_err("%s: Aux PCM GPIO request failed\n", __func__);
return -EINVAL;
}
+err:
return ret;
}
-static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
+static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
- pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
- __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
- if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
- msm_aux_pcm_free_gpios(substream);
+ pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+ if (atomic_dec_return(&prim_auxpcm_rsc_ref) == 0)
+ msm_aux_pcm_free_gpios(auxpcm_ctrl);
}
-static struct snd_soc_ops msm_auxpcm_be_ops = {
- .startup = msm_auxpcm_startup,
- .shutdown = msm_auxpcm_shutdown,
+static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
+ .startup = msm_prim_auxpcm_startup,
+ .shutdown = msm_prim_auxpcm_shutdown,
+};
+
+static int msm_sec_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+ if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+ pr_err("%s: Ctrl pointers are NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (atomic_inc_return(&sec_auxpcm_rsc_ref) == 1) {
+ if (lpaif_sec_muxsel_virt_addr != NULL)
+ iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
+ lpaif_sec_muxsel_virt_addr);
+ else
+ pr_err("%s lpaif_sec_muxsel_virt_addr is NULL\n",
+ __func__);
+ ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
+ }
+ if (ret < 0) {
+ pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+ return -EINVAL;
+ }
+err:
+ return ret;
+}
+
+static void msm_sec_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+
+ pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+ if (atomic_dec_return(&sec_auxpcm_rsc_ref) == 0)
+ msm_aux_pcm_free_gpios(auxpcm_ctrl);
+}
+
+static struct snd_soc_ops msm_sec_auxpcm_be_ops = {
+ .startup = msm_sec_auxpcm_startup,
+ .shutdown = msm_sec_auxpcm_shutdown,
};
static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -1092,7 +1149,7 @@
SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
- SOC_ENUM_SINGLE_EXT(2, slim0_rx_sample_rate_text),
+ SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1784,7 +1841,7 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- /* AUX PCM Backend DAI Links */
+ /* Primary AUX PCM Backend DAI Links */
{
.name = LPASS_BE_AUXPCM_RX,
.stream_name = "AUX PCM Playback",
@@ -1795,7 +1852,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
- .ops = &msm_auxpcm_be_ops,
+ .ops = &msm_pri_auxpcm_be_ops,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
/* this dainlink has playback support */
@@ -1810,9 +1867,39 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
- .ops = &msm_auxpcm_be_ops,
+ .ops = &msm_pri_auxpcm_be_ops,
.ignore_suspend = 1,
},
+ /* Secondary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_SEC_AUXPCM_RX,
+ .stream_name = "Sec AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6.4108",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+ .ops = &msm_sec_auxpcm_be_ops,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ },
+ {
+ .name = LPASS_BE_SEC_AUXPCM_TX,
+ .stream_name = "Sec AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6.4109",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+ .ops = &msm_sec_auxpcm_be_ops,
+ .ignore_suspend = 1,
+ },
+
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -2030,7 +2117,8 @@
};
static int msm8974_dtparse_auxpcm(struct platform_device *pdev,
- struct msm8974_asoc_mach_data **pdata)
+ struct msm_auxpcm_ctrl **auxpcm_ctrl,
+ char *msm_auxpcm_gpio_name[][2])
{
int ret = 0;
int i = 0;
@@ -2038,7 +2126,7 @@
struct msm_auxpcm_ctrl *ctrl;
unsigned int gpio_no[NUM_OF_AUXPCM_GPIOS];
enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
- int prim_cnt = 0;
+ int auxpcm_cnt = 0;
pin_data = devm_kzalloc(&pdev->dev, (ARRAY_SIZE(gpio_no) *
sizeof(struct msm_auxpcm_gpio)),
@@ -2056,13 +2144,13 @@
if (gpio_no[i] > 0) {
pin_data[i].gpio_name =
- msm_auxpcm_gpio_name[prim_cnt][GPIO_NAME_INDEX];
+ msm_auxpcm_gpio_name[auxpcm_cnt][GPIO_NAME_INDEX];
pin_data[i].gpio_no = gpio_no[i];
dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
"0x%x\n", __func__,
pin_data[i].gpio_name,
pin_data[i].gpio_no);
- prim_cnt++;
+ auxpcm_cnt++;
} else {
dev_err(&pdev->dev, "%s:Invalid AUXPCM GPIO[%s]= %x\n",
__func__,
@@ -2082,8 +2170,8 @@
}
ctrl->pin_data = pin_data;
- ctrl->cnt = prim_cnt;
- (*pdata)->pri_auxpcm_ctrl = ctrl;
+ ctrl->cnt = auxpcm_cnt;
+ *auxpcm_ctrl = ctrl;
return ret;
err:
@@ -2160,10 +2248,21 @@
return -ENOMEM;
}
- ret = msm8974_dtparse_auxpcm(pdev, &pdata);
+ /* Parse Primary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
+ msm_prim_auxpcm_gpio_name);
if (ret) {
dev_err(&pdev->dev,
- "%s: Auxpcm pin data parse failed\n", __func__);
+ "%s: Primary Auxpcm pin data parse failed\n", __func__);
+ goto err;
+ }
+
+ /* Parse Secondary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->sec_auxpcm_ctrl,
+ msm_sec_auxpcm_gpio_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Secondary Auxpcm pin data parse failed\n", __func__);
goto err;
}
@@ -2248,7 +2347,8 @@
ret);
mutex_init(&cdc_mclk_mutex);
- atomic_set(&auxpcm_rsc_ref, 0);
+ atomic_set(&prim_auxpcm_rsc_ref, 0);
+ atomic_set(&sec_auxpcm_rsc_ref, 0);
spdev = pdev;
ext_spk_amp_regulator = NULL;
msm8974_liquid_dock_dev = NULL;
@@ -2266,6 +2366,12 @@
ret = -EINVAL;
goto err;
}
+ lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4);
+ if (lpaif_sec_muxsel_virt_addr == NULL) {
+ pr_err("%s Sec muxsel virt addr is null\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
return 0;
err:
if (pdata->mclk_gpio > 0) {
@@ -2310,6 +2416,7 @@
}
iounmap(lpaif_pri_muxsel_virt_addr);
+ iounmap(lpaif_sec_muxsel_virt_addr);
snd_soc_unregister_card(card);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 391b3da..f3dcf95 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -5,6 +5,7 @@
msm-lsm-client.o
obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
msm-dai-stub-v2.o
+obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o \
rtac.o q6lsm.o
ocmem-audio-objs += audio_ocmem.o
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 16d6e81..96da2f1 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -18,6 +18,7 @@
#include <linux/uaccess.h>
#include <linux/msm_ion.h>
#include <linux/mm.h>
+#include <linux/msm_audio_ion.h>
#include "audio_acdb.h"
@@ -870,9 +871,7 @@
kfree(acdb_data.col_data[i]);
acdb_data.col_data[i] = NULL;
}
- ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
- ion_free(acdb_data.ion_client, acdb_data.ion_handle);
- ion_client_destroy(acdb_data.ion_client);
+ msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
mutex_unlock(&acdb_data.acdb_mutex);
}
return 0;
@@ -894,34 +893,16 @@
(uint32_t)acdb_data.col_data[i]);
}
- acdb_data.ion_client =
- msm_ion_client_create(UINT_MAX, "audio_acdb_client");
- if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
- pr_err("%s: Could not register ION client!!!\n", __func__);
+ result = msm_audio_ion_import("audio_acdb_client",
+ &acdb_data.ion_client,
+ &acdb_data.ion_handle,
+ atomic_read(&acdb_data.map_handle),
+ NULL, 0,
+ &paddr, (size_t *)&mem_len, &kvptr);
+ if (result) {
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
+ __func__, result);
result = PTR_ERR(acdb_data.ion_client);
- goto err;
- }
-
- acdb_data.ion_handle = ion_import_dma_buf(acdb_data.ion_client,
- atomic_read(&acdb_data.map_handle));
- if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
- pr_err("%s: Could not import map handle!!!\n", __func__);
- result = PTR_ERR(acdb_data.ion_handle);
- goto err_ion_client;
- }
-
- result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
- &paddr, (size_t *)&mem_len);
- if (result != 0) {
- pr_err("%s: Could not get phys addr!!!\n", __func__);
- goto err_ion_handle;
- }
-
- kvptr = ion_map_kernel(acdb_data.ion_client,
- acdb_data.ion_handle);
- if (IS_ERR_OR_NULL(kvptr)) {
- pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
- result = PTR_ERR(kvptr);
goto err_ion_handle;
}
kvaddr = (unsigned long)kvptr;
@@ -938,10 +919,8 @@
return result;
err_ion_handle:
- ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-err_ion_client:
- ion_client_destroy(acdb_data.ion_client);
-err:
+ msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+
atomic64_set(&acdb_data.mem_len, 0);
mutex_unlock(&acdb_data.acdb_mutex);
return result;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 5dc5f96..9359ed7 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -321,6 +321,23 @@
}
}
+static int msm_compr_send_ddp_cfg(struct audio_client *ac,
+ struct snd_dec_ddp *ddp)
+{
+ int i, rc;
+ pr_debug("%s\n", __func__);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
+ ddp->params_value[i]);
+ if (rc) {
+ pr_err("sending params_id: %d failed\n",
+ ddp->params_id[i]);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -358,6 +375,24 @@
if (ret < 0)
pr_err("%s: CMD Format block failed\n", __func__);
break;
+ case SND_AUDIOCODEC_AC3: {
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__);
+ ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+ if (ret < 0)
+ pr_err("%s: DDP CMD CFG failed\n", __func__);
+ break;
+ }
+ case SND_AUDIOCODEC_EAC3: {
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__);
+ ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+ if (ret < 0)
+ pr_err("%s: DDP CMD CFG failed\n", __func__);
+ break;
+ }
default:
return -EINVAL;
}
@@ -511,13 +546,15 @@
{
pr_debug("%s\n", __func__);
/* MP3 Block */
- compr->info.compr_cap.num_codecs = 2;
+ compr->info.compr_cap.num_codecs = 4;
compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
+ compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
+ compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
/* Add new codecs here */
}
@@ -897,7 +934,7 @@
}
return 0;
case SNDRV_COMPRESS_SET_PARAMS:
- pr_debug("SNDRV_COMPRESS_SET_PARAMS: ");
+ pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n");
if (copy_from_user(&compr->info.codec_param, (void *) arg,
sizeof(struct snd_compr_params))) {
rc = -EFAULT;
@@ -914,6 +951,68 @@
pr_debug("SND_AUDIOCODEC_AAC\n");
compr->codec = FORMAT_MPEG4_AAC;
break;
+ case SND_AUDIOCODEC_AC3: {
+ char params_value[18*2*sizeof(int)];
+ int *params_value_data = (int *)params_value;
+ /* 36 is the max param length for ddp */
+ int i;
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ int params_length = ddp->params_length*sizeof(int);
+ pr_debug("SND_AUDIOCODEC_AC3\n");
+ compr->codec = FORMAT_AC3;
+ if (copy_from_user(params_value, (void *)ddp->params,
+ params_length))
+ pr_err("%s: ERROR: copy ddp params value\n",
+ __func__);
+ pr_debug("params_length: %d\n", ddp->params_length);
+ for (i = 0; i < params_length; i++)
+ pr_debug("params_value[%d]: %x\n", i,
+ params_value_data[i]);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ ddp->params_id[i] = params_value_data[2*i];
+ ddp->params_value[i] = params_value_data[2*i+1];
+ }
+ if (atomic_read(&prtd->start)) {
+ rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+ ddp);
+ if (rc < 0)
+ pr_err("%s: DDP CMD CFG failed\n",
+ __func__);
+ }
+ break;
+ }
+ case SND_AUDIOCODEC_EAC3: {
+ char params_value[18*2*sizeof(int)];
+ int *params_value_data = (int *)params_value;
+ /* 36 is the max param length for ddp */
+ int i;
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ int params_length = ddp->params_length*sizeof(int);
+ pr_debug("SND_AUDIOCODEC_EAC3\n");
+ compr->codec = FORMAT_EAC3;
+ if (copy_from_user(params_value, (void *)ddp->params,
+ params_length))
+ pr_err("%s: ERROR: copy ddp params value\n",
+ __func__);
+ pr_debug("params_length: %d\n", ddp->params_length);
+ for (i = 0; i < ddp->params_length; i++)
+ pr_debug("params_value[%d]: %x\n", i,
+ params_value_data[i]);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ ddp->params_id[i] = params_value_data[2*i];
+ ddp->params_value[i] = params_value_data[2*i+1];
+ }
+ if (atomic_read(&prtd->start)) {
+ rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+ ddp);
+ if (rc < 0)
+ pr_err("%s: DDP CMD CFG failed\n",
+ __func__);
+ }
+ break;
+ }
default:
pr_debug("FORMAT_LINEAR_PCM\n");
compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 5b18311..8bb3eaf 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -155,6 +155,8 @@
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
struct afe_clk_cfg lpass_pcm_oe_clk;
struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
mutex_lock(&aux_pcm_mutex);
@@ -186,22 +188,32 @@
auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)dai->dev->platform_data;
lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
- rc = afe_close(PCM_RX); /* can block */
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX
+ || dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX
+ || dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+
+ rc = afe_close(rx_port); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
- rc = afe_close(PCM_TX);
+ rc = afe_close(tx_port);
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM TX port\n");
lpass_pcm_src_clk->clk_val1 = 0;
- afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
- afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+ afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
+ afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
sizeof(struct afe_clk_cfg));
lpass_pcm_oe_clk.clk_val1 = 0;
- afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+ afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
mutex_unlock(&aux_pcm_mutex);
}
@@ -215,6 +227,8 @@
unsigned long pcm_clk_rate;
struct afe_clk_cfg lpass_pcm_oe_clk;
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
auxpcm_pdata = dai->dev->platform_data;
lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
@@ -279,30 +293,39 @@
sizeof(struct afe_clk_cfg));
lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
- rc = afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+
+ rc = afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on RX pcm_src_clk failed\n",
__func__);
goto fail;
}
- rc = afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
+ rc = afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on TX pcm_src_clk failed\n",
__func__);
goto fail;
}
- rc = afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+ rc = afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
__func__);
goto fail;
}
- afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
-
- afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
+ afe_open(rx_port, &dai_data->port_config, dai_data->rate);
+ afe_open(tx_port, &dai_data->port_config, dai_data->rate);
fail:
mutex_unlock(&aux_pcm_mutex);
@@ -314,7 +337,7 @@
{
int rc = 0;
- pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
+ pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d\n",
__func__, dai->id, cmd, aux_pcm_count);
switch (cmd) {
@@ -359,7 +382,7 @@
} else
dev_set_drvdata(dai->dev, dai_data);
- pr_err("%s : probe done for dai->id %d\n", __func__, dai->id);
+ pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
return rc;
}
@@ -367,6 +390,8 @@
{
struct msm_dai_q6_dai_data *dai_data;
int rc;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
dai_data = dev_get_drvdata(dai->dev);
@@ -393,14 +418,22 @@
dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d.closing afe\n",
__func__, dai->id, aux_pcm_count);
- rc = afe_close(PCM_RX); /* can block */
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+ rc = afe_close(rx_port); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
- rc = afe_close(PCM_TX);
+ rc = afe_close(tx_port);
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
-
done:
kfree(dai_data);
snd_soc_unregister_dai(dai->dev);
@@ -941,12 +974,13 @@
static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_dai_q6_ops,
.probe = msm_dai_q6_dai_probe,
@@ -1084,10 +1118,12 @@
switch (id) {
case AFE_PORT_ID_PRIMARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_aux_pcm_rx_dai);
break;
case AFE_PORT_ID_PRIMARY_PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_aux_pcm_tx_dai);
break;
@@ -1828,8 +1864,8 @@
if (ch_cnt) {
dai_data->rx_dai.mi2s_dai_data.port_config.i2s.channel_mode =
- mi2s_pdata->rx_sd_lines;
- dai_data->rx_dai.pdata_mi2s_lines = mi2s_pdata->rx_sd_lines;
+ sd_line;
+ dai_data->rx_dai.pdata_mi2s_lines = sd_line;
dai_driver->playback.channels_min = 1;
dai_driver->playback.channels_max = ch_cnt << 1;
} else {
@@ -1846,8 +1882,8 @@
if (ch_cnt) {
dai_data->tx_dai.mi2s_dai_data.port_config.i2s.channel_mode =
- mi2s_pdata->tx_sd_lines;
- dai_data->tx_dai.pdata_mi2s_lines = mi2s_pdata->tx_sd_lines;
+ sd_line;
+ dai_data->tx_dai.pdata_mi2s_lines = sd_line;
dai_driver->capture.channels_min = 1;
dai_driver->capture.channels_max = ch_cnt << 1;
} else {
@@ -1873,25 +1909,26 @@
u32 rx_line = 0;
u32 mi2s_intf = 0;
struct msm_mi2s_pdata *mi2s_pdata;
- int rc = 0;
-
+ int rc;
+ struct snd_soc_dai_driver *mi2s_dai;
rc = of_property_read_u32(pdev->dev.of_node, q6_mi2s_dev_id,
&mi2s_intf);
if (rc) {
dev_err(&pdev->dev,
"%s: missing %x in dt node\n", __func__, mi2s_intf);
- return rc;
+ goto rtn;
}
dev_dbg(&pdev->dev, "dev name %s dev id %x\n", dev_name(&pdev->dev),
- mi2s_intf);
+ mi2s_intf);
if (mi2s_intf < MSM_PRIM_MI2S || mi2s_intf > MSM_QUAT_MI2S) {
dev_err(&pdev->dev,
"%s: Invalid MI2S ID %u from Device Tree\n",
__func__, mi2s_intf);
- return -ENXIO;
+ rc = -ENXIO;
+ goto rtn;
}
dev_set_name(&pdev->dev, "%s.%d", "msm-dai-q6-mi2s", mi2s_intf);
@@ -1909,7 +1946,7 @@
if (rc) {
dev_err(&pdev->dev, "%s: Rx line from DT file %s\n", __func__,
"qcom,msm-mi2s-rx-lines");
- goto rtn;
+ goto free_pdata;
}
rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-mi2s-tx-lines",
@@ -1917,36 +1954,53 @@
if (rc) {
dev_err(&pdev->dev, "%s: Tx line from DT file %s\n", __func__,
"qcom,msm-mi2s-tx-lines");
- goto rtn;
+ goto free_pdata;
}
dev_dbg(&pdev->dev, "dev name %s Rx line %x , Tx ine %x\n",
dev_name(&pdev->dev), rx_line, tx_line);
mi2s_pdata->rx_sd_lines = rx_line;
mi2s_pdata->tx_sd_lines = tx_line;
+
dai_data = kzalloc(sizeof(struct msm_dai_q6_mi2s_dai_data),
- GFP_KERNEL);
+ GFP_KERNEL);
if (!dai_data) {
dev_err(&pdev->dev, "fail to allocate dai data\n");
rc = -ENOMEM;
- goto rtn;
+ goto free_pdata;
} else
dev_set_drvdata(&pdev->dev, dai_data);
+
pdev->dev.platform_data = mi2s_pdata;
- rc = msm_dai_q6_mi2s_platform_data_validation(pdev,
- &msm_dai_q6_mi2s_dai);
+
+ mi2s_dai = kzalloc(sizeof(struct snd_soc_dai_driver), GFP_KERNEL);
+ if (!mi2s_dai) {
+ dev_err(&pdev->dev, "fail to allocate for mi2s_dai\n");
+ rc = -ENOMEM;
+ goto free_dai_data;
+ }
+
+ memcpy(mi2s_dai, &msm_dai_q6_mi2s_dai,
+ sizeof(struct snd_soc_dai_driver));
+ rc = msm_dai_q6_mi2s_platform_data_validation(pdev, mi2s_dai);
if (IS_ERR_VALUE(rc))
- goto err_pdata;
+ goto free_dai;
+
dai_data->rate_constraint.count = 1;
dai_data->bitwidth_constraint.count = 1;
- rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_mi2s_dai);
+ rc = snd_soc_register_dai(&pdev->dev, mi2s_dai);
if (IS_ERR_VALUE(rc))
- goto err_pdata;
+ goto err_register;
return 0;
-err_pdata:
+
+err_register:
dev_err(&pdev->dev, "fail to msm_dai_q6_mi2s_dev_probe\n");
+free_dai:
+ kfree(mi2s_dai);
+free_dai_data:
kfree(dai_data);
-rtn:
+free_pdata:
kfree(mi2s_pdata);
+rtn:
return rc;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
new file mode 100644
index 0000000..b43c3bd
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -0,0 +1,707 @@
+/* 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/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/q6adm-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6afe-v2.h>
+
+#include "msm-dolby-dap-config.h"
+
+/* dolby endp based parameters */
+struct dolby_dap_endp_params_s {
+ int device;
+ int device_ch_caps;
+ int dap_device;
+ int params_id[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_len[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_offset[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_val[DOLBY_ENDDEP_PARAM_LENGTH];
+};
+
+const struct dolby_dap_endp_params_s
+ dolby_dap_endp_params[NUM_DOLBY_ENDP_DEVICE] = {
+ {EARPIECE, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {SPEAKER, 2, DOLBY_ENDP_INT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {WIRED_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {WIRED_HEADPHONE, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO_HEADSET, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO_CARKIT, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP_HEADPHONES, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP_SPEAKER, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {AUX_DIGITAL, 2, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {AUX_DIGITAL, 6, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {AUX_DIGITAL, 8, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {ANLG_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {DGTL_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {USB_ACCESSORY, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {USB_DEVICE, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {REMOTE_SUBMIX, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {ANC_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {ANC_HEADPHONE, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {PROXY, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {FM, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {FM_TX, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+};
+
+/* dolby param ids to/from dsp */
+static uint32_t dolby_dap_params_id[ALL_DOLBY_PARAMS] = {
+ DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
+ DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
+ DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
+ DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
+ DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
+ DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
+ DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
+ DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB, DOLBY_PARAM_ID_PLMD,
+ DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
+ DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
+ DOLBY_PARAM_ID_IEA, DOLBY_PARAM_ID_DEA, DOLBY_PARAM_ID_DED,
+ DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
+ DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
+ DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
+ DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
+ DOLBY_PARAM_ID_VEN, DOLBY_PARAM_ID_PSTG, DOLBY_COMMIT_ALL_TO_DSP,
+ DOLBY_COMMIT_TO_DSP, DOLBY_USE_CACHE, DOLBY_AUTO_ENDP,
+ DOLBY_AUTO_ENDDEP_PARAMS
+};
+
+/* modifed state: 0x00000000 - Not updated
+* > 0x00000000 && < 0x00010000
+* Updated and not commited to DSP
+* 0x00010001 - Updated and commited to DSP
+* > 0x00010001 - Modified the commited value
+*/
+static int dolby_dap_params_modified[MAX_DOLBY_PARAMS] = { 0 };
+/* param offset */
+static uint32_t dolby_dap_params_offset[MAX_DOLBY_PARAMS] = {
+ DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
+ DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
+ DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
+ DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
+ DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
+ DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
+ DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
+ DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
+ DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
+ DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
+ DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
+ DOLBY_PARAM_PLB_OFFSET, DOLBY_PARAM_PLMD_OFFSET,
+ DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
+ DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
+ DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
+ DOLBY_PARAM_IEA_OFFSET, DOLBY_PARAM_DEA_OFFSET,
+ DOLBY_PARAM_DED_OFFSET, DOLBY_PARAM_GEBG_OFFSET,
+ DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
+ DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
+ DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
+ DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
+ DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
+ DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
+ DOLBY_PARAM_PSTG_OFFSET
+};
+/* param_length */
+static uint32_t dolby_dap_params_length[MAX_DOLBY_PARAMS] = {
+ DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
+ DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
+ DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
+ DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
+ DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
+ DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
+ DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
+ DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
+ DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
+ DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
+ DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
+ DOLBY_PARAM_PLB_LENGTH, DOLBY_PARAM_PLMD_LENGTH,
+ DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
+ DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
+ DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
+ DOLBY_PARAM_IEA_LENGTH, DOLBY_PARAM_DEA_LENGTH,
+ DOLBY_PARAM_DED_LENGTH, DOLBY_PARAM_GEBG_LENGTH,
+ DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
+ DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
+ DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
+ DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
+ DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
+ DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
+ DOLBY_PARAM_PSTG_LENGTH
+};
+
+/* param_value */
+static uint32_t dolby_dap_params_value[TOTAL_LENGTH_DOLBY_PARAM] = {0};
+
+struct dolby_dap_params_get_s {
+ int32_t port_id;
+ uint32_t device_id;
+ uint32_t param_id;
+ uint32_t offset;
+ uint32_t length;
+};
+
+struct dolby_dap_params_states_s {
+ bool use_cache;
+ bool auto_endp;
+ bool enddep_params;
+ int port_id;
+ int port_open_count;
+ int port_ids_dolby_can_be_enabled;
+ int device;
+};
+
+static struct dolby_dap_params_get_s dolby_dap_params_get = {-1, DEVICE_OUT_ALL,
+ 0, 0, 0};
+static struct dolby_dap_params_states_s dolby_dap_params_states = { true, true,
+ true, DOLBY_INVALID_PORT_ID,
+ 0, DEVICE_OUT_ALL, 0 };
+/*
+port_ids_dolby_can_be_enabled is set to 0x7FFFFFFF.
+this needs to be removed after interface validation
+*/
+
+static int map_device_to_dolby_endpoint(int device)
+{
+ int i, dolby_dap_device = DOLBY_ENDP_INT_SPEAKERS;
+ for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
+ if (dolby_dap_endp_params[i].device == device) {
+ dolby_dap_device = dolby_dap_endp_params[i].dap_device;
+ break;
+ }
+ }
+ /* default the endpoint to speaker if corresponding device entry */
+ /* not found */
+ if (i >= NUM_DOLBY_ENDP_DEVICE)
+ dolby_dap_params_states.device = SPEAKER;
+ return dolby_dap_device;
+}
+
+static int dolby_dap_send_end_point(int port_id)
+{
+ int rc = 0;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = (DOLBY_PARAM_INT_ENDP_LENGTH +
+ DOLBY_PARAM_PAYLOAD_SIZE) * sizeof(uint32_t);
+
+ pr_debug("%s\n", __func__);
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ = DOLBY_PARAM_ID_INIT_ENDP;
+ *update_params_value++ = DOLBY_PARAM_INT_ENDP_LENGTH * sizeof(uint32_t);
+ *update_params_value++ =
+ map_device_to_dolby_endpoint(dolby_dap_params_states.device);
+ rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ rc = -EINVAL;
+ }
+ kfree(params_value);
+ return rc;
+}
+
+static int dolby_dap_send_enddep_params(int port_id, int device_channels)
+{
+ int i, j, rc = 0, idx, offset;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = (DOLBY_ENDDEP_PARAM_LENGTH +
+ DOLBY_NUM_ENDP_DEPENDENT_PARAMS *
+ DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+
+ pr_debug("%s\n", __func__);
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ for (idx = 0; idx < NUM_DOLBY_ENDP_DEVICE; idx++) {
+ if (dolby_dap_endp_params[idx].device ==
+ dolby_dap_params_states.device) {
+ if (dolby_dap_params_states.device == AUX_DIGITAL) {
+ if (dolby_dap_endp_params[idx].device_ch_caps ==
+ device_channels)
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+ if (idx >= NUM_DOLBY_ENDP_DEVICE) {
+ pr_err("%s: device is not set accordingly\n", __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < DOLBY_ENDDEP_PARAM_LENGTH; i++) {
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_id[i];
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_len[i] *
+ sizeof(uint32_t);
+ offset = dolby_dap_endp_params[idx].params_offset[i];
+ for (j = 0; j < dolby_dap_endp_params[idx].params_len[i]; j++)
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_val[offset+j];
+ }
+ rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ rc = -EINVAL;
+ }
+ kfree(params_value);
+ return rc;
+}
+
+static int dolby_dap_send_cached_params(int port_id, int commit)
+{
+ char *params_value;
+ int *update_params_value, rc = 0;
+ uint32_t index_offset, i, j;
+ uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
+ MAX_DOLBY_PARAMS * DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ params_length = 0;
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+ if ((dolby_dap_params_modified[i] == 0) ||
+ ((commit) &&
+ ((dolby_dap_params_modified[i] & 0x00010000) &&
+ ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))))
+ continue;
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ = dolby_dap_params_id[i];
+ *update_params_value++ = dolby_dap_params_length[i] *
+ sizeof(uint32_t);
+ index_offset = dolby_dap_params_offset[i];
+ for (j = 0; j < dolby_dap_params_length[i]; j++)
+ *update_params_value++ =
+ dolby_dap_params_value[index_offset+j];
+ params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
+ dolby_dap_params_length[i]) * sizeof(uint32_t);
+ }
+ pr_debug("%s, valid param length: %d", __func__, params_length);
+ if (params_length) {
+ rc = adm_dolby_dap_send_params(port_id, params_value,
+ params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+ if ((dolby_dap_params_modified[i] == 0) ||
+ ((commit) &&
+ ((dolby_dap_params_modified[i] & 0x00010000) &&
+ ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))
+ ))
+ continue;
+ dolby_dap_params_modified[i] = 0x00010001;
+ }
+ }
+ kfree(params_value);
+ return 0;
+}
+
+int dolby_dap_init(int port_id, int channels)
+{
+ int ret = 0;
+ if ((port_id != DOLBY_INVALID_PORT_ID) &&
+ (port_id &
+ dolby_dap_params_states.port_ids_dolby_can_be_enabled)) {
+ dolby_dap_params_states.port_id = port_id;
+ dolby_dap_params_states.port_open_count++;
+ if (dolby_dap_params_states.auto_endp) {
+ ret = dolby_dap_send_end_point(port_id);
+ if (ret) {
+ pr_err("%s: err sending endppoint\n", __func__);
+ return ret;
+ }
+ }
+ if (dolby_dap_params_states.use_cache) {
+ ret = dolby_dap_send_cached_params(port_id, 0);
+ if (ret) {
+ pr_err("%s: err sending cached params\n",
+ __func__);
+ return ret;
+ }
+ }
+ if (dolby_dap_params_states.enddep_params) {
+ dolby_dap_send_enddep_params(port_id,
+ channels);
+ if (ret) {
+ pr_err("%s: err sending endp dependent params\n",
+ __func__);
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
+void dolby_dap_deinit(int port_id)
+{
+ dolby_dap_params_states.port_open_count--;
+ if ((dolby_dap_params_states.port_id == port_id) &&
+ (!dolby_dap_params_states.port_open_count))
+ dolby_dap_params_states.port_id = DOLBY_INVALID_PORT_ID;
+}
+
+static int map_device_to_port_id(int device)
+{
+ int port_id = SLIMBUS_0_RX;
+ device = DEVICE_OUT_ALL;
+ /*update the device when single stream to multiple device is handled*/
+ if (device == DEVICE_OUT_ALL) {
+ port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
+ INT_BT_SCO_RX | INT_FM_RX |
+ RT_PROXY_PORT_001_RX | PCM_RX |
+ MI2S_RX | SECONDARY_I2S_RX |
+ SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
+ AFE_PORT_ID_SECONDARY_MI2S_RX;
+ } else {
+ /* update port_id based on the device */
+ }
+ return port_id;
+}
+
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the parameters */
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int rc = 0;
+ uint32_t idx, j;
+ uint32_t device = ucontrol->value.integer.value[0];
+ uint32_t param_id = ucontrol->value.integer.value[1];
+ uint32_t offset = ucontrol->value.integer.value[2];
+ uint32_t length = ucontrol->value.integer.value[3];
+
+ int port_id = dolby_dap_params_states.port_id;
+
+ dolby_dap_params_states.port_ids_dolby_can_be_enabled =
+ map_device_to_port_id(device);
+ for (idx = 0; idx < ALL_DOLBY_PARAMS; idx++) {
+ /*paramid from user space*/
+ if (param_id == dolby_dap_params_id[idx])
+ break;
+ }
+ if (idx > ALL_DOLBY_PARAMS-1) {
+ pr_err("%s: invalid param id 0x%x to set\n", __func__,
+ param_id);
+ return -EINVAL;
+ }
+ switch (idx) {
+ case DOLBY_COMMIT_ALL_IDX: {
+ /* COMIIT ALL: Send all parameters to DSP */
+ pr_debug("%s: COMMIT_ALL recvd\n", __func__);
+ if (port_id != DOLBY_INVALID_PORT_ID)
+ rc = dolby_dap_send_cached_params(port_id, 0);
+ }
+ break;
+ case DOLBY_COMMIT_IDX: {
+ pr_debug("%s: COMMIT recvd\n", __func__);
+ /* COMMIT: Send only modified paramters to DSP */
+ if (port_id != DOLBY_INVALID_PORT_ID)
+ rc = dolby_dap_send_cached_params(port_id, 1);
+ }
+ break;
+ case DOLBY_USE_CACHE_IDX: {
+ pr_debug("%s: USE CACHE recvd val: %ld\n", __func__,
+ ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.use_cache =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ case DOLBY_AUTO_ENDP_IDX: {
+ pr_debug("%s: AUTO_ENDP recvd val: %ld\n", __func__,
+ ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.auto_endp =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ case DOLBY_AUTO_ENDDEP_IDX: {
+ pr_debug("%s: USE_ENDDEP_PARAMS recvd val: %ld\n",
+ __func__, ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.enddep_params =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ default: {
+ /* cache the parameters */
+ dolby_dap_params_modified[idx] += 1;
+ dolby_dap_params_length[idx] = length;
+ pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
+ __func__, device, param_id, offset, length);
+ for (j = 0; j < length; j++) {
+ dolby_dap_params_value[
+ dolby_dap_params_offset[idx] +
+ offset + j]
+ = ucontrol->value.integer.value[4+j];
+ pr_debug("value[%d]: %ld\n", j,
+ ucontrol->value.integer.value[4+j]);
+ }
+ }
+ }
+
+ return rc;
+}
+
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int rc = 0, i;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
+ sizeof(uint32_t);
+ uint32_t param_payload_len =
+ DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+ int port_id = dolby_dap_params_states.port_id;
+
+ if (port_id == DOLBY_INVALID_PORT_ID) {
+ pr_err("%s, port_id not set, returning error", __func__);
+ return -EINVAL;
+ }
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
+ rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VER,
+ params_length +
+ param_payload_len,
+ params_value);
+ } else {
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++)
+ if (dolby_dap_params_id[i] ==
+ dolby_dap_params_get.param_id)
+ break;
+ if (i > MAX_DOLBY_PARAMS-1) {
+ pr_err("%s: invalid param id to set", __func__);
+ rc = -EINVAL;
+ } else {
+ params_length = (dolby_dap_params_length[i] +
+ DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(
+ dolby_dap_params_get.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ dolby_dap_params_id[i],
+ params_length +
+ param_payload_len,
+ params_value);
+ }
+ }
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(params_value);
+ rc = -EINVAL;
+ }
+ update_params_value = (int *)params_value;
+ ucontrol->value.integer.value[0] = dolby_dap_params_get.device_id;
+ ucontrol->value.integer.value[1] = dolby_dap_params_get.param_id;
+ ucontrol->value.integer.value[2] = dolby_dap_params_get.offset;
+ ucontrol->value.integer.value[3] = dolby_dap_params_get.length;
+
+ pr_debug("%s: FROM DSP value[0] 0x%x value[1] %d value[2] 0x%x\n",
+ __func__, update_params_value[0],
+ update_params_value[1], update_params_value[2]);
+ for (i = 0; i < dolby_dap_params_get.length; i++) {
+ ucontrol->value.integer.value[DOLBY_PARAM_PAYLOAD_SIZE+i] =
+ update_params_value[i];
+ pr_debug("value[%d]:%d\n", i, update_params_value[i]);
+ }
+ pr_debug("%s: Returning param_id=0x%x offset=%d length=%d\n",
+ __func__, dolby_dap_params_get.param_id,
+ dolby_dap_params_get.offset,
+ dolby_dap_params_get.length);
+ kfree(params_value);
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ dolby_dap_params_get.device_id = ucontrol->value.integer.value[0];
+ dolby_dap_params_get.port_id =
+ (dolby_dap_params_get.device_id == DEVICE_OUT_ALL) ?
+ dolby_dap_params_states.port_id :
+ map_device_to_port_id(dolby_dap_params_get.device_id);
+ dolby_dap_params_get.param_id = ucontrol->value.integer.value[1];
+ dolby_dap_params_get.offset = ucontrol->value.integer.value[2];
+ dolby_dap_params_get.length = ucontrol->value.integer.value[3];
+ pr_debug("%s: param_id=0x%x offset=%d length=%d\n", __func__,
+ dolby_dap_params_get.param_id, dolby_dap_params_get.offset,
+ dolby_dap_params_get.length);
+ return 0;
+}
+
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ uint32_t length = dolby_dap_params_value[DOLBY_PARAM_VCNB_OFFSET];
+ char *visualizer_data;
+ int i, rc;
+ int *update_visualizer_data;
+ uint32_t offset, params_length =
+ (2*length + DOLBY_VIS_PARAM_HEADER_SIZE)*sizeof(uint32_t);
+ uint32_t param_payload_len =
+ DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+ int port_id = dolby_dap_params_states.port_id;
+ if (port_id == DOLBY_INVALID_PORT_ID) {
+ pr_err("%s, port_id not set, returning error", __func__);
+ ucontrol->value.integer.value[0] = 0;
+ return -EINVAL;
+ }
+ visualizer_data = kzalloc(params_length, GFP_KERNEL);
+ if (!visualizer_data) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ offset = 0;
+ params_length = length * sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VCBG,
+ params_length + param_payload_len,
+ visualizer_data + offset);
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(visualizer_data);
+ return -EINVAL;
+ }
+
+ offset = length * sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VCBE,
+ params_length + param_payload_len,
+ visualizer_data + offset);
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(visualizer_data);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = 2*length;
+ pr_debug("%s: visualizer data length %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ update_visualizer_data = (int *)visualizer_data;
+ for (i = 0; i < 2*length; i++) {
+ ucontrol->value.integer.value[1+i] = update_visualizer_data[i];
+ pr_debug("value[%d] %d\n", i, update_visualizer_data[i]);
+ }
+ kfree(visualizer_data);
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while getting the visualizer data */
+ return 0;
+}
+
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the endpoint */
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int device = ucontrol->value.integer.value[0];
+ dolby_dap_params_states.device = device;
+ return 0;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
new file mode 100644
index 0000000..58ea36d
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
@@ -0,0 +1,348 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 and
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MSM_DOLBY_DAP_CONFIG_H_
+#define _MSM_DOLBY_DAP_CONFIG_H_
+
+#ifdef CONFIG_DOLBY_DAP
+/* DOLBY DOLBY GUIDS */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID 0x0001033B
+#define DOLBY_BUNDLE_MODULE_ID 0x00010723
+#define DOLBY_VISUALIZER_MODULE_ID 0x0001072B
+
+#define DOLBY_PARAM_ID_VDHE 0x0001074D
+#define DOLBY_PARAM_ID_VSPE 0x00010750
+#define DOLBY_PARAM_ID_DSSF 0x00010753
+#define DOLBY_PARAM_ID_DVLI 0x0001073E
+#define DOLBY_PARAM_ID_DVLO 0x0001073F
+#define DOLBY_PARAM_ID_DVLE 0x0001073C
+#define DOLBY_PARAM_ID_DVMC 0x00010741
+#define DOLBY_PARAM_ID_DVME 0x00010740
+#define DOLBY_PARAM_ID_IENB 0x00010744
+#define DOLBY_PARAM_ID_IEBF 0x00010745
+#define DOLBY_PARAM_ID_IEON 0x00010743
+#define DOLBY_PARAM_ID_DEON 0x00010738
+#define DOLBY_PARAM_ID_NGON 0x00010736
+#define DOLBY_PARAM_ID_GEON 0x00010748
+#define DOLBY_PARAM_ID_GENB 0x00010749
+#define DOLBY_PARAM_ID_GEBF 0x0001074A
+#define DOLBY_PARAM_ID_AONB 0x0001075B
+#define DOLBY_PARAM_ID_AOBF 0x0001075C
+#define DOLBY_PARAM_ID_AOBG 0x0001075D
+#define DOLBY_PARAM_ID_AOON 0x00010759
+#define DOLBY_PARAM_ID_ARNB 0x0001075F
+#define DOLBY_PARAM_ID_ARBF 0x00010760
+#define DOLBY_PARAM_ID_PLB 0x00010768
+#define DOLBY_PARAM_ID_PLMD 0x00010767
+#define DOLBY_PARAM_ID_DHSB 0x0001074E
+#define DOLBY_PARAM_ID_DHRG 0x0001074F
+#define DOLBY_PARAM_ID_DSSB 0x00010751
+#define DOLBY_PARAM_ID_DSSA 0x00010752
+#define DOLBY_PARAM_ID_DVLA 0x0001073D
+#define DOLBY_PARAM_ID_IEBT 0x00010746
+#define DOLBY_PARAM_ID_IEA 0x0001076A
+#define DOLBY_PARAM_ID_DEA 0x00010739
+#define DOLBY_PARAM_ID_DED 0x0001073A
+#define DOLBY_PARAM_ID_GEBG 0x0001074B
+#define DOLBY_PARAM_ID_AOCC 0x0001075A
+#define DOLBY_PARAM_ID_ARBI 0x00010761
+#define DOLBY_PARAM_ID_ARBL 0x00010762
+#define DOLBY_PARAM_ID_ARBH 0x00010763
+#define DOLBY_PARAM_ID_AROD 0x00010764
+#define DOLBY_PARAM_ID_ARTP 0x00010765
+#define DOLBY_PARAM_ID_VMON 0x00010756
+#define DOLBY_PARAM_ID_VMB 0x00010757
+#define DOLBY_PARAM_ID_VCNB 0x00010733
+#define DOLBY_PARAM_ID_VCBF 0x00010734
+#define DOLBY_PARAM_ID_PREG 0x00010728
+#define DOLBY_PARAM_ID_VEN 0x00010732
+#define DOLBY_PARAM_ID_PSTG 0x00010729
+#define DOLBY_PARAM_ID_INIT_ENDP 0x00010727
+
+/* Not Used with Set Param kcontrol, only to query using Get Param */
+#define DOLBY_PARAM_ID_VER 0x00010726
+
+#define DOLBY_PARAM_ID_VCBG 0x00010730
+#define DOLBY_PARAM_ID_VCBE 0x00010731
+
+/* DOLBY DAP control params */
+#define DOLBY_COMMIT_ALL_TO_DSP 0x70000001
+#define DOLBY_COMMIT_TO_DSP 0x70000002
+#define DOLBY_USE_CACHE 0x70000003
+#define DOLBY_AUTO_ENDP 0x70000004
+#define DOLBY_AUTO_ENDDEP_PARAMS 0x70000005
+
+/* DOLBY DAP offsets start */
+#define DOLBY_PARAM_VDHE_LENGTH 1
+#define DOLBY_PARAM_VDHE_OFFSET 0
+#define DOLBY_PARAM_VSPE_LENGTH 1
+#define DOLBY_PARAM_VSPE_OFFSET (DOLBY_PARAM_VDHE_OFFSET + \
+ DOLBY_PARAM_VDHE_LENGTH)
+#define DOLBY_PARAM_DSSF_LENGTH 1
+#define DOLBY_PARAM_DSSF_OFFSET (DOLBY_PARAM_VSPE_OFFSET + \
+ DOLBY_PARAM_VSPE_LENGTH)
+#define DOLBY_PARAM_DVLI_LENGTH 1
+#define DOLBY_PARAM_DVLI_OFFSET (DOLBY_PARAM_DSSF_OFFSET + \
+ DOLBY_PARAM_DSSF_LENGTH)
+#define DOLBY_PARAM_DVLO_LENGTH 1
+#define DOLBY_PARAM_DVLO_OFFSET (DOLBY_PARAM_DVLI_OFFSET + \
+ DOLBY_PARAM_DVLI_LENGTH)
+#define DOLBY_PARAM_DVLE_LENGTH 1
+#define DOLBY_PARAM_DVLE_OFFSET (DOLBY_PARAM_DVLO_OFFSET + \
+ DOLBY_PARAM_DVLO_LENGTH)
+#define DOLBY_PARAM_DVMC_LENGTH 1
+#define DOLBY_PARAM_DVMC_OFFSET (DOLBY_PARAM_DVLE_OFFSET + \
+ DOLBY_PARAM_DVLE_LENGTH)
+#define DOLBY_PARAM_DVME_LENGTH 1
+#define DOLBY_PARAM_DVME_OFFSET (DOLBY_PARAM_DVMC_OFFSET + \
+ DOLBY_PARAM_DVMC_LENGTH)
+#define DOLBY_PARAM_IENB_LENGTH 1
+#define DOLBY_PARAM_IENB_OFFSET (DOLBY_PARAM_DVME_OFFSET + \
+ DOLBY_PARAM_DVME_LENGTH)
+#define DOLBY_PARAM_IEBF_LENGTH 40
+#define DOLBY_PARAM_IEBF_OFFSET (DOLBY_PARAM_IENB_OFFSET + \
+ DOLBY_PARAM_IENB_LENGTH)
+#define DOLBY_PARAM_IEON_LENGTH 1
+#define DOLBY_PARAM_IEON_OFFSET (DOLBY_PARAM_IEBF_OFFSET + \
+ DOLBY_PARAM_IEBF_LENGTH)
+#define DOLBY_PARAM_DEON_LENGTH 1
+#define DOLBY_PARAM_DEON_OFFSET (DOLBY_PARAM_IEON_OFFSET + \
+ DOLBY_PARAM_IEON_LENGTH)
+#define DOLBY_PARAM_NGON_LENGTH 1
+#define DOLBY_PARAM_NGON_OFFSET (DOLBY_PARAM_DEON_OFFSET + \
+ DOLBY_PARAM_DEON_LENGTH)
+#define DOLBY_PARAM_GEON_LENGTH 1
+#define DOLBY_PARAM_GEON_OFFSET (DOLBY_PARAM_NGON_OFFSET + \
+ DOLBY_PARAM_NGON_LENGTH)
+#define DOLBY_PARAM_GENB_LENGTH 1
+#define DOLBY_PARAM_GENB_OFFSET (DOLBY_PARAM_GEON_OFFSET + \
+ DOLBY_PARAM_GEON_LENGTH)
+#define DOLBY_PARAM_GEBF_LENGTH 40
+#define DOLBY_PARAM_GEBF_OFFSET (DOLBY_PARAM_GENB_OFFSET + \
+ DOLBY_PARAM_GENB_LENGTH)
+#define DOLBY_PARAM_AONB_LENGTH 1
+#define DOLBY_PARAM_AONB_OFFSET (DOLBY_PARAM_GEBF_OFFSET + \
+ DOLBY_PARAM_GEBF_LENGTH)
+#define DOLBY_PARAM_AOBF_LENGTH 40
+#define DOLBY_PARAM_AOBF_OFFSET (DOLBY_PARAM_AONB_OFFSET + \
+ DOLBY_PARAM_AONB_LENGTH)
+#define DOLBY_PARAM_AOBG_LENGTH 329
+#define DOLBY_PARAM_AOBG_OFFSET (DOLBY_PARAM_AOBF_OFFSET + \
+ DOLBY_PARAM_AOBF_LENGTH)
+#define DOLBY_PARAM_AOON_LENGTH 1
+#define DOLBY_PARAM_AOON_OFFSET (DOLBY_PARAM_AOBG_OFFSET + \
+ DOLBY_PARAM_AOBG_LENGTH)
+#define DOLBY_PARAM_ARNB_LENGTH 1
+#define DOLBY_PARAM_ARNB_OFFSET (DOLBY_PARAM_AOON_OFFSET + \
+ DOLBY_PARAM_AOON_LENGTH)
+#define DOLBY_PARAM_ARBF_LENGTH 40
+#define DOLBY_PARAM_ARBF_OFFSET (DOLBY_PARAM_ARNB_OFFSET + \
+ DOLBY_PARAM_ARNB_LENGTH)
+#define DOLBY_PARAM_PLB_LENGTH 1
+#define DOLBY_PARAM_PLB_OFFSET (DOLBY_PARAM_ARBF_OFFSET + \
+ DOLBY_PARAM_ARBF_LENGTH)
+#define DOLBY_PARAM_PLMD_LENGTH 1
+#define DOLBY_PARAM_PLMD_OFFSET (DOLBY_PARAM_PLB_OFFSET + \
+ DOLBY_PARAM_PLB_LENGTH)
+#define DOLBY_PARAM_DHSB_LENGTH 1
+#define DOLBY_PARAM_DHSB_OFFSET (DOLBY_PARAM_PLMD_OFFSET + \
+ DOLBY_PARAM_PLMD_LENGTH)
+#define DOLBY_PARAM_DHRG_LENGTH 1
+#define DOLBY_PARAM_DHRG_OFFSET (DOLBY_PARAM_DHSB_OFFSET + \
+ DOLBY_PARAM_DHSB_LENGTH)
+#define DOLBY_PARAM_DSSB_LENGTH 1
+#define DOLBY_PARAM_DSSB_OFFSET (DOLBY_PARAM_DHRG_OFFSET + \
+ DOLBY_PARAM_DHRG_LENGTH)
+#define DOLBY_PARAM_DSSA_LENGTH 1
+#define DOLBY_PARAM_DSSA_OFFSET (DOLBY_PARAM_DSSB_OFFSET + \
+ DOLBY_PARAM_DSSB_LENGTH)
+#define DOLBY_PARAM_DVLA_LENGTH 1
+#define DOLBY_PARAM_DVLA_OFFSET (DOLBY_PARAM_DSSA_OFFSET + \
+ DOLBY_PARAM_DSSA_LENGTH)
+#define DOLBY_PARAM_IEBT_LENGTH 40
+#define DOLBY_PARAM_IEBT_OFFSET (DOLBY_PARAM_DVLA_OFFSET + \
+ DOLBY_PARAM_DVLA_LENGTH)
+#define DOLBY_PARAM_IEA_LENGTH 1
+#define DOLBY_PARAM_IEA_OFFSET (DOLBY_PARAM_IEBT_OFFSET + \
+ DOLBY_PARAM_IEBT_LENGTH)
+#define DOLBY_PARAM_DEA_LENGTH 1
+#define DOLBY_PARAM_DEA_OFFSET (DOLBY_PARAM_IEA_OFFSET + \
+ DOLBY_PARAM_IEA_LENGTH)
+#define DOLBY_PARAM_DED_LENGTH 1
+#define DOLBY_PARAM_DED_OFFSET (DOLBY_PARAM_DEA_OFFSET + \
+ DOLBY_PARAM_DEA_LENGTH)
+#define DOLBY_PARAM_GEBG_LENGTH 40
+#define DOLBY_PARAM_GEBG_OFFSET (DOLBY_PARAM_DED_OFFSET + \
+ DOLBY_PARAM_DED_LENGTH)
+#define DOLBY_PARAM_AOCC_LENGTH 1
+#define DOLBY_PARAM_AOCC_OFFSET (DOLBY_PARAM_GEBG_OFFSET + \
+ DOLBY_PARAM_GEBG_LENGTH)
+#define DOLBY_PARAM_ARBI_LENGTH 40
+#define DOLBY_PARAM_ARBI_OFFSET (DOLBY_PARAM_AOCC_OFFSET + \
+ DOLBY_PARAM_AOCC_LENGTH)
+#define DOLBY_PARAM_ARBL_LENGTH 40
+#define DOLBY_PARAM_ARBL_OFFSET (DOLBY_PARAM_ARBI_OFFSET + \
+ DOLBY_PARAM_ARBI_LENGTH)
+#define DOLBY_PARAM_ARBH_LENGTH 40
+#define DOLBY_PARAM_ARBH_OFFSET (DOLBY_PARAM_ARBL_OFFSET + \
+ DOLBY_PARAM_ARBL_LENGTH)
+#define DOLBY_PARAM_AROD_LENGTH 1
+#define DOLBY_PARAM_AROD_OFFSET (DOLBY_PARAM_ARBH_OFFSET + \
+ DOLBY_PARAM_ARBH_LENGTH)
+#define DOLBY_PARAM_ARTP_LENGTH 1
+#define DOLBY_PARAM_ARTP_OFFSET (DOLBY_PARAM_AROD_OFFSET + \
+ DOLBY_PARAM_AROD_LENGTH)
+#define DOLBY_PARAM_VMON_LENGTH 1
+#define DOLBY_PARAM_VMON_OFFSET (DOLBY_PARAM_ARTP_OFFSET + \
+ DOLBY_PARAM_ARTP_LENGTH)
+#define DOLBY_PARAM_VMB_LENGTH 1
+#define DOLBY_PARAM_VMB_OFFSET (DOLBY_PARAM_VMON_OFFSET + \
+ DOLBY_PARAM_VMON_LENGTH)
+#define DOLBY_PARAM_VCNB_LENGTH 1
+#define DOLBY_PARAM_VCNB_OFFSET (DOLBY_PARAM_VMB_OFFSET + \
+ DOLBY_PARAM_VMB_LENGTH)
+#define DOLBY_PARAM_VCBF_LENGTH 20
+#define DOLBY_PARAM_VCBF_OFFSET (DOLBY_PARAM_VCNB_OFFSET + \
+ DOLBY_PARAM_VCNB_LENGTH)
+#define DOLBY_PARAM_PREG_LENGTH 1
+#define DOLBY_PARAM_PREG_OFFSET (DOLBY_PARAM_VCBF_OFFSET + \
+ DOLBY_PARAM_VCBF_LENGTH)
+#define DOLBY_PARAM_VEN_LENGTH 1
+#define DOLBY_PARAM_VEN_OFFSET (DOLBY_PARAM_PREG_OFFSET + \
+ DOLBY_PARAM_PREG_LENGTH)
+#define DOLBY_PARAM_PSTG_LENGTH 1
+#define DOLBY_PARAM_PSTG_OFFSET (DOLBY_PARAM_VEN_OFFSET + \
+ DOLBY_PARAM_VEN_LENGTH)
+
+#define DOLBY_PARAM_INT_ENDP_LENGTH 1
+#define DOLBY_PARAM_PAYLOAD_SIZE 4
+#define DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM 329
+
+#define DOLBY_NUM_ENDP_DEPENDENT_PARAMS 1
+#define DOLBY_ENDDEP_PARAM_DVLO_OFFSET 0
+#define DOLBY_ENDDEP_PARAM_DVLO_LENGTH 1
+#define DOLBY_ENDDEP_PARAM_LENGTH DOLBY_ENDDEP_PARAM_DVLO_LENGTH
+
+#define MAX_DOLBY_PARAMS 47
+#define MAX_DOLBY_CTRL_PARAMS 5
+#define ALL_DOLBY_PARAMS (MAX_DOLBY_PARAMS + \
+ MAX_DOLBY_CTRL_PARAMS)
+#define DOLBY_COMMIT_ALL_IDX MAX_DOLBY_PARAMS
+#define DOLBY_COMMIT_IDX (MAX_DOLBY_PARAMS+1)
+#define DOLBY_USE_CACHE_IDX (MAX_DOLBY_PARAMS+2)
+#define DOLBY_AUTO_ENDP_IDX (MAX_DOLBY_PARAMS+3)
+#define DOLBY_AUTO_ENDDEP_IDX (MAX_DOLBY_PARAMS+4)
+
+#define TOTAL_LENGTH_DOLBY_PARAM 745
+#define NUM_DOLBY_ENDP_DEVICE 23
+#define DOLBY_VIS_PARAM_HEADER_SIZE 25
+
+#define DOLBY_INVALID_PORT_ID -1
+/* DOLBY device definitions */
+enum {
+ DOLBY_ENDP_INT_SPEAKERS = 0,
+ DOLBY_ENDP_EXT_SPEAKERS,
+ DOLBY_ENDP_HEADPHONES,
+ DOLBY_ENDP_HDMI,
+ DOLBY_ENDP_SPDIF,
+ DOLBY_ENDP_DLNA,
+ DOLBY_ENDP_ANALOG,
+};
+
+enum {
+ DEVICE_NONE = 0x0,
+ /* output devices */
+ EARPIECE = 0x1,
+ SPEAKER = 0x2,
+ WIRED_HEADSET = 0x4,
+ WIRED_HEADPHONE = 0x8,
+ BLUETOOTH_SCO = 0x10,
+ BLUETOOTH_SCO_HEADSET = 0x20,
+ BLUETOOTH_SCO_CARKIT = 0x40,
+ BLUETOOTH_A2DP = 0x80,
+ BLUETOOTH_A2DP_HEADPHONES = 0x100,
+ BLUETOOTH_A2DP_SPEAKER = 0x200,
+ AUX_DIGITAL = 0x400,
+ ANLG_DOCK_HEADSET = 0x800,
+ DGTL_DOCK_HEADSET = 0x1000,
+ USB_ACCESSORY = 0x2000,
+ USB_DEVICE = 0x4000,
+ REMOTE_SUBMIX = 0x8000,
+ ANC_HEADSET = 0x10000,
+ ANC_HEADPHONE = 0x20000,
+ PROXY = 0x40000,
+ FM = 0x80000,
+ FM_TX = 0x100000,
+ DEVICE_OUT_ALL = 0x7FFFFFFF,
+};
+/* DOLBY device definitions end */
+
+struct dolby_dap_params {
+ uint32_t value[TOTAL_LENGTH_DOLBY_PARAM + MAX_DOLBY_PARAMS];
+} __packed;
+int dolby_dap_init(int port_id, int channels);
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+void dolby_dap_deinit(int port_id);
+/* Dolby DOLBY end */
+#else
+int dolby_dap_init(int port_id, int channels) { return 0; }
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+void dolby_dap_deinit(int port_id) { return; }
+#endif
+
+#endif
+
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index ca91fe5..717e63b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -82,9 +82,9 @@
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
.channels_min = 1,
.channels_max = 8,
.buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
@@ -98,7 +98,7 @@
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
- 96000
+ 96000, 192000
};
static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index d8f2759..8257023 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -10,7 +10,6 @@
* GNU General Public License for more details.
*/
-
#include <linux/init.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -31,8 +30,10 @@
#include <sound/tlv.h>
#include <sound/asound.h>
#include <sound/pcm_params.h>
+#include <mach/qdsp6v2/q6core.h>
#include "msm-pcm-routing-v2.h"
+#include "msm-dolby-dap-config.h"
#include "q6voice.h"
struct msm_pcm_routing_bdai_data {
@@ -185,6 +186,20 @@
(void *)&msm_srs_trumedia_params[param_block_idx].srs_params.global);
}
+int get_topology(int path_type)
+{
+ int topology_id = 0;
+ if (path_type == ADM_PATH_PLAYBACK)
+ topology_id = get_adm_rx_topology();
+ else
+ topology_id = get_adm_tx_topology();
+
+ if (topology_id == 0)
+ topology_id = DEFAULT_COPP_TOPOLOGY;
+
+ return topology_id;
+}
+
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
{ PRIMARY_I2S_RX, 0, 0, 0, 0, 0},
@@ -225,6 +240,8 @@
{ AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0},
{ AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0},
{ AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
};
@@ -318,7 +335,7 @@
void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
int dspst_id, int stream_type)
{
- int i, session_type, path_type, port_type;
+ int i, session_type, path_type, port_type, port_id, topology;
struct route_payload payload;
u32 channels;
uint16_t bits_per_sample = 16;
@@ -346,6 +363,7 @@
/* re-enable EQ if active */
if (eq_data[fedai_id].enable)
msm_send_eq_values(fedai_id);
+ topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
msm_bedais[i].perf_mode = perf_mode;
@@ -361,27 +379,31 @@
else if (msm_bedais[i].format ==
SNDRV_PCM_FORMAT_S24_LE)
bits_per_sample = 24;
-
if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
(channels > 0))
adm_multi_ch_copp_open(msm_bedais[i].port_id,
path_type,
msm_bedais[i].sample_rate,
msm_bedais[i].channel,
- DEFAULT_COPP_TOPOLOGY, msm_bedais[i].perf_mode,
+ topology, msm_bedais[i].perf_mode,
bits_per_sample);
else
adm_open(msm_bedais[i].port_id,
path_type,
msm_bedais[i].sample_rate,
msm_bedais[i].channel,
- DEFAULT_COPP_TOPOLOGY, false,
+ topology, false,
bits_per_sample);
payload.copp_ids[payload.num_copps++] =
msm_bedais[i].port_id;
- srs_port_id = msm_bedais[i].port_id;
+ port_id = srs_port_id = msm_bedais[i].port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id,
+ msm_bedais[i].channel) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
}
if (payload.num_copps)
@@ -393,7 +415,7 @@
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
{
- int i, port_type, session_type;
+ int i, port_type, session_type, path_type, topology;
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* bad ID assigned in machine driver */
@@ -404,19 +426,24 @@
if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
port_type = MSM_AFE_PORT_TYPE_RX;
session_type = SESSION_TYPE_RX;
+ path_type = ADM_PATH_PLAYBACK;
} else {
port_type = MSM_AFE_PORT_TYPE_TX;
session_type = SESSION_TYPE_TX;
+ path_type = ADM_PATH_LIVE_REC;
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
if (!is_be_dai_extproc(i) &&
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
(msm_bedais[i].active) &&
- (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
adm_close(msm_bedais[i].port_id);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(msm_bedais[i].port_id);
+ }
}
fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
@@ -443,7 +470,7 @@
static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
{
- int session_type, path_type;
+ int session_type, path_type, port_id, topology;
u32 channels;
uint16_t bits_per_sample = 16;
@@ -465,7 +492,7 @@
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
if (set) {
if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
@@ -484,19 +511,23 @@
path_type,
msm_bedais[reg].sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY,
+ topology,
msm_bedais[reg].perf_mode,
bits_per_sample);
} else
adm_open(msm_bedais[reg].port_id,
path_type,
msm_bedais[reg].sample_rate, channels,
- DEFAULT_COPP_TOPOLOGY, false, bits_per_sample);
+ topology, false, bits_per_sample);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
- srs_port_id = msm_bedais[reg].port_id;
+ port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id, channels) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
} else {
if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
@@ -506,6 +537,8 @@
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
INVALID_SESSION) {
adm_close(msm_bedais[reg].port_id);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
}
@@ -1513,6 +1546,24 @@
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1532,6 +1583,9 @@
SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -1583,6 +1637,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
@@ -1723,6 +1780,24 @@
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
+ SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1781,6 +1856,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
@@ -1820,6 +1898,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("MI2S_TX_VoLTE", MSM_BACKEND_DAI_MI2S_TX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1844,6 +1925,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voip", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
@@ -1874,6 +1958,9 @@
SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
@@ -1888,6 +1975,15 @@
msm_routing_put_port_mixer),
};
+static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+};
+
static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2090,6 +2186,51 @@
}
};
+int msm_routing_get_dolby_security_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the manfr id*/
+ return 0;
+}
+
+int msm_routing_put_dolby_security_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int manufacturer_id = ucontrol->value.integer.value[0];
+ core_set_dolby_manufacturer_id(manufacturer_id);
+ return 0;
+}
+
+static const struct snd_kcontrol_new dolby_security_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 Security", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 1, msm_routing_get_dolby_security_control,
+ msm_routing_put_dolby_security_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_set_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Set Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_dolby_dap_param_to_set_control,
+ msm_routing_put_dolby_dap_param_to_set_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_get_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Get Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_dolby_dap_param_to_get_control,
+ msm_routing_put_dolby_dap_param_to_get_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_visualizer_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Get Visualizer", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 41, msm_routing_get_dolby_dap_param_visualizer_control,
+ msm_routing_put_dolby_dap_param_visualizer_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_end_point_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Endpoint", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 1, msm_routing_get_dolby_dap_endpoint_control,
+ msm_routing_put_dolby_dap_endpoint_control),
+};
+
static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -2425,6 +2566,10 @@
SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SEC_AUX_PCM_RX", "Sec AUX PCM Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SEC_AUX_PCM_TX", "Sec AUX PCM Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
@@ -2480,6 +2625,8 @@
mmul5_mixer_controls, ARRAY_SIZE(mmul5_mixer_controls)),
SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
/* incall */
SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
incall_music_delivery_mixer_controls,
@@ -2511,6 +2658,10 @@
SND_SOC_NOPM, 0, 0,
aux_pcm_rx_voice_mixer_controls,
ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX_Voice Mixer",
+ SND_SOC_NOPM, 0, 0,
+ sec_aux_pcm_rx_voice_mixer_controls,
+ ARRAY_SIZE(sec_aux_pcm_rx_voice_mixer_controls)),
SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
SND_SOC_NOPM, 0, 0,
hdmi_rx_voice_mixer_controls,
@@ -2551,6 +2702,9 @@
SND_SOC_DAPM_MIXER("AUXPCM_RX Port Mixer",
SND_SOC_NOPM, 0, 0, auxpcm_rx_port_mixer_controls,
ARRAY_SIZE(auxpcm_rx_port_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUXPCM_RX Port Mixer",
+ SND_SOC_NOPM, 0, 0, sec_auxpcm_rx_port_mixer_controls,
+ ARRAY_SIZE(sec_auxpcm_rx_port_mixer_controls)),
SND_SOC_DAPM_MIXER("SLIMBUS_1_RX Port Mixer", SND_SOC_NOPM, 0, 0,
sbus_1_rx_port_mixer_controls,
ARRAY_SIZE(sbus_1_rx_port_mixer_controls)),
@@ -2657,6 +2811,8 @@
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia5 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
+ {"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+ {"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -2700,6 +2856,13 @@
{"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
+
{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
@@ -2749,6 +2912,12 @@
{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
+
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
@@ -2770,6 +2939,7 @@
{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
+ {"Voice_Tx Mixer", "SEC_AUX_PCM_TX_Voice", "SEC_AUX_PCM_TX"},
{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
@@ -2785,6 +2955,7 @@
{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+ {"VoLTE_Tx Mixer", "SEC_AUX_PCM_TX_VoLTE", "SEC_AUX_PCM_TX"},
{"VoLTE_Tx Mixer", "MI2S_TX_VoLTE", "MI2S_TX"},
{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
@@ -2793,6 +2964,7 @@
{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
{"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
+ {"Voip_Tx Mixer", "SEC_AUX_PCM_TX_Voip", "SEC_AUX_PCM_TX"},
{"VOIP_UL", NULL, "Voip_Tx Mixer"},
{"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
@@ -2828,6 +3000,7 @@
{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+ {"SLIMBUS_0_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
@@ -2837,6 +3010,10 @@
{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+ {"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+ {"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
+
{"Voice Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
{"Voice Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -2892,6 +3069,7 @@
{"BE_OUT", NULL, "PCM_RX"},
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
+ {"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"MI2S_TX", NULL, "BE_IN"},
@@ -2911,6 +3089,8 @@
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
{"AUX_PCM_TX", NULL, "BE_IN"},
+ {"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
+ {"SEC_AUX_PCM_TX", NULL, "BE_IN"},
{"INCALL_RECORD_TX", NULL, "BE_IN"},
{"INCALL_RECORD_RX", NULL, "BE_IN"},
{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
@@ -2941,7 +3121,7 @@
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int be_id = rtd->dai_link->be_id;
- int i, session_type;
+ int i, session_type, path_type, topology;
struct msm_pcm_routing_bdai_data *bedai;
if (be_id >= MSM_BACKEND_DAI_MAX) {
@@ -2952,13 +3132,20 @@
bedai = &msm_bedais[be_id];
session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
0 : 1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ path_type = ADM_PATH_PLAYBACK;
+ else
+ path_type = ADM_PATH_LIVE_REC;
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
- if (fe_dai_map[i][session_type] != INVALID_SESSION)
+ if (fe_dai_map[i][session_type] != INVALID_SESSION) {
adm_close(bedai->port_id);
srs_port_id = -1;
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(bedai->port_id);
+ }
}
bedai->active = 0;
@@ -2974,7 +3161,7 @@
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int be_id = rtd->dai_link->be_id;
- int i, path_type, session_type;
+ int i, path_type, session_type, port_id, topology;
struct msm_pcm_routing_bdai_data *bedai;
u32 channels;
bool playback, capture;
@@ -2996,7 +3183,7 @@
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
if (bedai->active == 1)
goto done; /* Ignore prepare if back-end already active */
@@ -3021,21 +3208,25 @@
path_type,
bedai->sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY, bedai->perf_mode,
+ topology, bedai->perf_mode,
bits_per_sample);
} else if (capture) {
adm_open(bedai->port_id,
path_type,
bedai->sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY, false,
+ topology, false,
bits_per_sample);
}
msm_pcm_routing_build_matrix(i,
fe_dai_map[i][session_type], path_type);
- srs_port_id = bedai->port_id;
+ port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id, channels) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
}
@@ -3130,6 +3321,27 @@
snd_soc_add_platform_controls(platform,
aanc_slim_0_rx_mux,
ARRAY_SIZE(aanc_slim_0_rx_mux));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_security_controls,
+ ARRAY_SIZE(dolby_security_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_to_set_controls,
+ ARRAY_SIZE(dolby_dap_param_to_set_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_to_get_controls,
+ ARRAY_SIZE(dolby_dap_param_to_get_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_visualizer_controls,
+ ARRAY_SIZE(dolby_dap_param_visualizer_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_end_point_controls,
+ ARRAY_SIZE(dolby_dap_param_end_point_controls));
+
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 1c1029c..4a58369 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -26,6 +26,8 @@
#define LPASS_BE_AFE_PCM_TX "RT_PROXY_DAI_002_TX"
#define LPASS_BE_AUXPCM_RX "AUX_PCM_RX"
#define LPASS_BE_AUXPCM_TX "AUX_PCM_TX"
+#define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
+#define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
#define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
#define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
#define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
@@ -119,6 +121,8 @@
MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_BACKEND_DAI_AUDIO_I2S_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_BACKEND_DAI_MAX,
};
@@ -141,4 +145,7 @@
int compressed_set_volume(unsigned volume);
+uint32_t get_adm_rx_topology(void);
+
+uint32_t get_adm_tx_topology(void);
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b1db277..1bd3eac 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -33,6 +33,7 @@
#define RESET_COPP_ID 99
#define INVALID_COPP_ID 0xFF
+#define ADM_GET_PARAMETER_LENGTH 350
struct adm_ctl {
void *apr;
@@ -64,6 +65,8 @@
{0, 0, 0, 0, 0, 0, 0, 0}
};
+static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
{
struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
@@ -266,6 +269,134 @@
return ret;
}
+int adm_dolby_dap_send_params(int port_id, char *params, uint32_t params_length)
+{
+ struct adm_cmd_set_pp_params_v5 *adm_params = NULL;
+ int sz, rc = 0, index = afe_get_port_index(port_id);
+
+ pr_debug("%s\n", __func__);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %#x\n",
+ __func__, index, port_id);
+ return -EINVAL;
+ }
+ sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+ adm_params = kzalloc(sz, GFP_KERNEL);
+ if (!adm_params) {
+ pr_err("%s, adm params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+ params, params_length);
+ adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ adm_params->hdr.pkt_size = sz;
+ adm_params->hdr.src_svc = APR_SVC_ADM;
+ adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+ adm_params->hdr.src_port = port_id;
+ adm_params->hdr.dest_svc = APR_SVC_ADM;
+ adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+ adm_params->hdr.token = port_id;
+ adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
+ adm_params->payload_addr_lsw = 0;
+ adm_params->payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->payload_size = params_length;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+ if (rc < 0) {
+ pr_err("%s: Set params failed port = %#x\n",
+ __func__, port_id);
+ rc = -EINVAL;
+ goto dolby_dap_send_param_return;
+ }
+ /* Wait for the callback */
+ rc = wait_event_timeout(this_adm.wait[index],
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!rc) {
+ pr_err("%s: Set params timed out port = %#x\n",
+ __func__, port_id);
+ rc = -EINVAL;
+ goto dolby_dap_send_param_return;
+ }
+ rc = 0;
+dolby_dap_send_param_return:
+ kfree(adm_params);
+ return rc;
+}
+
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+ uint32_t params_length, char *params)
+{
+ struct adm_cmd_get_pp_params_v5 *adm_params = NULL;
+ int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
+ int *params_data = (int *)params;
+
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %#x\n",
+ __func__, index, port_id);
+ return -EINVAL;
+ }
+ sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+ adm_params = kzalloc(sz, GFP_KERNEL);
+ if (!adm_params) {
+ pr_err("%s, adm params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+ params, params_length);
+ adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ adm_params->hdr.pkt_size = sz;
+ adm_params->hdr.src_svc = APR_SVC_ADM;
+ adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+ adm_params->hdr.src_port = port_id;
+ adm_params->hdr.dest_svc = APR_SVC_ADM;
+ adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+ adm_params->hdr.token = port_id;
+ adm_params->hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
+ adm_params->data_payload_addr_lsw = 0;
+ adm_params->data_payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->module_id = module_id;
+ adm_params->param_id = param_id;
+ adm_params->param_max_size = params_length;
+ adm_params->reserved = 0;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+ if (rc < 0) {
+ pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+ port_id);
+ rc = -EINVAL;
+ goto dolby_dap_get_param_return;
+ }
+ /* Wait for the callback with copp id */
+ rc = wait_event_timeout(this_adm.wait[index],
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!rc) {
+ pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+ port_id);
+ rc = -EINVAL;
+ goto dolby_dap_get_param_return;
+ }
+ if (params_data) {
+ for (i = 0; i < adm_dolby_get_parameters[0]; i++)
+ params_data[i] = adm_dolby_get_parameters[1+i];
+ }
+ rc = 0;
+dolby_dap_get_param_return:
+ kfree(adm_params);
+ return rc;
+}
+
static void adm_callback_debug_print(struct apr_client_data *data)
{
uint32_t *payload;
@@ -428,6 +559,13 @@
__func__, payload[0]);
rtac_make_adm_callback(payload,
data->payload_size);
+ adm_dolby_get_parameters[0] = payload[3];
+ pr_debug("GET_PP PARAM:received parameter length: %x\n",
+ adm_dolby_get_parameters[0]);
+ for (i = 0; i < payload[3]; i++)
+ adm_dolby_get_parameters[1+i] = payload[4+i];
+ atomic_set(&this_adm.copp_stat[index], 1);
+ wake_up(&this_adm.wait[index]);
break;
case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
@@ -807,20 +945,10 @@
open.endpoint_id_1 = tmp_port;
open.endpoint_id_2 = 0xFFFF;
- /* convert path to acdb path */
- if (path == ADM_PATH_PLAYBACK)
- open.topology_id = get_adm_rx_topology();
- else {
- open.topology_id = get_adm_tx_topology();
- if ((open.topology_id ==
- VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
- (open.topology_id ==
- VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+ open.topology_id = topology;
+ if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- }
-
- if (open.topology_id == 0)
- open.topology_id = topology;
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index fed0d81..09d6a0f 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -17,7 +17,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
-#include <linux/msm_ion.h>
+#include <linux/msm_audio_ion.h>
#include <sound/apr_audio-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/q6audio-v2.h>
@@ -224,6 +224,7 @@
case AFE_PORT_ID_SECONDARY_MI2S_RX:
case AFE_PORT_ID_TERTIARY_MI2S_RX:
case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -247,6 +248,7 @@
case AFE_PORT_ID_SECONDARY_MI2S_TX:
case AFE_PORT_ID_TERTIARY_MI2S_TX:
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
ret = MSM_AFE_PORT_TYPE_TX;
break;
@@ -295,6 +297,8 @@
break;
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
default:
ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
break;
@@ -1120,7 +1124,9 @@
break;
case PCM_RX:
case PCM_TX:
- cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ cfg_type = AFE_PARAM_ID_PCM_CONFIG;
break;
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
@@ -1215,6 +1221,10 @@
case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
case PCM_RX: return IDX_PCM_RX;
case PCM_TX: return IDX_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
case MI2S_RX: return IDX_MI2S_RX;
@@ -1310,6 +1320,8 @@
break;
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
cfg_type = AFE_PARAM_ID_PCM_CONFIG;
break;
case SECONDARY_I2S_RX:
@@ -1707,35 +1719,13 @@
ac->port[dir].buf = buf;
- buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)buf[0].client)) {
- pr_err("%s: ION create client for AUDIO failed\n", __func__);
- goto fail;
- }
- buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[0].client, buf[0].handle,
- (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("audio_client", &buf[0].client,
+ &buf[0].handle, bufsz*bufcnt,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+ &buf[0].data);
if (rc) {
- pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto fail;
- }
-
- buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
- if (IS_ERR_OR_NULL((void *) buf[0].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
- goto fail;
- }
- memset((void *)buf[0].data, 0, (bufsz * bufcnt));
- if (!buf[0].data) {
- pr_err("%s:invalid vaddr, iomap failed\n", __func__);
mutex_unlock(&ac->cmd_lock);
goto fail;
}
@@ -1944,9 +1934,7 @@
cnt = port->max_buf_cnt - 1;
if (port->buf[0].data) {
- ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
- ion_free(port->buf[0].client, port->buf[0].handle);
- ion_client_destroy(port->buf[0].client);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -2521,6 +2509,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index f5b4bc1..c2b824f 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -29,6 +29,7 @@
#include <linux/debugfs.h>
#include <linux/time.h>
#include <linux/atomic.h>
+#include <linux/msm_audio_ion.h>
#include <asm/ioctls.h>
@@ -455,11 +456,8 @@
while (cnt >= 0) {
if (port->buf[cnt].data) {
- ion_unmap_kernel(port->buf[cnt].client,
- port->buf[cnt].handle);
- ion_free(port->buf[cnt].client,
- port->buf[cnt].handle);
- ion_client_destroy(port->buf[cnt].client);
+ msm_audio_ion_free(port->buf[cnt].client,
+ port->buf[cnt].handle);
port->buf[cnt].data = NULL;
port->buf[cnt].phys = 0;
--(port->max_buf_cnt);
@@ -496,9 +494,7 @@
}
if (port->buf[0].data) {
- ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
- ion_free(port->buf[0].client, port->buf[0].handle);
- ion_client_destroy(port->buf[0].client);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -723,44 +719,19 @@
while (cnt < bufcnt) {
if (bufsz > 0) {
if (!buf[cnt].data) {
- buf[cnt].client = msm_ion_client_create
- (UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].client)) {
- pr_err("%s: ION create client for AUDIO failed\n",
- __func__);
- goto fail;
- }
- buf[cnt].handle = ion_alloc
- (buf[cnt].client, bufsz, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[cnt].client,
- buf[cnt].handle,
- (ion_phys_addr_t *)
- &buf[cnt].phys,
- (size_t *)&len);
+ msm_audio_ion_alloc("audio_client",
+ &buf[cnt].client, &buf[cnt].handle,
+ bufsz,
+ (ion_phys_addr_t *)&buf[cnt].phys,
+ (size_t *)&len,
+ &buf[cnt].data);
if (rc) {
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
__func__, rc);
- goto fail;
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
}
- buf[cnt].data = ion_map_kernel
- (buf[cnt].client, buf[cnt].handle);
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n",
- __func__);
- goto fail;
- }
- memset((void *)buf[cnt].data, 0, bufsz);
buf[cnt].used = 1;
buf[cnt].size = bufsz;
buf[cnt].actual_size = bufsz;
@@ -823,35 +794,13 @@
ac->port[dir].buf = buf;
- buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)buf[0].client)) {
- pr_err("%s: ION create client for AUDIO failed\n", __func__);
- goto fail;
- }
- buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[0].client, buf[0].handle,
- (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("audio_client", &buf[0].client, &buf[0].handle,
+ bufsz*bufcnt,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+ &buf[0].data);
if (rc) {
- pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ pr_err("%s: Audio ION alloc is failed, rc = %d\n",
__func__, rc);
- goto fail;
- }
-
- buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
- if (IS_ERR_OR_NULL((void *) buf[0].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
- goto fail;
- }
- memset((void *)buf[0].data, 0, (bufsz * bufcnt));
- if (!buf[0].data) {
- pr_err("%s:invalid vaddr, iomap failed\n", __func__);
mutex_unlock(&ac->cmd_lock);
goto fail;
}
@@ -1569,6 +1518,12 @@
case FORMAT_MP3:
open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
break;
+ case FORMAT_AC3:
+ open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+ break;
+ case FORMAT_EAC3:
+ open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2570,6 +2525,40 @@
return -EINVAL;
}
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+ int param_id, int param_value)
+{
+ struct asm_dec_ddp_endp_param_v2 ddp_cfg;
+ int rc = 0;
+
+ pr_debug("%s: session[%d]param_id[%d]param_value[%d]", __func__,
+ ac->session, param_id, param_value);
+ q6asm_add_hdr(ac, &ddp_cfg.hdr, sizeof(ddp_cfg), TRUE);
+ ddp_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ ddp_cfg.encdec.param_id = param_id;
+ ddp_cfg.encdec.param_size = sizeof(struct asm_dec_ddp_endp_param_v2) -
+ (sizeof(struct apr_hdr) +
+ sizeof(struct asm_stream_cmd_set_encdec_param));
+ ddp_cfg.endp_param_value = param_value;
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &ddp_cfg);
+ if (rc < 0) {
+ pr_err("%s:Command opcode[0x%x] failed\n",
+ __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout opcode[0x%x]\n", __func__,
+ ddp_cfg.hdr.opcode);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
uint32_t bufsz, uint32_t bufcnt)
{
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index d3d335d..faf5f35 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -26,6 +26,10 @@
case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
case PCM_RX: return IDX_PCM_RX;
case PCM_TX: return IDX_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
case MI2S_RX: return IDX_MI2S_RX;
@@ -74,6 +78,10 @@
case PRIMARY_I2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX;
case PCM_RX: return AFE_PORT_ID_PRIMARY_PCM_RX;
case PCM_TX: return AFE_PORT_ID_PRIMARY_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return AFE_PORT_ID_SECONDARY_MI2S_RX;
case SECONDARY_I2S_TX: return AFE_PORT_ID_SECONDARY_MI2S_TX;
case MI2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX;
@@ -146,6 +154,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
@@ -171,6 +181,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 754a4fa..a417b26 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -16,6 +16,7 @@
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/mutex.h>
+#include <linux/msm_audio_ion.h>
#include <asm/mach-types.h>
#include <mach/qdsp6v2/rtac.h>
@@ -2532,14 +2533,8 @@
mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING;
mvm_set_voice_timing.timing.mode = 0;
mvm_set_voice_timing.timing.enc_offset = 8000;
- if ((machine_is_apq8064_sim()) || (machine_is_msm8974_sim())) {
- pr_debug("%s: Machine is MSM8974 sim\n", __func__);
- mvm_set_voice_timing.timing.dec_req_offset = 0;
- mvm_set_voice_timing.timing.dec_offset = 18000;
- } else {
- mvm_set_voice_timing.timing.dec_req_offset = 3300;
- mvm_set_voice_timing.timing.dec_offset = 8300;
- }
+ mvm_set_voice_timing.timing.dec_req_offset = 3300;
+ mvm_set_voice_timing.timing.dec_offset = 8300;
v->mvm_state = CMD_STATUS_FAIL;
@@ -4639,35 +4634,16 @@
pr_err("%s: v is NULL\n", __func__);
return -EINVAL;
}
- v->shmem_info.sh_buf.client = msm_ion_client_create(UINT_MAX,
- "voip_client");
- if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.client)) {
- pr_err("%s: ION create client failed\n", __func__);
- goto err;
- }
- v->shmem_info.sh_buf.handle = ion_alloc(v->shmem_info.sh_buf.client,
- bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.handle)) {
- pr_err("%s: ION memory allocation failed\n",
- __func__);
- goto err_ion_client;
- }
-
- rc = ion_phys(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle,
- (ion_phys_addr_t *)&phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
+ &(v->shmem_info.sh_buf.handle),
+ bufsz*bufcnt,
+ (ion_phys_addr_t *)&phys, (size_t *)&len,
+ &mem_addr);
if (rc) {
- pr_err("%s: ION Get Physical failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto err_ion_handle;
- }
-
- mem_addr = ion_map_kernel(v->shmem_info.sh_buf.client,
- v->shmem_info.sh_buf.handle);
- if (IS_ERR_OR_NULL(mem_addr)) {
- pr_err("%s: ION memory mapping failed\n", __func__);
- goto err_ion_handle;
+ return -EINVAL;
}
while (cnt < bufcnt) {
@@ -4691,13 +4667,6 @@
memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
return 0;
-
-err_ion_handle:
- ion_free(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle);
-err_ion_client:
- ion_client_destroy(v->shmem_info.sh_buf.client);
-err:
- return -EINVAL;
}
static int voice_alloc_oob_mem_table(void)
@@ -4711,41 +4680,19 @@
pr_err("%s: v is NULL\n", __func__);
return -EINVAL;
}
- v->shmem_info.memtbl.client = msm_ion_client_create(UINT_MAX,
- "voip_client");
- if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.client)) {
- pr_err("%s: ION create client for memtbl failed\n", __func__);
- goto err;
- }
- v->shmem_info.memtbl.handle = ion_alloc(v->shmem_info.memtbl.client,
- sizeof(struct vss_imemory_table_t), SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) v->shmem_info.memtbl.handle)) {
- pr_err("%s: ION memory allocation for memtbl failed\n",
- __func__);
- goto err_ion_client;
- }
-
- rc = ion_phys(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle,
- (ion_phys_addr_t *)&v->shmem_info.memtbl.phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
+ &(v->shmem_info.memtbl.handle),
+ sizeof(struct vss_imemory_table_t),
+ (ion_phys_addr_t *)&v->shmem_info.memtbl.phys,
+ (size_t *)&len,
+ &(v->shmem_info.memtbl.data));
if (rc) {
- pr_err("%s: ION Get Physical for memtbl failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto err_ion_handle;
+ return -EINVAL;
}
- v->shmem_info.memtbl.data = ion_map_kernel(v->shmem_info.memtbl.client,
- v->shmem_info.memtbl.handle);
- if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.data)) {
- pr_err("%s: ION memory mapping for memtbl failed\n",
- __func__);
- goto err_ion_handle;
- }
-
- memset(v->shmem_info.memtbl.data, 0,
- sizeof(struct vss_imemory_table_t));
-
v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
@@ -4755,12 +4702,6 @@
return 0;
-err_ion_handle:
- ion_free(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle);
-err_ion_client:
- ion_client_destroy(v->shmem_info.memtbl.client);
-err:
- return -EINVAL;
}
static int voice_alloc_cal_mem_map_table(void)
@@ -4768,67 +4709,25 @@
int ret = 0;
int len;
- common.cal_mem_map_table.client = msm_ion_client_create(UINT_MAX,
- "voc_client");
-
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.client)) {
- pr_err("%s: ION create client for cal mem map table failed\n",
- __func__);
-
- goto err;
- }
-
- common.cal_mem_map_table.handle =
- ion_alloc(common.cal_mem_map_table.client,
- sizeof(struct vss_imemory_table_t),
- SZ_4K, (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.handle)) {
- pr_err("%s: ION memory alloc for cal mem map table failed\n",
- __func__);
-
- goto err_ion_client;
- }
-
- ret = ion_phys(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle,
- (ion_phys_addr_t *) &common.cal_mem_map_table.phys,
- (size_t *) &len);
+ ret = msm_audio_ion_alloc("voip_client",
+ &(common.cal_mem_map_table.client),
+ &(common.cal_mem_map_table.handle),
+ sizeof(struct vss_imemory_table_t),
+ (ion_phys_addr_t *)&common.cal_mem_map_table.phys,
+ (size_t *) &len,
+ &(common.cal_mem_map_table.data));
if (ret) {
- pr_err("%s: Phy addr for cal mem map table failed %d\n",
- __func__, ret);
-
- goto err_ion_handle;
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
+ __func__, ret);
+ return -EINVAL;
}
- common.cal_mem_map_table.data =
- ion_map_kernel(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle);
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.data)) {
- pr_err("%s: Virtual addr for cal memory map table failed\n",
- __func__);
-
- goto err_ion_handle;
- }
-
- memset(common.cal_mem_map_table.data, 0,
- sizeof(struct vss_imemory_table_t));
-
common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
-
pr_debug("%s: data 0x%x phys 0x%x\n", __func__,
(unsigned int) common.cal_mem_map_table.data,
common.cal_mem_map_table.phys);
return 0;
-
-err_ion_handle:
- ion_free(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle);
-err_ion_client:
- ion_client_destroy(common.cal_mem_map_table.client);
- memset(&common.cal_mem_map_table, 0, sizeof(common.cal_mem_map_table));
-err:
- return -EINVAL;
}
static int __init voice_init(void)