Merge "ASoC: msm: Add voice volume boost support"
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 04310ec..b489f7a 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -13,21 +13,17 @@
Required properties:
- compatible: Must be "qcom,cpr-regulator"
- reg: Register addresses for RBCPR, RBCPR clock
- select, PVS eFuse and CPR eFuse
+ select, PVS and CPR eFuse address
- reg-names: Register names. Must be "rbcpr", "rbcpr_clk",
- "pvs_efuse" and "cpr_efuse"
+ "efuse_addr"
- regulator-name: A string used to describe the regulator
- interrupts: Interrupt line from RBCPR to interrupt controller.
- regulator-min-microvolt: Minimum corner value as min constraint, which
should be 1 for SVS corner
- regulator-max-microvolt: Maximum corner value as max constraint, which
should be 4 for SUPER_TURBO or 3 for TURBO
-- qcom,num-efuse-bits: The number of bits used in efuse memory to
- represent total number of PVS bins. It should
- not exceed a maximum of 5 for total number of
- 32 bins.
- qcom,pvs-bin-process: A list of integers whose length is equal to 2 to
- the power of qcom,num-efuse-bits. The location or
+ the power of qcom,pvs-fuse[num-of-bits]. The location or
0-based index of an element in the list corresponds
to the bin number. The value of each integer
corresponds to the PVS process speed of the APC
@@ -54,7 +50,7 @@
- qcom,cpr-timer-cons-down: Consecutive number of timer interval (qcom,cpr-timer-delay)
occurred before issuing DOWN interrupt.
- qcom,cpr-irq-line: Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
-- qcom,cpr-step-quotient: Number of CPR quotient (RO count) per vdd-apc-supply step
+- qcom,cpr-step-quotient: Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step
to issue error_steps.
- qcom,cpr-up-threshold: The threshold for CPR to issue interrupt when
error_steps is greater than it when stepping up.
@@ -64,6 +60,62 @@
- qcom,cpr-gcnt-time: The time for gate count in microseconds.
- qcom,cpr-apc-volt-step: The voltage in microvolt per CPR step, such as 5000uV.
+- qcom,pvs-fuse-redun-sel: Array of 4 elements to indicate where to read the bits and what value to
+ compare with in order to decide if the redundant PVS fuse bits would be
+ used instead of the original bits. The 4 elements with index [0..3] are:
+ [0] => the fuse row number of the selector
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+ [3] => the value to indicate redundant selection
+ When the value of the fuse bits specified by first 3 elements equals to
+ the value in 4th element, redundant PVS fuse bits should be selected.
+ Otherwise, the original PVS bits should be selected.
+- qcom,pvs-fuse: Array of three elements to indicate the bits for PVS fuse. The array
+ should have index and value like this:
+ [0] => the PVS fuse row number
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+- qcom,pvs-fuse-redun: Array of three elements to indicate the bits for redundant PVS fuse.
+ The array should have index and value like this:
+ [0] => the redundant PVS fuse row number
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+
+- qcom,cpr-fuse-redun-sel: Array of 4 elements to indicate where to read the bits and what value to
+ compare with in order to decide if the redundant CPR fuse bits would be
+ used instead of the original bits. The 4 elements with index [0..3] are:
+ [0] => the fuse row number of the selector
+ [1] => LSB bit position of the bits
+ [2] => number of bits
+ [3] => the value to indicate redundant selection
+ When the value of the fuse bits specified by first 3 elements equals to
+ the value in 4th element, redundant CPR fuse bits should be selected.
+ Otherwise, the original CPR bits should be selected.
+- qcom,cpr-fuse-row: Row number of CPR fuse
+- qcom,cpr-fuse-bp-cpr-disable: Bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-bp-scheme: Bit position of the bit to indicate if it's a global/local scheme
+- qcom,cpr-fuse-target-quot: Array of bit positions in fuse for Target Quotient of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for SVS target quotient
+ [1] => bit position of the LSB bit for NOMINAL target quotient
+ [2] => bit position of the LSB bit for TURBO target quotient
+- qcom,cpr-fuse-ro-sel: Array of bit positions in fuse for RO select of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for SVS RO select bits
+ [1] => bit position of the LSB bit for NOMINAL RO select bits
+ [2] => bit position of the LSB bit for TURBO RO select bits
+- qcom,cpr-fuse-redun-row: Row number of the redundant CPR fuse
+- qcom,cpr-fuse-redun-target-quot: Array of bit positions in fuse for redundant Target Quotient of all corners.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for redundant SVS target quotient
+ [1] => bit position of the LSB bit for redundant NOMINAL target quotient
+ [2] => bit position of the LSB bit for redundant TURBO target quotient
+- qcom,cpr-fuse-redun-ro-sel: Array of bit positions in eFuse for redundant RO select.
+ It should have index and value like this:
+ [0] => bit position of the LSB bit for redundant SVS RO select bits
+ [1] => bit position of the LSB bit for redundant NOMINAL RO select bits
+ [2] => bit position of the LSB bit for redundant TURBO RO select bits
+
Optional properties:
- vdd-mx-supply: Regulator to supply memory power as dependency
@@ -78,6 +130,10 @@
2 => equal to slow speed corner ceiling
3 => equal to qcom,vdd-mx-vmax
This is required when vdd-mx-supply is present.
+- qcom,cpr-fuse-redun-bp-cpr-disable: Redundant bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-redun-bp-scheme: Redundant bit position of the bit to indicate if it's a global/local scheme
+ This property is required if cpr-fuse-redun-bp-cpr-disable
+ is present, and vise versa.
- qcom,cpr-enable: Present: CPR enabled by default.
Not Present: CPR disable by default.
@@ -86,13 +142,17 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xfc4b80b0 8>, <0xfc4bc450 16>;
- reg-names = "rbcpr", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
+
+ qcom,pvs-fuse = <22 6 5>;
+ qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+ qcom,pvs-fuse-redun = <22 27 5>;
+
qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
@@ -115,5 +175,15 @@
qcom,cpr-idle-clocks = <5>;
qcom,cpr-gcnt-time = <1>;
qcom,cpr-apc-volt-step = <5000>;
+
+ qcom,cpr-fuse-row = <138>;
+ qcom,cpr-fuse-bp-cpr-disable = <36>;
+ qcom,cpr-fuse-bp-scheme = <37>;
+ qcom,cpr-fuse-target-quot = <24 12 0>;
+ qcom,cpr-fuse-ro-sel = <54 38 41>;
+ qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+ qcom,cpr-fuse-redun-row = <139>;
+ qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
};
diff --git a/arch/arm/boot/dts/apq8084.dtsi b/arch/arm/boot/dts/apq8084.dtsi
index 7ac286a..350257c 100644
--- a/arch/arm/boot/dts/apq8084.dtsi
+++ b/arch/arm/boot/dts/apq8084.dtsi
@@ -245,7 +245,7 @@
memory_hole: qcom,msm-mem-hole {
compatible = "qcom,msm-mem-hole";
- qcom,memblock-remove = <0x0dc00000 0x2000000>; /* Address and Size of Hole */
+ qcom,memblock-remove = <0x0d200000 0x02c00000>; /* Address and Size of Hole */
};
qcom,ipc-spinlock@fd484000 {
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f57a7bd
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,124 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+ qcom,dsi_v2_truly_wvga_video {
+ compatible = "qcom,dsi-panel-v2";
+ label = "Truly WVGA command mode dsi panel";
+ qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+ qcom,rst-gpio = <&msmgpio 41 0>;
+ qcom,mode-selection-gpio = <&msmgpio 7 0>;
+ qcom,te-gpio = <&msmgpio 12 0>;
+ vdda-supply = <&pm8110_l19>;
+ vddio-supply=<&pm8110_l14>;
+ qcom,mdss-pan-res = <480 800>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-dest = "display_1";
+ qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-dsi-mode = <1>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <1>;
+ qcom,mdss-pan-dsi-dst-format = <8>;
+ qcom,mdss-pan-insert-dcs-cmd = <1>;
+ qcom,mdss-pan-wr-mem-continue = <0x3c>;
+ qcom,mdss-pan-wr-mem-start = <0x2c>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+ qcom,mdss-pan-dsi-dlane-swap = <0>;
+ qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x02>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+ qcom,panel-phy-timingSettings = [5D 12 0C 00 33 38
+ 10 16 1E 03 04 00];
+ qcom,panel-phy-strengthCtrl = [ff 06];
+ qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+ qcom,panel-phy-laneConfig =
+ [80 45 00 00 01 66 /*lane0**/
+ 80 45 00 00 01 66 /*lane1*/
+ 80 45 00 00 01 66 /*lane2*/
+ 80 45 00 00 01 66 /*lane3*/
+ 40 67 00 00 01 88]; /*Clk*/
+
+ qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,panel-on-cmds = [
+ 05 01 00 00 00 02
+ 01 00
+ 23 01 00 00 00 02
+ b0 04
+ 29 01 00 00 00 03
+ b3 02 00
+ 23 01 00 00 00 02
+ bd 00
+ 29 01 00 00 00 03
+ c0 18 66
+ 29 01 00 00 00 10
+ c1 23 31 99 21 20 00 30 28 0c 0c
+ 00 00 00 21 01
+ 29 01 00 00 00 07
+ c2 00 06 06 01 03 00
+ 29 01 00 00 00 19
+ c8 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 19
+ c9 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 19
+ ca 04 10 18 20 2e 46 3c 28 1f 18
+ 10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+ 29 01 00 00 00 11
+ d0 29 03 ce a6 00 43 20 10 01 00
+ 01 01 00 03 01 00
+ 29 01 00 00 00 08
+ d1 18 0C 23 03 75 02 50
+ 23 01 00 00 00 02
+ d3 11
+ 29 01 00 00 00 03
+ d5 2a 2a
+ 29 01 00 00 00 03
+ de 01 51
+ 23 01 00 00 00 02
+ e6 51
+ 23 01 00 00 00 02
+ fa 03
+ 23 01 00 00 64 02
+ d6 28
+ 15 01 00 00 00 02
+ 36 41
+ 39 01 00 00 00 05
+ 2a 00 00 01 df
+ 39 01 00 00 00 05
+ 2b 00 00 03 1f
+ 15 01 00 00 00 02
+ 35 00
+ 39 01 00 00 00 03
+ 44 00 50
+ 15 01 00 00 00 02
+ 3a 77
+ 05 01 00 00 7D 02
+ 11 00
+ 05 01 00 00 14 02
+ 29 00
+ ];
+ qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+ 05 01 00 00 78 02 10 00];
+ qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
index 5693ccd..8be8d71 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -69,7 +69,7 @@
c1 23 31 99 21 20 00 30 28 0c 0c
00 00 00 21 01
29 01 00 00 00 07
- c2 10 06 06 01 03 00
+ c2 00 06 06 01 03 00
29 01 00 00 00 19
c8 04 10 18 20 2e 46 3c 28 1f 18
10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
@@ -89,7 +89,7 @@
29 01 00 00 00 03
d5 2a 2a
29 01 00 00 00 03
- de 01 41
+ de 01 51
23 01 00 00 00 02
e6 51
23 01 00 00 00 02
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index e5683fb..1e379b2 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -227,6 +227,16 @@
status = "ok";
};
+&sdcc3 {
+ qcom,sup-voltages = <1800 1800>;
+ status = "disabled";
+};
+
+&sdhc_3 {
+ qcom,sup-voltages = <1800 1800>;
+ status = "disabled";
+};
+
&spmi_bus {
qcom,pm8226@0 {
qcom,leds@a100 {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index db0620f..e991552 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -180,7 +180,7 @@
&sdcc2 {
vdd-supply = <&pm8226_l18>;
qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <9000 800000>;
+ qcom,vdd-current-level = <9000 400000>;
vdd-io-supply = <&pm8226_l21>;
qcom,vdd-io-voltage-level = <1800000 2950000>;
@@ -196,7 +196,7 @@
qcom,xpc;
qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
- qcom,current-limit = <600>;
+ qcom,current-limit = <400>;
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -215,7 +215,7 @@
&sdhc_2 {
vdd-supply = <&pm8226_l18>;
qcom,vdd-voltage-level = <2950000 2950000>;
- qcom,vdd-current-level = <9000 800000>;
+ qcom,vdd-current-level = <9000 400000>;
vdd-io-supply = <&pm8226_l21>;
qcom,vdd-io-voltage-level = <1800000 2950000>;
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 7f78c84..3e89c3a 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -30,14 +30,17 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
- <0xfc4bc450 16>;
- reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
+
+ qcom,pvs-fuse-redun-sel = <22 24 3 2>;
+ qcom,pvs-fuse = <22 6 5>;
+ qcom,pvs-fuse-redun = <22 27 5>;
+
qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
qcom,pvs-corner-ceiling-slow = <1155000 1160000 1275000>;
@@ -63,6 +66,16 @@
qcom,vdd-apc-step-down-limit = <1>;
qcom,cpr-apc-volt-step = <5000>;
+ qcom,cpr-fuse-redun-sel = <138 57 1 1>;
+ qcom,cpr-fuse-row = <138>;
+ qcom,cpr-fuse-bp-cpr-disable = <36>;
+ qcom,cpr-fuse-bp-scheme = <37>;
+ qcom,cpr-fuse-target-quot = <24 12 0>;
+ qcom,cpr-fuse-ro-sel = <54 38 41>;
+ qcom,cpr-fuse-redun-row = <139>;
+ qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
+
qcom,cpr-enable;
};
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 42c1247..17bdb9c 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -21,6 +21,7 @@
spi0 = &spi_0;
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+ sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
};
memory {
@@ -762,6 +763,95 @@
status = "disabled";
};
+ sdcc3: qcom,sdcc@f9864000 {
+ cell-index = <3>;
+ compatible = "qcom,msm-sdcc";
+ reg = <0xf9864000 0x800>,
+ <0xf9864800 0x100>,
+ <0xf9844000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+
+ qcom,bus-width = <4>;
+ gpios = <&msmgpio 44 0>, /* CLK */
+ <&msmgpio 43 0>, /* CMD */
+ <&msmgpio 42 0>, /* DATA0 */
+ <&msmgpio 41 0>, /* DATA1 */
+ <&msmgpio 40 0>, /* DATA2 */
+ <&msmgpio 39 0>; /* DATA3 */
+ qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+ qcom,msm-bus,name = "sdcc3";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+ <79 512 1600 3200>, /* 400 KB/s*/
+ <79 512 80000 160000>, /* 20 MB/s */
+ <79 512 100000 200000>, /* 25 MB/s */
+ <79 512 200000 400000>, /* 50 MB/s */
+ <79 512 400000 800000>, /* 100 MB/s */
+ <79 512 400000 800000>, /* 200 MB/s */
+ <79 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdcc3>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 127 0
+ 1 &intc 0 223 0
+ 2 &msmgpio 41 0x8>;
+ interrupt-names = "core_irq", "bam_irq", "sdiowakeup_irq";
+
+ status = "disabled";
+ };
+
+ sdhc_3: sdhci@f9864900 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0xf9864900 0x11c>, <0xf9864000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ qcom,bus-width = <4>;
+ gpios = <&msmgpio 44 0>, /* CLK */
+ <&msmgpio 43 0>, /* CMD */
+ <&msmgpio 42 0>, /* DATA0 */
+ <&msmgpio 41 0>, /* DATA1 */
+ <&msmgpio 40 0>, /* DATA2 */
+ <&msmgpio 39 0>; /* DATA3 */
+ qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+
+ qcom,msm-bus,name = "sdhc3";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <79 512 0 0>, /* No vote */
+ <79 512 1600 3200>, /* 400 KB/s*/
+ <79 512 80000 160000>, /* 20 MB/s */
+ <79 512 100000 200000>, /* 25 MB/s */
+ <79 512 200000 400000>, /* 50 MB/s */
+ <79 512 400000 800000>, /* 100 MB/s */
+ <79 512 400000 800000>, /* 200 MB/s */
+ <79 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_3>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 127 0
+ 1 &intc 0 224 0
+ 2 &msmgpio 41 0x8>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ status = "disabled";
+ };
+
spmi_bus: qcom,spmi@fc4c0000 {
cell-index = <0>;
compatible = "qcom,spmi-pmic-arb";
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 352ccf1..16fc2e7 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -171,7 +171,7 @@
cdc-vdda-h-supply = <&pm8110_l6>;
qcom,cdc-vdda-h-voltage = <1800000 1800000>;
- qcom,cdc-vdda-h-current = <250000>;
+ qcom,cdc-vdda-h-current = <25000>;
cdc-vdd-px-supply = <&pm8110_l6>;
qcom,cdc-vdd-px-voltage = <1800000 1800000>;
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 7a93c49..5a30d40 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -124,51 +124,6 @@
};
};
- i2c@f9927000 {
- msm8x10_wcd_codec@0d{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x0d>;
- cdc-vdda-cp-supply = <&pm8110_s4>;
- qcom,cdc-vdda-cp-voltage = <2150000 2150000>;
- qcom,cdc-vdda-cp-current = <650000>;
-
- cdc-vdda-h-supply = <&pm8110_l6>;
- qcom,cdc-vdda-h-voltage = <1800000 1800000>;
- qcom,cdc-vdda-h-current = <250000>;
-
- cdc-vdd-px-supply = <&pm8110_l6>;
- qcom,cdc-vdd-px-voltage = <1800000 1800000>;
- qcom,cdc-vdd-px-current = <10000>;
-
- cdc-vdd-1p2v-supply = <&pm8110_l4>;
- qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
- qcom,cdc-vdd-1p2v-current = <5000>;
-
- cdc-vdd-mic-bias-supply = <&pm8110_l20>;
- qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
- qcom,cdc-vdd-mic-bias-current = <25000>;
-
- qcom,cdc-micbias-cfilt-sel = <0x0>;
- qcom,cdc-micbias-cfilt-mv = <1800000>;
- qcom,cdc-mclk-clk-rate = <12288000>;
- };
-
- msm8x10_wcd_codec@77{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x77>;
- };
-
- msm8x10_wcd_codec@66{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x66>;
- };
-
- msm8x10_wcd_codec@55{
- compatible = "qcom,msm8x10-wcd-i2c";
- reg = <0x55>;
- };
- };
-
sound {
qcom,audio-routing =
"RX_BIAS", "MCLK",
@@ -180,6 +135,58 @@
};
};
+&i2c_cdc {
+ msm8x10_wcd_codec@0d{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x0d>;
+ cdc-vdda-cp-supply = <&pm8110_s4>;
+ qcom,cdc-vdda-cp-voltage = <1800000 2150000>;
+ qcom,cdc-vdda-cp-current = <650000>;
+
+ cdc-vdda-h-supply = <&pm8110_l6>;
+ qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdda-h-current = <25000>;
+
+ cdc-vdd-px-supply = <&pm8110_l6>;
+ qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-px-current = <10000>;
+
+ cdc-vdd-1p2v-supply = <&pm8110_l4>;
+ qcom,cdc-vdd-1p2v-voltage = <1200000 1200000>;
+ qcom,cdc-vdd-1p2v-current = <5000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8110_l20>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <25000>;
+
+ qcom,cdc-micbias-cfilt-sel = <0x0>;
+ qcom,cdc-micbias-cfilt-mv = <1800000>;
+ qcom,cdc-mclk-clk-rate = <12288000>;
+
+ qcom,cdc-static-supplies = "cdc-vdda-h",
+ "cdc-vdd-px",
+ "cdc-vdd-1p2v";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdda-cp",
+ "cdc-vdd-mic-bias";
+ };
+
+ msm8x10_wcd_codec@77{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x77>;
+ };
+
+ msm8x10_wcd_codec@66{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x66>;
+ };
+
+ msm8x10_wcd_codec@55{
+ compatible = "qcom,msm8x10-wcd-i2c";
+ reg = <0x55>;
+ };
+};
+
&spmi_bus {
qcom,pm8110@0 {
qcom,leds@a100 {
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 0d47e5d..38f587b 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -30,19 +30,22 @@
apc_vreg_corner: regulator@f9018000 {
status = "okay";
compatible = "qcom,cpr-regulator";
- reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b80b0 8>,
- <0xfc4bc450 16>;
- reg-names = "rbcpr", "rbcpr_clk", "pvs_efuse", "cpr_efuse";
+ reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
interrupts = <0 15 0>;
regulator-name = "apc_corner";
regulator-min-microvolt = <1>;
regulator-max-microvolt = <3>;
- qcom,num-efuse-bits = <5>;
- qcom,pvs-bin-process = <0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 2
- 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+
+ qcom,pvs-fuse-redun-sel = <53 25 3 2>;
+ qcom,pvs-fuse = <23 6 5>;
+ qcom,pvs-fuse-redun = <61 47 5>;
+
+ qcom,pvs-bin-process = <1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1>;
qcom,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
- qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000>;
- qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000>;
+ qcom,pvs-corner-ceiling-nom = <1075000 1075000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <1000000 1000000 1140000>;
vdd-apc-supply = <&pm8110_s2>;
vdd-mx-supply = <&pm8110_l3_ao>;
@@ -62,6 +65,18 @@
qcom,vdd-apc-step-up-limit = <1>;
qcom,vdd-apc-step-down-limit = <1>;
qcom,cpr-apc-volt-step = <5000>;
+
+ qcom,cpr-fuse-redun-sel = <53 25 3 2>;
+ qcom,cpr-fuse-row = <61>;
+ qcom,cpr-fuse-bp-cpr-disable = <39>;
+ qcom,cpr-fuse-bp-scheme = <40>;
+ qcom,cpr-fuse-target-quot = <27 15 3>;
+ qcom,cpr-fuse-ro-sel = <47 41 44>;
+ qcom,cpr-fuse-redun-row = <52>;
+ qcom,cpr-fuse-redun-bp-cpr-disable = <24>;
+ qcom,cpr-fuse-redun-bp-scheme = <25>;
+ qcom,cpr-fuse-redun-target-quot = <32 12 0>;
+ qcom,cpr-fuse-redun-ro-sel = <44 26 29>;
};
};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
new file mode 100644
index 0000000..cb8895f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974v2 CDP";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+ qcom,msm-id = <126 1 0x20002>,
+ <185 1 0x20002>,
+ <186 1 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
new file mode 100644
index 0000000..8e04c18
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974v2 FLUID";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+ qcom,msm-id = <126 3 0x20002>,
+ <185 3 0x20002>,
+ <186 3 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
new file mode 100644
index 0000000..7128abe
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974v2 LIQUID";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+ qcom,msm-id = <126 9 0x20002>,
+ <185 9 0x20002>,
+ <186 9 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
new file mode 100644
index 0000000..b7e35cf
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974v2 MTP";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+ qcom,msm-id = <126 8 0x20002>,
+ <185 8 0x20002>,
+ <186 8 0x20002>;
+};
+
+&pm8941_chg {
+ qcom,bpd-detection = "bpd_thm";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2.dtsi b/arch/arm/boot/dts/msm8974-v2-2.dtsi
new file mode 100644
index 0000000..09455b1
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2.dtsi
@@ -0,0 +1,105 @@
+/* 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+/* GPU overrides */
+&msm_gpu {
+ /* Updated chip ID */
+ qcom,chipid = <0x03030001>;
+
+ qcom,initial-pwrlevel = <4>;
+
+ /* Updated bus bandwidth requirements */
+ qcom,msm-bus,vectors-KBps =
+ /* Off */
+ <26 512 0 0>, <89 604 0 0>,
+ /* SVS */
+ <26 512 0 2400000>, <89 604 0 3000000>,
+ /* Nominal / SVS */
+ <26 512 0 4656000>, <89 604 0 3000000>,
+ /* Nominal */
+ <26 512 0 4656000>, <89 604 0 5120000>,
+ /* Turbo / Nominal */
+ <26 512 0 7464000>, <89 604 0 5120000>,
+ /* Turbo */
+ <26 512 0 7464000>, <89 604 0 6400000>;
+
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <450000000>;
+ qcom,bus-freq = <5>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index ba6377c..35d6d2a 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -50,6 +50,11 @@
reg = <0xfe807800 0x1000>; /* Address and size of IMEM */
};
+ qcom,msm-mem-hole {
+ compatible = "qcom,msm-mem-hole";
+ qcom,memblock-remove = <0x02000000 0x06000000>; /* Address and Size of Hole */
+ };
+
timer@f9020000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 174a576..a8eee29 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -429,6 +429,7 @@
select GPIO_MSM_V3
select MAY_HAVE_SPARSE_IRQ
select SPARSE_IRQ
+ select MEMORY_HOLE_CARVEOUT
config ARCH_MSM8610
bool "MSM8610"
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 4b6477b..6d848d2 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -270,7 +270,7 @@
[7] = { { 806400, HFPLL, 1, 42 }, LVL_NOM, 950000, 4 },
[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 },
+ [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 5 },
[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, 7 },
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index a32031d..fd831fc 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -468,6 +468,91 @@
},
};
+#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+static struct gpiomux_setting sdc3_clk_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sdc3_cmd_data_0_3_actv_cfg = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting sdc3_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting sdc3_data_1_suspend_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct msm_gpiomux_config msm8226_sdc3_configs[] __initdata = {
+ {
+ /* DAT3 */
+ .gpio = 39,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* DAT2 */
+ .gpio = 40,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* DAT1 */
+ .gpio = 41,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_data_1_suspend_cfg,
+ },
+ },
+ {
+ /* DAT0 */
+ .gpio = 42,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* CMD */
+ .gpio = 43,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_cmd_data_0_3_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+ {
+ /* CLK */
+ .gpio = 44,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &sdc3_clk_actv_cfg,
+ [GPIOMUX_SUSPENDED] = &sdc3_suspend_cfg,
+ },
+ },
+};
+
+static void msm_gpiomux_sdc3_install(void)
+{
+ msm_gpiomux_install(msm8226_sdc3_configs,
+ ARRAY_SIZE(msm8226_sdc3_configs));
+}
+#else
+static void msm_gpiomux_sdc3_install(void) {}
+#endif /* CONFIG_MMC_MSM_SDC3_SUPPORT */
+
void __init msm8226_init_gpiomux(void)
{
int rc;
@@ -500,4 +585,6 @@
if (of_board_is_cdp() || of_board_is_mtp() || of_board_is_xpm())
msm_gpiomux_install(usb_otg_sw_configs,
ARRAY_SIZE(usb_otg_sw_configs));
+
+ msm_gpiomux_sdc3_install();
}
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 5ad6175..0d62b7a 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -75,10 +75,14 @@
"msm_sdcc.1", NULL),
OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF98A4000, \
"msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,msm-sdcc", 0xF9864000, \
+ "msm_sdcc.3", NULL),
OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9824900, \
"msm_sdcc.1", NULL),
OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
"msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+ "msm_sdcc.3", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6432c93..66f2cd3 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -180,6 +180,12 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting gpio_epm_marker_config = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
@@ -526,6 +532,18 @@
[GPIOMUX_SUSPENDED] = &gpio_epm_config,
},
},
+ {
+ .gpio = 85, /* EPM MARKER2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+ },
+ },
+ {
+ .gpio = 96, /* EPM MARKER1 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+ },
+ },
};
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
@@ -825,6 +843,135 @@
},
};
+static struct msm_gpiomux_config msm_sensor_configs_dragonboard[] __initdata = {
+ {
+ .gpio = 15, /* CAM_MCLK0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 16, /* CAM_MCLK1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 17, /* CAM_MCLK2 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &cam_settings[4],
+ },
+ },
+ {
+ .gpio = 19, /* CCI_I2C_SDA0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 20, /* CCI_I2C_SCL0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 21, /* CCI_I2C_SDA1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 22, /* CCI_I2C_SCL1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[0],
+ },
+ },
+ {
+ .gpio = 23, /* FLASH_LED_EN */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 24, /* FLASH_LED_NOW */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 25, /* WEBCAM2_RESET_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 26, /* CAM_IRQ */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 27, /* OIS_SYNC */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 28, /* WEBCAM1_STANDBY */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 89, /* CAM1_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 90, /* CAM1_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 91, /* CAM2_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+ {
+ .gpio = 94, /* CAM2_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[3],
+ [GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
+ },
+ },
+};
+
static struct gpiomux_setting auxpcm_act_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
@@ -1198,7 +1345,9 @@
}
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
- msm_gpiomux_install(msm_eth_configs, ARRAY_SIZE(msm_eth_configs));
+ if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+ msm_gpiomux_install(msm_eth_configs, \
+ ARRAY_SIZE(msm_eth_configs));
#endif
msm_gpiomux_install(msm_blsp_configs, ARRAY_SIZE(msm_blsp_configs));
msm_gpiomux_install(msm_blsp2_uart7_configs,
@@ -1215,7 +1364,12 @@
msm_gpiomux_install(hap_lvl_shft_config,
ARRAY_SIZE(hap_lvl_shft_config));
- msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+ if (of_board_is_dragonboard() && machine_is_apq8074())
+ msm_gpiomux_install(msm_sensor_configs_dragonboard, \
+ ARRAY_SIZE(msm_sensor_configs_dragonboard));
+ else
+ msm_gpiomux_install(msm_sensor_configs, \
+ ARRAY_SIZE(msm_sensor_configs));
msm_gpiomux_install(&sd_card_det, 1);
@@ -1223,7 +1377,8 @@
of_board_is_dragonboard()))
msm_gpiomux_sdc3_install();
- msm_gpiomux_sdc4_install();
+ if (!(of_board_is_dragonboard() && machine_is_apq8074()))
+ msm_gpiomux_sdc4_install();
msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index fad2efc..36ad755 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -117,6 +117,10 @@
"usb_bam", NULL),
OF_DEV_AUXDATA("qcom,hsic-host", 0xF9A15000, \
"msm_hsic_host", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF98A4900, \
+ "msm_sdcc.2", NULL),
+ OF_DEV_AUXDATA("qcom,sdhci-msm", 0xF9864900, \
+ "msm_sdcc.3", NULL),
{}
};
diff --git a/arch/arm/mach-msm/board-krypton.c b/arch/arm/mach-msm/board-krypton.c
index 0d06b83..e80244b 100644
--- a/arch/arm/mach-msm/board-krypton.c
+++ b/arch/arm/mach-msm/board-krypton.c
@@ -31,6 +31,22 @@
#include "clock.h"
#include "devices.h"
+static struct memtype_reserve msmkrypton_reserve_table[] __initdata = {
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static int msmkrypton_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msmkrypton_reserve_info __initdata = {
+ .memtype_reserve_table = msmkrypton_reserve_table,
+ .paddr_to_memtype = msmkrypton_paddr_to_memtype,
+};
+
static struct of_dev_auxdata msmkrypton_auxdata_lookup[] __initdata = {
{}
};
@@ -47,6 +63,11 @@
msm_clock_init(&msmkrypton_clock_init_data);
}
+static void __init msmkrypton_early_memory(void)
+{
+ reserve_info = &msmkrypton_reserve_info;
+ of_scan_flat_dt(dt_scan_for_memory_hole, msmkrypton_reserve_table);
+}
static void __init msmkrypton_map_io(void)
{
msm_map_msmkrypton_io();
@@ -74,5 +95,6 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msmkrypton_dt_match,
+ .init_very_early = msmkrypton_early_memory,
.restart = msm_restart,
MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8084.c b/arch/arm/mach-msm/clock-8084.c
index 605a7ae..c54c3db 100644
--- a/arch/arm/mach-msm/clock-8084.c
+++ b/arch/arm/mach-msm/clock-8084.c
@@ -310,20 +310,24 @@
CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("core_clk_src", mdp_clk_src.c, "fd900000.qcom,mdss_mdp", OFF),
- CLK_DUMMY("", mdss_byte0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_byte1_clk.c, "", OFF),
CLK_DUMMY("", mdss_edpaux_clk.c, "", OFF),
CLK_DUMMY("", mdss_edplink_clk.c, "", OFF),
CLK_DUMMY("", mdss_edppixel_clk.c, "", OFF),
- CLK_DUMMY("", mdss_esc0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_esc1_clk.c, "", OFF),
+ CLK_DUMMY("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("byte_clk", mdss_byte1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("core_clk", mdss_esc1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("iface_clk", mdss_ahb_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("bus_clk", mdss_axi_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi", OFF),
+ CLK_DUMMY("pixel_clk", mdss_pclk1_clk.c, "fd922e00.qcom,mdss_dsi", OFF),
CLK_DUMMY("", mdss_extpclk_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_ahb_clk.c, "", OFF),
CLK_DUMMY("", mdss_hdmi_clk.c, "", OFF),
CLK_DUMMY("core_clk", mdss_mdp_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("lut_clk", mdss_mdp_lut_clk.c, "fd900000.qcom,mdss_mdp", OFF),
- CLK_DUMMY("", mdss_pclk0_clk.c, "", OFF),
- CLK_DUMMY("", mdss_pclk1_clk.c, "", OFF),
CLK_DUMMY("vsync_clk", mdss_vsync_clk.c, "fd900000.qcom,mdss_mdp", OFF),
CLK_DUMMY("", mmss_misc_ahb_clk.c, "", OFF),
CLK_DUMMY("", mmss_mmssnoc_ahb_clk.c, "", OFF),
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index 5550282..a2936c2 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -125,21 +125,7 @@
#define CPR_FUSE_RO_SEL_BITS 3
#define CPR_FUSE_RO_SEL_BITS_MASK ((1<<CPR_FUSE_RO_SEL_BITS)-1)
-#define CPR_FUSE_TARGET_QUOT_TURBO_SHIFT 0
-#define CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT 12
-#define CPR_FUSE_TARGET_QUOT_SVS_SHIFT 24
-
-#define CPR_FUSE_DISABLE_CPR_SHIFT 36
-#define CPR_FUSE_LOCAL_APPROACH_SHIFT 37
-#define CPR_FUSE_REDUNDANT_SHIFT 57
-
-/* PVS eFuse parameters */
-#define PVS_FUSE_REDUNDANT_SHIFT 24
-#define PVS_FUSE_REDUNDANT_BITS 3
-#define PVS_FUSE_REDUNDANT_MASK ((1<<PVS_FUSE_REDUNDANT_BITS)-1)
-
-#define PVS_FUSE_BINS_SHIFT 6
-#define PVS_FUSE_BINS_REDUNDANT_SHIFT 27
+#define BYTES_PER_FUSE_ROW 8
enum voltage_change_dir {
NO_CHANGE,
@@ -154,9 +140,11 @@
int corner;
int ceiling_max;
+ /* eFuse parameters */
+ phys_addr_t efuse_addr;
+ void __iomem *efuse_base;
+
/* Process voltage parameters */
- phys_addr_t pvs_efuse;
- u32 num_efuse_bits;
u32 pvs_bin_process[CPR_PVS_EFUSE_BINS_MAX];
u32 pvs_corner_v[NUM_APC_PVS][CPR_CORNER_MAX];
/* Process voltage variables */
@@ -173,12 +161,9 @@
int vdd_mx_vmin;
/* CPR parameters */
- phys_addr_t cpr_fuse_addr;
u64 cpr_fuse_bits;
- u64 cpr_fuse_bits_2;
bool cpr_fuse_disable;
bool cpr_fuse_local;
- bool cpr_fuse_redundancy;
int cpr_fuse_target_quot[CPR_CORNER_MAX];
int cpr_fuse_ro_sel[CPR_CORNER_MAX];
int gcnt;
@@ -838,7 +823,7 @@
#define cpr_regulator_resume NULL
#endif
-static int cpr_config(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_config(struct cpr_regulator *cpr_vreg)
{
int i;
u32 val, gcnt, reg;
@@ -928,47 +913,80 @@
return 0;
}
-static int __init cpr_pvs_init(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_is_fuse_redundant(struct cpr_regulator *cpr_vreg,
+ u32 redun_sel[4])
{
- void __iomem *efuse_base;
- u32 efuse_bits, redundant, shift, mask;
- int i, process;
+ u32 fuse_bits;
+ int redundant;
- efuse_base = ioremap(cpr_vreg->pvs_efuse, 4);
- if (!efuse_base) {
- pr_err("Unable to map pvs_efuse 0x%08x\n",
- cpr_vreg->pvs_efuse);
- return -EINVAL;
+ fuse_bits = readl_relaxed(cpr_vreg->efuse_base
+ + redun_sel[0] * BYTES_PER_FUSE_ROW);
+ fuse_bits = (fuse_bits >> redun_sel[1]) & ((1 << redun_sel[2]) - 1);
+ if (fuse_bits == redun_sel[3])
+ redundant = 1;
+ else
+ redundant = 0;
+
+ pr_info("[row:%d] = 0x%x @%d:%d = %d?: redundant=%d\n",
+ redun_sel[0], fuse_bits,
+ redun_sel[1], redun_sel[2], redun_sel[3], redundant);
+ return redundant;
+}
+
+static int __devinit cpr_pvs_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct device_node *of_node = pdev->dev.of_node;
+ u32 efuse_bits;
+ int rc, process;
+ u32 pvs_fuse[3], pvs_fuse_redun_sel[4];
+ bool redundant;
+ size_t pvs_bins;
+
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun-sel",
+ pvs_fuse_redun_sel, 4);
+ if (rc < 0) {
+ pr_err("pvs-fuse-redun-sel missing: rc=%d\n", rc);
+ return rc;
}
- efuse_bits = readl_relaxed(efuse_base);
+ redundant = cpr_is_fuse_redundant(cpr_vreg, pvs_fuse_redun_sel);
+
+ if (redundant) {
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun",
+ pvs_fuse, 3);
+ if (rc < 0) {
+ pr_err("pvs-fuse-redun missing: rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse",
+ pvs_fuse, 3);
+ if (rc < 0) {
+ pr_err("pvs-fuse missing: rc=%d\n", rc);
+ return rc;
+ }
+ }
/* Construct PVS process # from the efuse bits */
- redundant = (efuse_bits >> PVS_FUSE_REDUNDANT_SHIFT)
- & PVS_FUSE_REDUNDANT_MASK;
- if (redundant == 2)
- shift = PVS_FUSE_BINS_REDUNDANT_SHIFT;
- else
- shift = PVS_FUSE_BINS_SHIFT;
- mask = (1 << cpr_vreg->num_efuse_bits) - 1;
- cpr_vreg->pvs_bin = (efuse_bits >> shift) & mask;
+ efuse_bits = readl_relaxed(cpr_vreg->efuse_base +
+ pvs_fuse[0] * BYTES_PER_FUSE_ROW);
+ cpr_vreg->pvs_bin = (efuse_bits >> pvs_fuse[1]) &
+ ((1 << pvs_fuse[2]) - 1);
- /* Set ceiling max and use it for APC_PVS_NO */
- cpr_vreg->ceiling_max =
- cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
-
- iounmap(efuse_base);
+ pvs_bins = 1 << pvs_fuse[2];
+ rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
+ cpr_vreg->pvs_bin_process,
+ pvs_bins);
+ if (rc < 0) {
+ pr_err("pvs-bin-process missing: rc=%d\n", rc);
+ return rc;
+ }
process = cpr_vreg->pvs_bin_process[cpr_vreg->pvs_bin];
- pr_info("[0x%08X] = 0x%08X, n_bits=%d, bin=%d (%d) [redundant=%d]\n",
- cpr_vreg->pvs_efuse, efuse_bits, cpr_vreg->num_efuse_bits,
- cpr_vreg->pvs_bin, process, redundant);
- for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
- pr_info("[%d] [%d %d %d] uV\n", i,
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
- cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
- }
+ pr_info("[row:%d] = 0x%08X, n_bits=%d, bin=%d (%d)\n",
+ pvs_fuse[0], efuse_bits, pvs_fuse[2],
+ cpr_vreg->pvs_bin, process);
if (process == APC_PVS_NO || process >= NUM_APC_PVS) {
pr_err("Bin=%d (%d) is out of spec. Assume SLOW.\n",
@@ -994,7 +1012,7 @@
} \
} while (0)
-static int __init cpr_apc_init(struct platform_device *pdev,
+static int __devinit cpr_apc_init(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
@@ -1055,81 +1073,124 @@
}
}
-static int __init cpr_init_cpr_efuse(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_efuse(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
- void __iomem *efuse_base;
+ struct device_node *of_node = pdev->dev.of_node;
+ int i, rc = 0;
+ bool redundant;
+ u32 cpr_fuse_redun_sel[4];
+ char *targ_quot_str, *ro_sel_str;
+ u32 cpr_fuse_row;
+ u32 bp_cpr_disable, bp_scheme;
+ int bp_target_quot[CPR_CORNER_MAX];
+ int bp_ro_sel[CPR_CORNER_MAX];
u32 ro_sel, val;
- u64 fuse_bits;
- int ro_sel_shift[CPR_CORNER_MAX];
+ u64 fuse_bits, fuse_bits_2;
- efuse_base = ioremap(cpr_vreg->cpr_fuse_addr, 16);
- if (!efuse_base) {
- pr_err("Unable to map cpr_fuse_addr 0x%08x\n",
- cpr_vreg->cpr_fuse_addr);
- return -EINVAL;
+ rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-redun-sel",
+ cpr_fuse_redun_sel, 4);
+ if (rc < 0) {
+ pr_err("cpr-fuse-redun-sel missing: rc=%d\n", rc);
+ return rc;
}
- cpr_vreg->cpr_fuse_bits = readll_relaxed(efuse_base);
- cpr_vreg->cpr_fuse_bits_2 = readll_relaxed(efuse_base + 8);
+ redundant = cpr_is_fuse_redundant(cpr_vreg, cpr_fuse_redun_sel);
- iounmap(efuse_base);
+ if (redundant) {
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-redun-row",
+ &cpr_fuse_row, rc);
+ targ_quot_str = "qcom,cpr-fuse-redun-target-quot";
+ ro_sel_str = "qcom,cpr-fuse-redun-ro-sel";
+ } else {
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+ &cpr_fuse_row, rc);
+ targ_quot_str = "qcom,cpr-fuse-target-quot";
+ ro_sel_str = "qcom,cpr-fuse-ro-sel";
+ }
+ if (rc)
+ return rc;
+
+ rc = of_property_read_u32_array(of_node,
+ targ_quot_str,
+ &bp_target_quot[CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("missing %s: rc=%d\n", targ_quot_str, rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32_array(of_node,
+ ro_sel_str,
+ &bp_ro_sel[CPR_CORNER_SVS],
+ CPR_CORNER_MAX - CPR_CORNER_SVS);
+ if (rc < 0) {
+ pr_err("missing %s: rc=%d\n", ro_sel_str, rc);
+ return rc;
+ }
/* Read the control bits of eFuse */
- cpr_vreg->cpr_fuse_disable = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_DISABLE_CPR_SHIFT) & 0x01;
- cpr_vreg->cpr_fuse_local = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_LOCAL_APPROACH_SHIFT) & 0x01;
- cpr_vreg->cpr_fuse_redundancy = (cpr_vreg->cpr_fuse_bits >>
- CPR_FUSE_REDUNDANT_SHIFT) & 0x01;
+ fuse_bits = readll_relaxed(cpr_vreg->efuse_base
+ + cpr_fuse_row * BYTES_PER_FUSE_ROW);
+ pr_info("[row:%d] = 0x%llx\n", cpr_fuse_row, fuse_bits);
- pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr,
- cpr_vreg->cpr_fuse_bits);
- pr_info("disable = %d, local = %d, redundancy = %d\n",
- cpr_vreg->cpr_fuse_disable,
- cpr_vreg->cpr_fuse_local,
- cpr_vreg->cpr_fuse_redundancy);
- pr_info("[0x%08X] = 0x%llx\n", cpr_vreg->cpr_fuse_addr + 8,
- cpr_vreg->cpr_fuse_bits_2);
+ if (redundant) {
+ if (of_property_read_bool(of_node,
+ "qcom,cpr-fuse-redun-bp-cpr-disable")) {
+ CPR_PROP_READ_U32(of_node,
+ "cpr-fuse-redun-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node,
+ "cpr-fuse-redun-bp-scheme",
+ &bp_scheme, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = fuse_bits;
+ } else {
+ u32 temp_row;
- if (cpr_vreg->cpr_fuse_redundancy == 0) {
- fuse_bits = cpr_vreg->cpr_fuse_bits;
- ro_sel_shift[CPR_CORNER_SVS] = 54;
- ro_sel_shift[CPR_CORNER_NORMAL] = 38;
- ro_sel_shift[CPR_CORNER_TURBO] = 41;
+ /* Use original fuse if no optional property */
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+ &bp_scheme, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-row",
+ &temp_row, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = readll_relaxed(cpr_vreg->efuse_base
+ + temp_row * BYTES_PER_FUSE_ROW);
+ pr_info("[original row:%d] = 0x%llx\n",
+ temp_row, fuse_bits_2);
+ }
} else {
- fuse_bits = cpr_vreg->cpr_fuse_bits_2;
- ro_sel_shift[CPR_CORNER_SVS] = 46;
- ro_sel_shift[CPR_CORNER_NORMAL] = 36;
- ro_sel_shift[CPR_CORNER_TURBO] = 39;
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-cpr-disable",
+ &bp_cpr_disable, rc);
+ CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
+ &bp_scheme, rc);
+ if (rc)
+ return rc;
+ fuse_bits_2 = fuse_bits;
}
- /* SVS */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_SVS])
- & CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_SVS_SHIFT)
- & CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_SVS] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_SVS] = ro_sel;
- pr_info("SVS: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ cpr_vreg->cpr_fuse_disable = (fuse_bits_2 >> bp_cpr_disable) & 0x01;
+ cpr_vreg->cpr_fuse_local = (fuse_bits_2 >> bp_scheme) & 0x01;
- /* Nominal */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_NORMAL])
- & CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_NOMINAL_SHIFT)
- & CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_NORMAL] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_NORMAL] = ro_sel;
- pr_info("Nominal: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ pr_info("disable = %d, local = %d\n",
+ cpr_vreg->cpr_fuse_disable, cpr_vreg->cpr_fuse_local);
- /* Turbo */
- ro_sel = (fuse_bits >> ro_sel_shift[CPR_CORNER_TURBO])
+ for (i = CPR_CORNER_SVS; i < CPR_CORNER_MAX; i++) {
+ ro_sel = (fuse_bits >> bp_ro_sel[i])
& CPR_FUSE_RO_SEL_BITS_MASK;
- val = (fuse_bits >> CPR_FUSE_TARGET_QUOT_TURBO_SHIFT)
+ val = (fuse_bits >> bp_target_quot[i])
& CPR_FUSE_TARGET_QUOT_BITS_MASK;
- cpr_vreg->cpr_fuse_target_quot[CPR_CORNER_TURBO] = val;
- cpr_vreg->cpr_fuse_ro_sel[CPR_CORNER_TURBO] = ro_sel;
- pr_info("Turbo: ro_sel = %d, target quot = 0x%04x\n", ro_sel, val);
+ cpr_vreg->cpr_fuse_target_quot[i] = val;
+ cpr_vreg->cpr_fuse_ro_sel[i] = ro_sel;
+ pr_info("Corner[%d]: ro_sel = %d, target quot = %d\n",
+ i, ro_sel, val);
+ }
+ cpr_vreg->cpr_fuse_bits = fuse_bits;
if (!cpr_vreg->cpr_fuse_bits) {
cpr_vreg->cpr_fuse_disable = 1;
pr_err("cpr_fuse_bits = 0: set cpr_fuse_disable = 1\n");
@@ -1138,7 +1199,7 @@
return 0;
}
-static int __init cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_init_cpr_voltages(struct cpr_regulator *cpr_vreg)
{
int i;
@@ -1155,7 +1216,7 @@
return 0;
}
-static int __init cpr_init_cpr_parameters(struct platform_device *pdev,
+static int __devinit cpr_init_cpr_parameters(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
@@ -1223,20 +1284,12 @@
return rc;
}
-static int __init cpr_init_cpr(struct platform_device *pdev,
+static int __devinit cpr_init_cpr(struct platform_device *pdev,
struct cpr_regulator *cpr_vreg)
{
struct resource *res;
int rc = 0;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "cpr_efuse");
- if (!res || !res->start) {
- pr_err("cpr_efuse missing: res=%p\n", res);
- return -EINVAL;
- }
- cpr_vreg->cpr_fuse_addr = res->start;
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rbcpr_clk");
if (!res || !res->start) {
pr_err("missing rbcpr_clk address: res=%p\n", res);
@@ -1244,7 +1297,7 @@
}
cpr_vreg->rbcpr_clk_addr = res->start;
- rc = cpr_init_cpr_efuse(cpr_vreg);
+ rc = cpr_init_cpr_efuse(pdev, cpr_vreg);
if (rc)
return rc;
@@ -1287,44 +1340,41 @@
return 0;
}
-static int __init cpr_pvs_parse_dt(struct platform_device *pdev,
- struct cpr_regulator *cpr_vreg)
+static int __devinit cpr_efuse_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
+{
+ struct resource *res;
+ int len;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse_addr");
+ if (!res || !res->start) {
+ pr_err("efuse_addr missing: res=%p\n", res);
+ return -EINVAL;
+ }
+ cpr_vreg->efuse_addr = res->start;
+ len = res->end - res->start + 1;
+
+ pr_info("efuse_addr = 0x%x (len=0x%x)\n", res->start, len);
+
+ cpr_vreg->efuse_base = ioremap(cpr_vreg->efuse_addr, len);
+ if (!cpr_vreg->efuse_base) {
+ pr_err("Unable to map efuse_addr 0x%08x\n",
+ cpr_vreg->efuse_addr);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void cpr_efuse_free(struct cpr_regulator *cpr_vreg)
+{
+ iounmap(cpr_vreg->efuse_base);
+}
+
+static int __devinit cpr_voltage_plan_init(struct platform_device *pdev,
+ struct cpr_regulator *cpr_vreg)
{
struct device_node *of_node = pdev->dev.of_node;
- struct resource *res;
- int rc;
- size_t pvs_bins;
-
- /* Parse process voltage parameters */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pvs_efuse");
- if (!res || !res->start) {
- pr_err("pvs_efuse missing: res=%p\n", res);
- return -EINVAL;
- }
- cpr_vreg->pvs_efuse = res->start;
-
- rc = of_property_read_u32(of_node, "qcom,num-efuse-bits",
- &cpr_vreg->num_efuse_bits);
- if (rc < 0) {
- pr_err("num-efuse-bits missing: rc=%d\n", rc);
- return rc;
- }
-
- if (cpr_vreg->num_efuse_bits == 0 ||
- cpr_vreg->num_efuse_bits > CPR_PVS_EFUSE_BITS_MAX) {
- pr_err("invalid num-efuse-bits : %d\n",
- cpr_vreg->num_efuse_bits);
- return -EINVAL;
- }
-
- pvs_bins = 1 << cpr_vreg->num_efuse_bits;
- rc = of_property_read_u32_array(of_node, "qcom,pvs-bin-process",
- cpr_vreg->pvs_bin_process,
- pvs_bins);
- if (rc < 0) {
- pr_err("pvs-bin-process missing: rc=%d\n", rc);
- return rc;
- }
+ int rc, i;
rc = of_property_read_u32_array(of_node,
"qcom,pvs-corner-ceiling-slow",
@@ -1353,6 +1403,17 @@
return rc;
}
+ /* Set ceiling max and use it for APC_PVS_NO */
+ cpr_vreg->ceiling_max =
+ cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_CORNER_TURBO];
+
+ for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++) {
+ pr_info("[%d] [%d %d %d] uV\n", i,
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_SVS],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_NORMAL],
+ cpr_vreg->pvs_corner_v[i][CPR_CORNER_TURBO]);
+ }
+
return 0;
}
@@ -1386,31 +1447,39 @@
return -ENOMEM;
}
- rc = cpr_pvs_parse_dt(pdev, cpr_vreg);
+ rc = cpr_efuse_init(pdev, cpr_vreg);
if (rc) {
- pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+ pr_err("Wrong eFuse address specified: rc=%d\n", rc);
return rc;
}
- rc = cpr_pvs_init(cpr_vreg);
+ rc = cpr_voltage_plan_init(pdev, cpr_vreg);
+ if (rc) {
+ pr_err("Wrong DT parameter specified: rc=%d\n", rc);
+ goto err_out;
+ }
+
+ rc = cpr_pvs_init(pdev, cpr_vreg);
if (rc) {
pr_err("Initialize PVS wrong: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
rc = cpr_apc_init(pdev, cpr_vreg);
if (rc) {
if (rc != -EPROBE_DEFER)
pr_err("Initialize APC wrong: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
rc = cpr_init_cpr(pdev, cpr_vreg);
if (rc) {
pr_err("Initialize CPR failed: rc=%d\n", rc);
- return rc;
+ goto err_out;
}
+ cpr_efuse_free(cpr_vreg);
+
mutex_init(&cpr_vreg->cpr_mutex);
rdesc = &cpr_vreg->rdesc;
@@ -1433,6 +1502,10 @@
the_cpr = cpr_vreg;
return 0;
+
+err_out:
+ cpr_efuse_free(cpr_vreg);
+ return rc;
}
static int __devexit cpr_regulator_remove(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 5d25134..f8a32b4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -25,6 +25,7 @@
#ifdef CONFIG_MSM_SCM
#define SCM_SVC_BOOT 0x1
#define SCM_CMD_TERMINATE_PC 0x2
+#define SCM_CMD_CORE_HOTPLUGGED 0x10
#endif
ENTRY(msm_arch_idle)
@@ -99,7 +100,7 @@
#ifdef CONFIG_MSM_SCM
ldr r0, =SCM_SVC_BOOT
ldr r1, =SCM_CMD_TERMINATE_PC
- mov r2, #0
+ ldr r2, =SCM_CMD_CORE_HOTPLUGGED
bl scm_call_atomic1
#else
mrc p15, 0, r3, c1, c0, 0 /* read current CR */
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index 95f33d5..ff3da11 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,7 +25,8 @@
struct msm_hdmi_audio_codec_ops {
int (*audio_info_setup)(struct platform_device *pdev,
- u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+ u32 sample_rate, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift,
bool down_mix);
int (*get_audio_edid_blk) (struct platform_device *pdev,
struct msm_hdmi_audio_edid_blk *blk);
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 0de37c9..58b0513 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -742,6 +742,16 @@
fd_install(ret, lock->file);
+ /*
+ * Taking a reference for lock file.
+ * This is required as now we have two file descriptor
+ * pointing to same file. If one FD is closed, lock file
+ * will be closed. Taking this reference will make sure
+ * that file doesn't get close. This refrence will go
+ * when client will call close on this FD.
+ */
+ fget(ret);
+
return ret;
}
EXPORT_SYMBOL(genlock_get_fd_handle);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e316742..32a667f 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -109,6 +109,10 @@
.pm4_fw = NULL,
.wait_timeout = 0, /* in milliseconds, 0 means disabled */
.ib_check_level = 0,
+ .ft_policy = KGSL_FT_DEFAULT_POLICY,
+ .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
+ .fast_hang_detect = 1,
+ .long_ib_detect = 1,
};
/* This set of registers are used for Hang detection
@@ -211,6 +215,8 @@
512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
};
+static unsigned int adreno_isidle(struct kgsl_device *device);
+
/**
* adreno_perfcounter_init: Reserve kernel performance counters
* @device: device to configure
@@ -818,6 +824,27 @@
return cmds - cmds_orig;
}
+/**
+ * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
+ * @adreno_dev: the device
+ *
+ * In many cases it is preferable to poke the iommu or gpummu directly rather
+ * than using the GPU command stream. If we are idle or trying to go to a low
+ * power state, using the command stream will be slower and asynchronous, which
+ * needlessly complicates the power state transitions. Additionally,
+ * the hardware simulators do not support command stream MMU operations so
+ * the command stream can never be used if we are capturing CFF data.
+ *
+ */
+static bool adreno_use_default_setstate(struct adreno_device *adreno_dev)
+{
+ return (adreno_isidle(&adreno_dev->dev) ||
+ adreno_dev->drawctxt_active == NULL ||
+ KGSL_STATE_ACTIVE != adreno_dev->dev.state ||
+ atomic_read(&adreno_dev->dev.active_cnt) == 0 ||
+ adreno_dev->dev.cff_dump_enable);
+}
+
static void adreno_iommu_setstate(struct kgsl_device *device,
unsigned int context_id,
uint32_t flags)
@@ -832,10 +859,7 @@
struct adreno_context *adreno_ctx = NULL;
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- if (!adreno_dev->drawctxt_active ||
- KGSL_STATE_ACTIVE != device->state ||
- !atomic_read(&device->active_cnt) ||
- device->cff_dump_enable) {
+ if (adreno_use_default_setstate(adreno_dev)) {
kgsl_mmu_device_setstate(&device->mmu, flags);
return;
}
@@ -845,7 +869,7 @@
if (context == NULL)
return;
- adreno_ctx = context->devctxt;
+ adreno_ctx = ADRENO_CONTEXT(context);
if (kgsl_mmu_enable_clk(&device->mmu,
KGSL_IOMMU_CONTEXT_USER))
@@ -886,8 +910,7 @@
adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
&link[0], sizedwords);
- kgsl_mmu_disable_clk_on_ts(&device->mmu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
+ kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, true);
kgsl_context_put(context);
}
@@ -915,11 +938,11 @@
* writes For CFF dump we must idle and use the registers so that it is
* easier to filter out the mmu accesses from the dump
*/
- if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
+ if (!adreno_use_default_setstate(adreno_dev)) {
context = kgsl_context_get(device, context_id);
if (context == NULL)
return;
- adreno_ctx = context->devctxt;
+ adreno_ctx = ADRENO_CONTEXT(context);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
/* wait for graphics pipe to be idle */
@@ -1663,6 +1686,8 @@
adreno_debugfs_init(device);
+ adreno_ft_init_sysfs(device);
+
kgsl_pwrscale_init(device);
kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
@@ -1703,7 +1728,6 @@
static int adreno_init(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int i;
if (KGSL_STATE_DUMP_AND_FT != device->state)
@@ -1744,8 +1768,6 @@
adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
- rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
/* Initialize ft detection register offsets */
ft_detect_regs[0] = adreno_getreg(adreno_dev,
ADRENO_REG_RBBM_STATUS);
@@ -1860,6 +1882,9 @@
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ if (adreno_dev->drawctxt_active)
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
adreno_dev->drawctxt_active = NULL;
adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
@@ -1892,7 +1917,7 @@
{
unsigned int ft_status = *((unsigned int *) data);
struct kgsl_context *context = ptr;
- struct adreno_context *adreno_context = context->devctxt;
+ struct adreno_context *adreno_context = ADRENO_CONTEXT(context);
if (ft_status) {
context->reset_status =
@@ -1930,20 +1955,16 @@
static int _set_max_ts(int id, void *ptr, void *data)
{
struct kgsl_device *device = data;
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
struct kgsl_context *context = ptr;
- struct adreno_context *drawctxt = context->devctxt;
+ struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
- if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+ if (drawctxt && drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
- soptimestamp),
- rb->timestamp[context->id]);
+ soptimestamp), drawctxt->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
- eoptimestamp),
- rb->timestamp[context->id]);
+ eoptimestamp), drawctxt->timestamp);
}
return 0;
@@ -2199,7 +2220,7 @@
}
if (context) {
- adreno_context = context->devctxt;
+ adreno_context = ADRENO_CONTEXT(context);
if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
if (ft_data->ib1) {
ret = _find_hanging_ib_sequence(rb,
@@ -2266,6 +2287,9 @@
return -EINVAL;
}
+ if (adreno_dev->drawctxt_active)
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
adreno_dev->drawctxt_active = NULL;
/* Stop the ringbuffer */
@@ -2328,11 +2352,9 @@
}
reset_done:
- if (context) {
- struct adreno_context *adreno_context = context->devctxt;
- kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
- KGSL_MEMSTORE_GLOBAL);
- }
+ if (context)
+ kgsl_mmu_setstate(&device->mmu, context->pagetable,
+ KGSL_MEMSTORE_GLOBAL);
/* If iommu is used then we need to make sure that the iommu clocks
* are on since there could be commands in pipeline that touch iommu */
@@ -2451,7 +2473,7 @@
}
} else {
no_context_ft = 0;
- adreno_context = context->devctxt;
+ adreno_context = ADRENO_CONTEXT(context);
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
/*
* set the invalid ts flag to 0 for this context since we have
@@ -2507,16 +2529,16 @@
goto play_good_cmds;
}
- /* Do not try the reply if hang is due to a pagefault */
- if (adreno_context && adreno_context->pagefault) {
+ /* Do not try to replay if hang is due to a pagefault */
+ if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
/* Resume MMU */
mmu->mmu_ops->mmu_pagefault_resume(mmu);
- if ((ft_data->context_id == adreno_context->id) &&
- (ft_data->global_eop == adreno_context->pagefault_ts)) {
+ if ((ft_data->context_id == context->id) &&
+ (ft_data->global_eop == context->pagefault_ts)) {
ft_data->ft_policy &= ~KGSL_FT_REPLAY;
KGSL_FT_ERR(device, "MMU fault skipping replay\n");
}
- adreno_context->pagefault = 0;
+ clear_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
}
if (ft_data->ft_policy & KGSL_FT_REPLAY) {
@@ -2604,6 +2626,10 @@
adreno_context->flags = (adreno_context->flags &
~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
}
+
+ if (last_active_ctx)
+ _kgsl_context_get(&last_active_ctx->base);
+
adreno_dev->drawctxt_active = last_active_ctx;
}
@@ -2631,10 +2657,7 @@
struct kgsl_context *last_ctx = kgsl_context_get(device,
ft_data->last_valid_ctx_id);
- if (last_ctx)
- adreno_dev->drawctxt_active = last_ctx->devctxt;
-
- kgsl_context_put(last_ctx);
+ adreno_dev->drawctxt_active = ADRENO_CONTEXT(last_ctx);
}
done:
@@ -2653,7 +2676,6 @@
int ret = 0;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- unsigned int timestamp;
/*
* If GPU FT is turned off do not run FT.
@@ -2670,8 +2692,8 @@
"Bad context_id: %u, global_eop: 0x%x\n",
ft_data->ib1, ft_data->context_id, ft_data->global_eop);
- timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
- KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
+ KGSL_FT_INFO(device, "Last issued global timestamp: %x\n",
+ rb->global_ts);
/* We may need to replay commands multiple times based on whether
* multiple contexts hang the GPU */
@@ -2700,14 +2722,12 @@
/* Restore correct states after fault tolerance */
if (adreno_dev->drawctxt_active)
device->mmu.hwpagetable =
- adreno_dev->drawctxt_active->pagetable;
+ adreno_dev->drawctxt_active->base.pagetable;
else
device->mmu.hwpagetable = device->mmu.defaultpagetable;
- rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp),
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ eoptimestamp), rb->global_ts);
/* switch to NULL ctxt */
if (adreno_dev->drawctxt_active != NULL)
@@ -2798,6 +2818,264 @@
}
EXPORT_SYMBOL(adreno_dump_and_exec_ft);
+/**
+ * _ft_sysfs_store() - Common routine to write to FT sysfs files
+ * @buf: value to write
+ * @count: size of the value to write
+ * @sysfs_cfg: KGSL FT sysfs config to write
+ *
+ * This is a common routine to write to FT sysfs files.
+ */
+static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr)
+{
+ char temp[20];
+ unsigned long val;
+ int rc;
+
+ snprintf(temp, sizeof(temp), "%.*s",
+ (int)min(count, sizeof(temp) - 1), buf);
+ rc = kstrtoul(temp, 0, &val);
+ if (rc)
+ return rc;
+
+ *ptr = val;
+
+ return count;
+}
+
+/**
+ * _get_adreno_dev() - Routine to get a pointer to adreno dev
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+struct adreno_device *_get_adreno_dev(struct device *dev)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ return device ? ADRENO_DEVICE(device) : NULL;
+}
+
+/**
+ * _ft_policy_store() - Routine to configure FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+static int _ft_policy_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+}
+
+/**
+ * _ft_policy_show() - Routine to read FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT policy
+ */
+static int _ft_policy_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy);
+}
+
+/**
+ * _ft_pagefault_policy_store() - Routine to configure FT
+ * pagefault policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+static int _ft_pagefault_policy_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+}
+
+/**
+ * _ft_pagefault_policy_show() - Routine to read FT pagefault
+ * policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT pagefault policy
+ */
+static int _ft_pagefault_policy_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy);
+}
+
+/**
+ * _ft_fast_hang_detect_store() - Routine to configure FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x1 - Enable fast hang detection
+ * 0x0 - Disable fast hang detection
+ */
+static int _ft_fast_hang_detect_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+
+}
+
+/**
+ * _ft_fast_hang_detect_show() - Routine to read FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_fast_hang_detect_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (adreno_dev->fast_hang_detect ? 1 : 0));
+}
+
+/**
+ * _ft_long_ib_detect_store() - Routine to configure FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x0 - Enable long IB detection
+ * 0x1 - Disable long IB detection
+ */
+static int _ft_long_ib_detect_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ int ret;
+ if (adreno_dev == NULL)
+ return 0;
+
+ mutex_lock(&adreno_dev->dev.mutex);
+ ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect);
+ mutex_unlock(&adreno_dev->dev.mutex);
+
+ return ret;
+
+}
+
+/**
+ * _ft_long_ib_detect_show() - Routine to read FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_long_ib_detect_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ (adreno_dev->long_ib_detect ? 1 : 0));
+}
+
+
+#define FT_DEVICE_ATTR(name) \
+ DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store);
+
+FT_DEVICE_ATTR(ft_policy);
+FT_DEVICE_ATTR(ft_pagefault_policy);
+FT_DEVICE_ATTR(ft_fast_hang_detect);
+FT_DEVICE_ATTR(ft_long_ib_detect);
+
+
+const struct device_attribute *ft_attr_list[] = {
+ &dev_attr_ft_policy,
+ &dev_attr_ft_pagefault_policy,
+ &dev_attr_ft_fast_hang_detect,
+ &dev_attr_ft_long_ib_detect,
+ NULL,
+};
+
+int adreno_ft_init_sysfs(struct kgsl_device *device)
+{
+ return kgsl_create_device_sysfs_files(device->dev, ft_attr_list);
+}
+
+void adreno_ft_uninit_sysfs(struct kgsl_device *device)
+{
+ kgsl_remove_device_sysfs_files(device->dev, ft_attr_list);
+}
+
static int adreno_getproperty(struct kgsl_device *device,
enum kgsl_property_type type,
void *value,
@@ -2942,20 +3220,15 @@
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- unsigned long wait;
+ unsigned long wait = jiffies;
unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
unsigned int rptr;
- /*
- * The first time into the loop, wait for 100 msecs and kick wptr again
- * to ensure that the hardware has updated correctly. After that, kick
- * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
- * expires
- */
-
- wait = jiffies + msecs_to_jiffies(100);
-
do {
+ /*
+ * Wait is "jiffies" first time in the loop to start
+ * GPU stall detection immediately.
+ */
if (time_after(jiffies, wait)) {
/* Check to see if the core is hung */
if (adreno_ft_detect(device, regs))
@@ -2977,11 +3250,10 @@
/* Caller must hold the device mutex. */
int adreno_idle(struct kgsl_device *device)
{
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- unsigned int rbbm_status;
unsigned long wait_time;
unsigned long wait_time_part;
unsigned int prev_reg_val[FT_DETECT_REGS_COUNT];
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -2999,23 +3271,15 @@
wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
while (time_before(jiffies, wait_time)) {
- adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
- &rbbm_status);
- if (adreno_is_a2xx(adreno_dev)) {
- if (rbbm_status == 0x110)
- return 0;
- } else {
- if (!(rbbm_status & 0x80000000))
- return 0;
- }
+ if (adreno_isidle(device))
+ return 0;
- /* Dont wait for timeout, detect hang faster.
- */
+ /* Dont wait for timeout, detect hang faster. */
if (time_after(jiffies, wait_time_part)) {
- wait_time_part = jiffies +
- msecs_to_jiffies(KGSL_TIMEOUT_PART);
- if ((adreno_ft_detect(device, prev_reg_val)))
- goto err;
+ wait_time_part = jiffies +
+ msecs_to_jiffies(KGSL_TIMEOUT_PART);
+ if ((adreno_ft_detect(device, prev_reg_val)))
+ goto err;
}
}
@@ -3064,9 +3328,8 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- WARN_ON(device->state == KGSL_STATE_INIT);
/* If the device isn't active, don't force it on. */
- if (device->state == KGSL_STATE_ACTIVE) {
+ if (kgsl_pwrctrl_isenabled(device)) {
/* Is the ring buffer is empty? */
unsigned int rptr = adreno_get_rptr(rb);
if (rptr == rb->wptr) {
@@ -3109,21 +3372,20 @@
phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
{
struct kgsl_context *context;
- struct adreno_context *adreno_context = NULL;
int next = 0;
struct kgsl_memdesc *desc = NULL;
-
read_lock(&device->context_lock);
while (1) {
context = idr_get_next(&device->context_idr, &next);
if (context == NULL)
break;
- adreno_context = (struct adreno_context *)context->devctxt;
-
- if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+ if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable,
pt_base)) {
+ struct adreno_context *adreno_context;
+
+ adreno_context = ADRENO_CONTEXT(context);
desc = &adreno_context->gpustate;
if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
break;
@@ -3257,9 +3519,10 @@
static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
{
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
+
if (k_ctxt != NULL) {
- struct adreno_context *a_ctxt = k_ctxt->devctxt;
- if (k_ctxt->id == KGSL_CONTEXT_INVALID || a_ctxt == NULL)
+ struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+ if (kgsl_context_detached(k_ctxt))
context_id = KGSL_CONTEXT_INVALID;
else if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
context_id = k_ctxt->id;
@@ -3330,7 +3593,8 @@
*/
if (context && device->state != KGSL_STATE_SLUMBER) {
- adreno_ringbuffer_issuecmds(device, context->devctxt,
+ adreno_ringbuffer_issuecmds(device,
+ ADRENO_CONTEXT(context),
KGSL_CMD_FLAGS_GET_INT, NULL, 0);
}
}
@@ -3390,6 +3654,7 @@
unsigned int curr_context_id = 0;
static struct adreno_context *curr_context;
static struct kgsl_context *context;
+ static char pid_name[TASK_COMM_LEN] = "unknown";
if (!adreno_dev->fast_hang_detect)
fast_hang_detected = 0;
@@ -3402,7 +3667,7 @@
if (is_adreno_rbbm_status_idle(device) &&
(kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED)
- == rb->timestamp[KGSL_MEMSTORE_GLOBAL])) {
+ == rb->global_ts)) {
/*
* On A2XX if the RPTR != WPTR and the device is idle, then
@@ -3453,8 +3718,13 @@
if (curr_global_ts == prev_global_ts) {
- /* Get the current context here */
- if (context == NULL) {
+ /* If we don't already have a good context, get it. */
+ if (kgsl_context_detached(context)) {
+ kgsl_context_put(context);
+ context = NULL;
+ curr_context = NULL;
+ strlcpy(pid_name, "unknown", sizeof(pid_name));
+
kgsl_sharedmem_readl(&device->memstore,
&curr_context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -3464,8 +3734,12 @@
context = kgsl_context_get(device, curr_context_id);
if (context != NULL) {
- curr_context = context->devctxt;
+ struct task_struct *task;
+ curr_context = ADRENO_CONTEXT(context);
curr_context->ib_gpu_time_used = 0;
+ task = find_task_by_vpid(context->pid);
+ if (task)
+ get_task_comm(pid_name, task);
} else {
KGSL_DRV_ERR(device,
"Fault tolerance no context found\n");
@@ -3489,8 +3763,7 @@
KGSL_FT_ERR(device,
"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
" on global ts %d\n",
- curr_context ? curr_context->pid_name : "",
- curr_context ? curr_context->id : 0,
+ pid_name, context ? context->id : 0,
(kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_RETIRED) + 1),
curr_global_ts + 1);
@@ -3502,7 +3775,7 @@
curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
KGSL_FT_INFO(device,
"Proc %s used GPU Time %d ms on timestamp 0x%X\n",
- curr_context->pid_name, curr_context->ib_gpu_time_used,
+ pid_name, curr_context->ib_gpu_time_used,
curr_global_ts+1);
if ((long_ib_detected) &&
@@ -3518,8 +3791,7 @@
"Proc %s, ctxt_id %d ts %d"
"used GPU for %d ms long ib "
"detected on global ts %d\n",
- curr_context->pid_name,
- curr_context->id,
+ pid_name, context->id,
(kgsl_readtimestamp(device,
context,
KGSL_TIMESTAMP_RETIRED)+1),
@@ -3541,6 +3813,7 @@
kgsl_context_put(context);
context = NULL;
curr_context = NULL;
+ strlcpy(pid_name, "unknown", sizeof(pid_name));
adreno_dev->long_ib = 0;
adreno_dev->long_ib_ts = 0;
}
@@ -3563,7 +3836,7 @@
if (context_id == KGSL_CONTEXT_INVALID)
return -EINVAL;
- ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+ ts_issued = adreno_context_timestamp(context, &adreno_dev->ringbuffer);
if (timestamp_cmp(timestamp, ts_issued) <= 0)
return 0;
@@ -3598,7 +3871,8 @@
unsigned int msecs)
{
static unsigned int io_cnt;
- struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+ struct adreno_context *adreno_ctx = context ? ADRENO_CONTEXT(context) :
+ NULL;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
unsigned int context_id = _get_context_id(context);
unsigned int time_elapsed = 0;
@@ -3606,8 +3880,6 @@
int ts_compare = 1;
int io, ret = -ETIMEDOUT;
- /* Get out early if the context has already been destroyed */
-
if (context_id == KGSL_CONTEXT_INVALID) {
KGSL_DRV_WARN(device, "context was detached");
return -EINVAL;
@@ -3745,9 +4017,9 @@
switch (type) {
case KGSL_TIMESTAMP_QUEUED: {
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- timestamp = rb->timestamp[context_id];
+ timestamp = adreno_context_timestamp(context,
+ &adreno_dev->ringbuffer);
break;
}
case KGSL_TIMESTAMP_CONSUMED:
@@ -3919,6 +4191,7 @@
/* Optional functions */
.setstate = adreno_setstate,
.drawctxt_create = adreno_drawctxt_create,
+ .drawctxt_detach = adreno_drawctxt_detach,
.drawctxt_destroy = adreno_drawctxt_destroy,
.setproperty = adreno_setproperty,
.postmortem_dump = adreno_dump,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b53d16f..cb75b34 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -25,6 +25,9 @@
#define ADRENO_DEVICE(device) \
KGSL_CONTAINER_OF(device, struct adreno_device, dev)
+#define ADRENO_CONTEXT(device) \
+ KGSL_CONTAINER_OF(device, struct adreno_context, base)
+
#define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
#define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
#define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
@@ -337,10 +340,10 @@
#define KGSL_FT_DEFAULT_POLICY (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
/* Pagefault policy flags */
-#define KGSL_FT_PAGEFAULT_INT_ENABLE 0x00000001
-#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE 0x00000002
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE 0x00000004
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT 0x00000008
+#define KGSL_FT_PAGEFAULT_INT_ENABLE BIT(0)
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE BIT(1)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE BIT(2)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT BIT(3)
#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY (KGSL_FT_PAGEFAULT_INT_ENABLE + \
KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
@@ -407,6 +410,9 @@
unsigned int adreno_ft_detect(struct kgsl_device *device,
unsigned int *prev_reg_val);
+int adreno_ft_init_sysfs(struct kgsl_device *device);
+void adreno_ft_uninit_sysfs(struct kgsl_device *device);
+
int adreno_perfcounter_get(struct adreno_device *adreno_dev,
unsigned int groupid, unsigned int countable, unsigned int *offset,
unsigned int flags);
@@ -501,6 +507,26 @@
}
/**
+ * adreno_context_timestamp() - Return the last queued timestamp for the context
+ * @k_ctxt: Pointer to the KGSL context to query
+ * @rb: Pointer to the ringbuffer structure for the GPU
+ *
+ * Return the last queued context for the given context. This is used to verify
+ * that incoming requests are not using an invalid (unsubmitted) timestamp
+ */
+static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
+ struct adreno_ringbuffer *rb)
+{
+ if (k_ctxt) {
+ struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+
+ if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+ return a_ctxt->timestamp;
+ }
+ return rb->global_ts;
+}
+
+/**
* adreno_encode_istore_size - encode istore size in CP format
* @adreno_dev - The 3D device.
*
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 42137fe..3d72c5c 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1355,7 +1355,7 @@
tmp_ctx.gmem_base = adreno_dev->gmem_base;
result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+ drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
if (result)
return result;
@@ -1364,7 +1364,7 @@
drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
/* blank out gmem shadow. */
- kgsl_sharedmem_set(drawctxt->dev_priv->device,
+ kgsl_sharedmem_set(drawctxt->base.device,
&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
drawctxt->context_gmem_shadow.size);
@@ -1389,7 +1389,7 @@
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(drawctxt->dev_priv,
+ kgsl_cffdump_syncmem(drawctxt->base.device,
&drawctxt->context_gmem_shadow.gmemshadow,
drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1410,13 +1410,13 @@
*/
ret = kgsl_allocate(&drawctxt->gpustate,
- drawctxt->pagetable, _context_size(adreno_dev));
+ drawctxt->base.pagetable, _context_size(adreno_dev));
if (ret)
return ret;
- kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
- 0, _context_size(adreno_dev));
+ kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate,
+ 0, 0, _context_size(adreno_dev));
tmp_ctx.cmd = tmp_ctx.start
= (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1440,8 +1440,8 @@
kgsl_cache_range_op(&drawctxt->gpustate,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
- drawctxt->gpustate.gpuaddr,
+ kgsl_cffdump_syncmem(drawctxt->base.device,
+ &drawctxt->gpustate, drawctxt->gpustate.gpuaddr,
drawctxt->gpustate.size, false);
done:
@@ -1516,7 +1516,7 @@
"Current active context has caused gpu hang\n");
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_save[1],
context->reg_save[2] << 2, true);
/* save registers and constants. */
@@ -1525,7 +1525,7 @@
context->reg_save, 3);
if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_save[1],
context->shader_save[2] << 2, true);
@@ -1534,7 +1534,7 @@
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_fixup[1],
context->shader_fixup[2] << 2, true);
@@ -1552,7 +1552,7 @@
if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
(context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
/* save gmem.
@@ -1562,7 +1562,7 @@
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_save, 3);
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1586,9 +1586,18 @@
unsigned int cmds[5];
if (context == NULL) {
- /* No context - set the default apgetable and thats it */
+ /* No context - set the default pagetable and thats it */
+ unsigned int id;
+ /*
+ * If there isn't a current context, the kgsl_mmu_setstate
+ * will use the CPU path so we don't need to give
+ * it a valid context id.
+ */
+ id = (adreno_dev->drawctxt_active != NULL)
+ ? adreno_dev->drawctxt_active->base.id
+ : KGSL_CONTEXT_INVALID;
kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
- adreno_dev->drawctxt_active->id);
+ id);
return;
}
@@ -1597,16 +1606,17 @@
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
cmds[3] = device->memstore.gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
- cmds[4] = context->id;
+ cmds[4] = context->base.id;
adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
cmds, 5);
- kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+ kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+ context->base.id);
/* restore gmem.
* (note: changes shader. shader must not already be restored.)
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
true);
@@ -1616,7 +1626,7 @@
context->context_gmem_shadow.gmem_restore, 3);
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1631,7 +1641,7 @@
}
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+ kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_restore[1],
context->reg_restore[2] << 2, true);
@@ -1641,7 +1651,7 @@
/* restore shader instructions & partitioning. */
if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_restore[1],
context->shader_restore[2] << 2, true);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7e5638c..670f0cf 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2321,7 +2321,7 @@
tmp_ctx.gmem_base = adreno_dev->gmem_base;
result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+ drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
if (result)
return result;
@@ -2355,7 +2355,7 @@
*/
ret = kgsl_allocate(&drawctxt->gpustate,
- drawctxt->pagetable, CONTEXT_SIZE);
+ drawctxt->base.pagetable, CONTEXT_SIZE);
if (ret)
return ret;
@@ -2420,7 +2420,7 @@
* already be saved.)
*/
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2441,8 +2441,17 @@
if (context == NULL) {
/* No context - set the default pagetable and thats it */
+ unsigned int id;
+ /*
+ * If there isn't a current context, the kgsl_mmu_setstate
+ * will use the CPU path so we don't need to give
+ * it a valid context id.
+ */
+ id = (adreno_dev->drawctxt_active != NULL)
+ ? adreno_dev->drawctxt_active->base.id
+ : KGSL_CONTEXT_INVALID;
kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
- adreno_dev->drawctxt_active->id);
+ id);
return;
}
@@ -2451,10 +2460,11 @@
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
cmds[3] = device->memstore.gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
- cmds[4] = context->id;
+ cmds[4] = context->base.id;
adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
cmds, 5);
- kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+ kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+ context->base.id);
/*
* Restore GMEM. (note: changes shader.
@@ -2462,7 +2472,7 @@
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(context->dev_priv,
+ kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 90bd017..fc98d86 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -56,41 +56,6 @@
&adreno_dev->wait_timeout);
debugfs_create_u32("ib_check", 0644, device->d_debugfs,
&adreno_dev->ib_check_level);
- /* By Default enable fast hang detection */
- adreno_dev->fast_hang_detect = 1;
- debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
- &adreno_dev->fast_hang_detect);
- /*
- * FT policy can be set to any of the options below.
- * KGSL_FT_OFF -> BIT(0) Set to turn off FT
- * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
- * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
- * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
- * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
- * by default set FT policy to KGSL_FT_DEFAULT_POLICY
- */
- adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
- debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_policy);
- /* By default enable long IB detection */
- adreno_dev->long_ib_detect = 1;
- debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
- &adreno_dev->long_ib_detect);
-
- /*
- * FT pagefault policy can be set to any of the options below.
- * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
- * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
- * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
- * pagefault per page.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
- * pagefault per INT.
- */
- adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
- debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_pf_policy);
-
debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
&_active_count_fops);
}
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b32cdae..bf173a7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -134,34 +134,32 @@
/**
* adreno_drawctxt_create - create a new adreno draw context
- * @device - KGSL device to create the context on
- * @pagetable - Pagetable for the context
- * @context- Generic KGSL context structure
- * @flags - flags for the context (passed from user space)
+ * @dev_priv: the owner of the context
+ * @flags: flags for the context (passed from user space)
*
- * Create a new draw context for the 3D core. Return 0 on success,
- * or error code on failure.
+ * Create and return a new draw context for the 3D core.
*/
-int adreno_drawctxt_create(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable,
- struct kgsl_context *context, uint32_t *flags)
+struct kgsl_context *
+adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
+ uint32_t *flags)
{
struct adreno_context *drawctxt;
+ struct kgsl_device *device = dev_priv->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int ret;
drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
-
if (drawctxt == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- drawctxt->pid = task_pid_nr(current);
- strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
- drawctxt->pagetable = pagetable;
+ ret = kgsl_context_init(dev_priv, &drawctxt->base);
+ if (ret != 0) {
+ kfree(drawctxt);
+ return ERR_PTR(ret);
+ }
+
drawctxt->bin_base_offset = 0;
- drawctxt->id = context->id;
- rb->timestamp[context->id] = 0;
+ drawctxt->timestamp = 0;
*flags &= (KGSL_CONTEXT_PREAMBLE |
KGSL_CONTEXT_NO_GMEM_ALLOC |
@@ -192,50 +190,47 @@
drawctxt->type =
(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
- drawctxt->dev_priv = context->dev_priv;
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
if (ret)
goto err;
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ref_wait_ts),
KGSL_INIT_REFTIMESTAMP);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ts_cmp_enable),
+ 0);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
+ 0);
kgsl_sharedmem_writel(device, &device->memstore,
- KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
+ KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
+ 0);
- context->devctxt = drawctxt;
- return 0;
+ return &drawctxt->base;
err:
- kfree(drawctxt);
- return ret;
+ kgsl_context_put(&drawctxt->base);
+ return ERR_PTR(ret);
}
/**
- * adreno_drawctxt_destroy - destroy a draw context
- * @device - KGSL device that owns the context
- * @context- Generic KGSL context container for the context
+ * adreno_drawctxt_detach(): detach a context from the GPU
+ * @context: Generic KGSL context container for the context
*
- * Destroy an existing context. Return 0 on success or error
- * code on failure.
*/
-
-/* destroy a drawing context */
-
-void adreno_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context)
+void adreno_drawctxt_detach(struct kgsl_context *context)
{
- struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
struct adreno_context *drawctxt;
- if (context == NULL || context->devctxt == NULL)
+ if (context == NULL)
return;
- drawctxt = context->devctxt;
+ device = context->device;
+ adreno_dev = ADRENO_DEVICE(device);
+ drawctxt = ADRENO_CONTEXT(context);
/* deactivate context */
if (adreno_dev->drawctxt_active == drawctxt) {
/* no need to save GMEM or shader, the context is
@@ -256,9 +251,17 @@
kgsl_sharedmem_free(&drawctxt->gpustate);
kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
+}
+
+void adreno_drawctxt_destroy(struct kgsl_context *context)
+{
+ struct adreno_context *drawctxt;
+ if (context == NULL)
+ return;
+
+ drawctxt = ADRENO_CONTEXT(context);
kfree(drawctxt);
- context->devctxt = NULL;
}
/**
@@ -274,10 +277,12 @@
struct kgsl_context *context,
unsigned int offset)
{
- struct adreno_context *drawctxt = context->devctxt;
+ struct adreno_context *drawctxt;
- if (drawctxt)
- drawctxt->bin_base_offset = offset;
+ if (context == NULL)
+ return;
+ drawctxt = ADRENO_CONTEXT(context);
+ drawctxt->bin_base_offset = offset;
}
/**
@@ -316,12 +321,22 @@
KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
adreno_dev->drawctxt_active ?
- adreno_dev->drawctxt_active->id : 0,
- drawctxt ? drawctxt->id : 0, flags);
+ adreno_dev->drawctxt_active->base.id : 0,
+ drawctxt ? drawctxt->base.id : 0, flags);
/* Save the old context */
adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
+ /* Put the old instance of the active drawctxt */
+ if (adreno_dev->drawctxt_active) {
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+ adreno_dev->drawctxt_active = NULL;
+ }
+
+ /* Get a refcount to the new instance */
+ if (drawctxt)
+ _kgsl_context_get(&drawctxt->base);
+
/* Set the new context */
adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
adreno_dev->drawctxt_active = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 2b8e600..88d1b8c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -13,8 +13,6 @@
#ifndef __ADRENO_DRAWCTXT_H
#define __ADRENO_DRAWCTXT_H
-#include <linux/sched.h>
-
#include "adreno_pm4types.h"
#include "a2xx_reg.h"
@@ -96,15 +94,11 @@
};
struct adreno_context {
- pid_t pid;
- char pid_name[TASK_COMM_LEN];
- unsigned int id;
+ struct kgsl_context base;
unsigned int ib_gpu_time_used;
+ unsigned int timestamp;
uint32_t flags;
- uint32_t pagefault;
- unsigned long pagefault_ts;
unsigned int type;
- struct kgsl_pagetable *pagetable;
struct kgsl_memdesc gpustate;
unsigned int reg_restore[3];
unsigned int shader_save[3];
@@ -131,16 +125,15 @@
struct kgsl_memdesc constant_load_commands[3];
struct kgsl_memdesc cond_execs[4];
struct kgsl_memdesc hlsqcontrol_restore_commands[1];
- struct kgsl_device_private *dev_priv;
};
-int adreno_drawctxt_create(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable,
- struct kgsl_context *context,
+
+struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
uint32_t *flags);
-void adreno_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context);
+void adreno_drawctxt_detach(struct kgsl_context *context);
+
+void adreno_drawctxt_destroy(struct kgsl_context *context);
void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6c05b5..999b782 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -138,7 +138,7 @@
if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
KGSL_CTXT_WARN(rb->device,
"Context %p caused a gpu hang. Will not accept commands for context %d\n",
- context, context->id);
+ context, context->base.id);
return -EDEADLK;
}
wait_time = jiffies + wait_timeout;
@@ -575,6 +575,8 @@
/* overlay structure on memptrs memory */
rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
+ rb->global_ts = 0;
+
return 0;
}
@@ -594,11 +596,11 @@
memset(rb, 0, sizeof(struct adreno_ringbuffer));
}
-static uint32_t
+static int
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
struct adreno_context *context,
unsigned int flags, unsigned int *cmds,
- int sizedwords, uint32_t timestamp)
+ int sizedwords)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
unsigned int *ringcmds;
@@ -607,6 +609,7 @@
unsigned int rcmd_gpu;
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
unsigned int gpuaddr = rb->device->memstore.gpuaddr;
+ unsigned int timestamp;
/*
* if the context was not created with per context timestamp
@@ -616,20 +619,7 @@
*/
if ((context && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) &&
!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
- context_id = context->id;
-
- if ((context && (context->flags & CTXT_FLAGS_USER_GENERATED_TS)) &&
- !(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
- if (timestamp_cmp(rb->timestamp[context_id],
- timestamp) >= 0) {
- KGSL_DRV_ERR(rb->device,
- "Invalid user generated ts <%d:0x%x>, "
- "less than last issued ts <%d:0x%x>\n",
- context_id, timestamp, context_id,
- rb->timestamp[context_id]);
- return -ERANGE;
- }
- }
+ context_id = context->base.id;
/* reserve space to temporarily turn off protected mode
* error checking if needed
@@ -669,13 +659,8 @@
total_sizedwords += 2;
ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
- if (!ringcmds) {
- /*
- * We could not allocate space in ringbuffer, just return the
- * last timestamp
- */
- return rb->timestamp[context_id];
- }
+ if (!ringcmds)
+ return -ENOSPC;
rcmd_gpu = rb->buffer_desc.gpuaddr
+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -690,26 +675,19 @@
}
/* always increment the global timestamp. once. */
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+ rb->global_ts++;
- /*
- * If global timestamp then we are not using per context ts for
- * this submission
- */
- if (context_id != KGSL_MEMSTORE_GLOBAL) {
- if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
- rb->timestamp[context_id] = timestamp;
- else
- rb->timestamp[context_id]++;
- }
- timestamp = rb->timestamp[context_id];
+ if (KGSL_MEMSTORE_GLOBAL != context_id)
+ timestamp = context->timestamp;
+ else
+ timestamp = rb->global_ts;
/* scratchpad ts for fault tolerance */
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type0_packet(adreno_getreg(adreno_dev,
ADRENO_REG_CP_TIMESTAMP), 1));
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ rb->global_ts);
/* start-of-pipeline timestamp */
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
@@ -781,7 +759,7 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp)));
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ rb->global_ts);
}
if (adreno_is_a20x(adreno_dev)) {
@@ -857,7 +835,7 @@
adreno_ringbuffer_submit(rb);
- return timestamp;
+ return 0;
}
unsigned int
@@ -877,7 +855,7 @@
flags |= KGSL_CMD_FLAGS_INTERNAL_ISSUE;
return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds,
- sizedwords, 0);
+ sizedwords);
}
static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -1097,12 +1075,9 @@
ret = -EINVAL;
goto done;
}
- drawctxt = context->devctxt;
+ drawctxt = ADRENO_CONTEXT(context);
if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
- KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
- " will not accept commands for context %d\n",
- drawctxt->pid_name, drawctxt->id);
ret = -EDEADLK;
goto done;
}
@@ -1116,10 +1091,6 @@
start_index = 1;
if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
- KGSL_CTXT_ERR(device,
- "proc %s triggered fault tolerance"
- " skipping commands for context till EOF %d\n",
- drawctxt->pid_name, drawctxt->id);
if (flags & KGSL_CMD_FLAGS_EOF)
drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
if (start_index)
@@ -1172,10 +1143,30 @@
adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
- *timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
+ if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+ if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
+ KGSL_DRV_ERR(device,
+ "Invalid user generated ts <%d:0x%x>, "
+ "less than last issued ts <%d:0x%x>\n",
+ context->id, *timestamp, context->id,
+ drawctxt->timestamp);
+ return -ERANGE;
+ }
+ drawctxt->timestamp = *timestamp;
+ } else
+ drawctxt->timestamp++;
+
+ ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
drawctxt,
(flags & KGSL_CMD_FLAGS_EOF),
- &link[0], (cmds - link), *timestamp);
+ &link[0], (cmds - link));
+ if (ret)
+ goto done;
+
+ if (drawctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+ *timestamp = drawctxt->timestamp;
+ else
+ *timestamp = adreno_dev->ringbuffer.global_ts;
#ifdef CONFIG_MSM_KGSL_CFF_DUMP
/*
@@ -1282,7 +1273,7 @@
k_ctxt = kgsl_context_get(device, ft_data->context_id);
if (k_ctxt) {
- a_ctxt = k_ctxt->devctxt;
+ a_ctxt = ADRENO_CONTEXT(k_ctxt);
if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
_turn_preamble_on_for_ib_seq(rb, rb_rptr);
kgsl_context_put(k_ctxt);
@@ -1319,7 +1310,7 @@
k_ctxt = kgsl_context_get(rb->device, val2);
if (k_ctxt) {
- a_ctxt = k_ctxt->devctxt;
+ a_ctxt = ADRENO_CONTEXT(k_ctxt);
/* If we are changing to a good context and were not
* copying commands then copy over commands to the good
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e9fb050..9634e32 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -55,7 +55,7 @@
unsigned int wptr; /* write pointer offset in dwords from baseaddr */
- unsigned int timestamp[KGSL_MEMSTORE_MAX];
+ unsigned int global_ts;
};
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4c1ef54..966e035 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -448,20 +448,24 @@
entry->priv = NULL;
}
-/* Allocate a new context id */
-
-static struct kgsl_context *
-kgsl_create_context(struct kgsl_device_private *dev_priv)
+/**
+ * kgsl_context_init() - helper to initialize kgsl_context members
+ * @dev_priv: the owner of the context
+ * @context: the newly created context struct, should be allocated by
+ * the device specific drawctxt_create function.
+ *
+ * This is a helper function for the device specific drawctxt_create
+ * function to initialize the common members of its context struct.
+ * If this function succeeds, reference counting is active in the context
+ * struct and the caller should kgsl_context_put() it on error.
+ * If it fails, the caller should just free the context structure
+ * it passed in.
+ */
+int kgsl_context_init(struct kgsl_device_private *dev_priv,
+ struct kgsl_context *context)
{
+ int ret = 0, id;
struct kgsl_device *device = dev_priv->device;
- struct kgsl_context *context;
- int ret, id = 0;
-
- context = kzalloc(sizeof(*context), GFP_KERNEL);
-
- if (context == NULL)
- return ERR_PTR(-ENOMEM);
-
while (1) {
if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
@@ -480,30 +484,26 @@
}
if (ret)
- goto func_end;
+ goto fail;
/* MAX - 1, there is one memdesc in memstore for device info */
if (id >= KGSL_MEMSTORE_MAX) {
KGSL_DRV_INFO(device, "cannot have more than %d "
"ctxts due to memstore limitation\n",
KGSL_MEMSTORE_MAX);
- write_lock(&device->context_lock);
- idr_remove(&device->context_idr, id);
- write_unlock(&device->context_lock);
ret = -ENOSPC;
- goto func_end;
+ goto fail_free_id;
}
kref_init(&context->refcount);
- context->dev_priv = dev_priv;
+ context->device = dev_priv->device;
+ context->pagetable = dev_priv->process_priv->pagetable;
+
+ context->pid = dev_priv->process_priv->pid;
ret = kgsl_sync_timeline_create(context);
- if (ret) {
- write_lock(&device->context_lock);
- idr_remove(&dev_priv->device->context_idr, id);
- write_unlock(&device->context_lock);
- goto func_end;
- }
+ if (ret)
+ goto fail_free_id;
/* Initialize the pending event list */
INIT_LIST_HEAD(&context->events);
@@ -518,15 +518,15 @@
*/
INIT_LIST_HEAD(&context->events_list);
-
-func_end:
- if (ret) {
- kfree(context);
- return ERR_PTR(ret);
- }
-
- return context;
+ return 0;
+fail_free_id:
+ write_lock(&device->context_lock);
+ idr_remove(&dev_priv->device->context_idr, id);
+ write_unlock(&device->context_lock);
+fail:
+ return ret;
}
+EXPORT_SYMBOL(kgsl_context_init);
/**
* kgsl_context_detach - Release the "master" context reference
@@ -536,37 +536,36 @@
* has requested for it to be destroyed. The context itself may
* exist a bit longer until its reference count goes to zero.
* Other code referencing the context can detect that it has been
- * detached because the context id will be set to KGSL_CONTEXT_INVALID.
+ * detached by checking the KGSL_CONTEXT_DETACHED bit in
+ * context->priv.
*/
void
kgsl_context_detach(struct kgsl_context *context)
{
- int id;
struct kgsl_device *device;
if (context == NULL)
return;
- device = context->dev_priv->device;
- trace_kgsl_context_detach(device, context);
- id = context->id;
- if (device->ftbl->drawctxt_destroy)
- device->ftbl->drawctxt_destroy(device, context);
- /*device specific drawctxt_destroy MUST clean up devctxt */
- BUG_ON(context->devctxt);
+ device = context->device;
+
+ /*
+ * Mark the context as detached to keep others from using
+ * the context before it gets fully removed, and to make sure
+ * we don't try to detach twice.
+ */
+ if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+ return;
+
+ trace_kgsl_context_detach(device, context);
+
+ device->ftbl->drawctxt_detach(context);
/*
* Cancel events after the device-specific context is
- * destroyed, to avoid possibly freeing memory while
+ * detached, to avoid possibly freeing memory while
* it is still in use by the GPU.
*/
kgsl_cancel_events_ctxt(device, context);
- write_lock(&device->context_lock);
- context->id = KGSL_CONTEXT_INVALID;
- idr_remove(&device->context_idr, id);
- write_unlock(&device->context_lock);
-
- context->dev_priv = NULL;
-
kgsl_context_put(context);
}
@@ -575,8 +574,19 @@
{
struct kgsl_context *context = container_of(kref, struct kgsl_context,
refcount);
+ struct kgsl_device *device = context->device;
+
+ trace_kgsl_context_destroy(device, context);
+
+ write_lock(&device->context_lock);
+ if (context->id != KGSL_CONTEXT_INVALID) {
+ idr_remove(&device->context_idr, context->id);
+ context->id = KGSL_CONTEXT_INVALID;
+ }
+ write_unlock(&device->context_lock);
kgsl_sync_timeline_destroy(context);
- kfree(context);
+
+ device->ftbl->drawctxt_destroy(context);
}
struct kgsl_device *kgsl_get_device(int dev_idx)
@@ -975,7 +985,7 @@
if (context == NULL)
break;
- if (context->dev_priv == dev_priv)
+ if (context->pid == private->pid)
kgsl_context_detach(context);
next = next + 1;
@@ -1623,27 +1633,16 @@
int result = 0;
struct kgsl_drawctxt_create *param = data;
struct kgsl_context *context = NULL;
+ struct kgsl_device *device = dev_priv->device;
- context = kgsl_create_context(dev_priv);
-
+ context = device->ftbl->drawctxt_create(dev_priv, ¶m->flags);
if (IS_ERR(context)) {
result = PTR_ERR(context);
goto done;
}
-
- if (dev_priv->device->ftbl->drawctxt_create) {
- result = dev_priv->device->ftbl->drawctxt_create(
- dev_priv->device, dev_priv->process_priv->pagetable,
- context, ¶m->flags);
- if (result)
- goto done;
- }
trace_kgsl_context_create(dev_priv->device, context, param->flags);
param->drawctxt_id = context->id;
done:
- if (result && !IS_ERR(context))
- kgsl_context_detach(context);
-
return result;
}
@@ -2600,7 +2599,7 @@
if (!entry)
return -EINVAL;
- kgsl_cffdump_syncmem(dev_priv, &entry->memdesc, param->gpuaddr,
+ kgsl_cffdump_syncmem(dev_priv->device, &entry->memdesc, param->gpuaddr,
param->len, true);
kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index b07a1cad..43bcc30 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -410,29 +410,19 @@
cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
}
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
- struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
- bool clean_cache)
+void kgsl_cffdump_syncmem(struct kgsl_device *device,
+ struct kgsl_memdesc *memdesc, uint gpuaddr,
+ uint sizebytes, bool clean_cache)
{
- struct kgsl_device *device = dev_priv->device;
const void *src;
if (!device->cff_dump_enable)
return;
+ BUG_ON(memdesc == NULL);
+
total_syncmem += sizebytes;
- if (memdesc == NULL) {
- struct kgsl_mem_entry *entry;
- entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
- gpuaddr, sizebytes);
- if (entry == NULL) {
- KGSL_CORE_ERR("did not find mapping "
- "for gpuaddr: 0x%08x\n", gpuaddr);
- return;
- }
- memdesc = &entry->memdesc;
- }
src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
if (memdesc->hostptr == NULL) {
KGSL_CORE_ERR(
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index ab5a345..2852e0f 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -28,7 +28,7 @@
void kgsl_cffdump_destroy(void);
void kgsl_cffdump_open(struct kgsl_device *device);
void kgsl_cffdump_close(struct kgsl_device *device);
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+void kgsl_cffdump_syncmem(struct kgsl_device *,
struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache);
void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
@@ -74,7 +74,7 @@
return;
}
-static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+static inline void kgsl_cffdump_syncmem(struct kgsl_device *device,
struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache)
{
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0e40db..1f8bcbe 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
#include <linux/idr.h>
#include <linux/pm_qos.h>
+#include <linux/sched.h>
#include "kgsl.h"
#include "kgsl_mmu.h"
@@ -103,11 +104,10 @@
calling the hook */
void (*setstate) (struct kgsl_device *device, unsigned int context_id,
uint32_t flags);
- int (*drawctxt_create) (struct kgsl_device *device,
- struct kgsl_pagetable *pagetable, struct kgsl_context *context,
- uint32_t *flags);
- void (*drawctxt_destroy) (struct kgsl_device *device,
- struct kgsl_context *context);
+ struct kgsl_context *(*drawctxt_create) (struct kgsl_device_private *,
+ uint32_t *flags);
+ void (*drawctxt_detach) (struct kgsl_context *context);
+ void (*drawctxt_destroy) (struct kgsl_context *context);
long (*ioctl) (struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
int (*setproperty) (struct kgsl_device *device,
@@ -254,31 +254,44 @@
.ver_minor = DRIVER_VERSION_MINOR
+/* bits for struct kgsl_context.priv */
+/* the context has been destroyed by userspace and is no longer using the gpu */
+#define KGSL_CONTEXT_DETACHED 0
+/* the context has caused a pagefault */
+#define KGSL_CONTEXT_PAGEFAULT 1
+
/**
* struct kgsl_context - Master structure for a KGSL context object
- * @refcount - kref object for reference counting the context
- * @id - integer identifier for the context
- * @dev_priv - pointer to the owning device instance
- * @devctxt - pointer to the device specific context information
- * @reset_status - status indication whether a gpu reset occured and whether
+ * @refcount: kref object for reference counting the context
+ * @id: integer identifier for the context
+ * @priv: in-kernel context flags, use KGSL_CONTEXT_* values
+ * @dev_priv: pointer to the owning device instance
+ * @reset_status: status indication whether a gpu reset occured and whether
* this context was responsible for causing it
- * @wait_on_invalid_ts - flag indicating if this context has tried to wait on a
+ * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
* bad timestamp
- * @timeline - sync timeline used to create fences that can be signaled when a
+ * @timeline: sync timeline used to create fences that can be signaled when a
* sync_pt timestamp expires
- * @events - list head of pending events for this context
- * @events_list - list node for the list of all contexts that have pending events
+ * @events: list head of pending events for this context
+ * @events_list: list node for the list of all contexts that have pending events
+ * @pid: process that owns this context.
+ * @pagefault: flag set if this context caused a pagefault.
+ * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
+ * is set.
*/
struct kgsl_context {
struct kref refcount;
uint32_t id;
- struct kgsl_device_private *dev_priv;
- void *devctxt;
+ pid_t pid;
+ unsigned long priv;
+ struct kgsl_device *device;
+ struct kgsl_pagetable *pagetable;
unsigned int reset_status;
bool wait_on_invalid_ts;
struct sync_timeline *timeline;
struct list_head events;
struct list_head events_list;
+ unsigned int pagefault_ts;
};
struct kgsl_process_private {
@@ -429,6 +442,9 @@
void kgsl_context_destroy(struct kref *kref);
+int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context
+ *context);
+
/**
* kgsl_context_put() - Release context reference count
* @context: Pointer to the KGSL context to be released
@@ -442,6 +458,22 @@
if (context)
kref_put(&context->refcount, kgsl_context_destroy);
}
+
+/**
+ * kgsl_context_detached() - check if a context is detached
+ * @context: the context
+ *
+ * Check if a context has been destroyed by userspace and is only waiting
+ * for reference counts to go away. This check is used to weed out
+ * contexts that shouldn't use the gpu so NULL is considered detached.
+ */
+static inline bool kgsl_context_detached(struct kgsl_context *context)
+{
+ return (context == NULL || test_bit(KGSL_CONTEXT_DETACHED,
+ &context->priv));
+}
+
+
/**
* kgsl_context_get() - get a pointer to a KGSL context
* @device: Pointer to the KGSL device that owns the context
@@ -462,7 +494,10 @@
context = idr_find(&device->context_idr, id);
- if (context)
+ /* Don't return a context that has been detached */
+ if (kgsl_context_detached(context))
+ context = NULL;
+ else
kref_get(&context->refcount);
read_unlock(&device->context_lock);
@@ -471,6 +506,20 @@
}
/**
+* _kgsl_context_get() - lightweight function to just increment the ref count
+* @context: Pointer to the KGSL context
+*
+* Get a reference to the specified KGSL context structure. This is a
+* lightweight way to just increase the refcount on a known context rather than
+* walking through kgsl_context_get and searching the iterator
+*/
+static inline void _kgsl_context_get(struct kgsl_context *context)
+{
+ if (context)
+ kref_get(&context->refcount);
+}
+
+/**
* kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
* process
* @dev_priv: Pointer to the process struct
@@ -489,8 +538,8 @@
context = kgsl_context_get(dev_priv->device, id);
- /* Verify that the context belongs to the dev_priv instance */
- if (context && context->dev_priv != dev_priv) {
+ /* Verify that the context belongs to current calling process. */
+ if (context != NULL && context->pid != dev_priv->process_priv->pid) {
kgsl_context_put(context);
return NULL;
}
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 0b75175..40974b0 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -147,7 +147,7 @@
* Increment the refcount to avoid freeing the context while
* cancelling its events
*/
- kref_get(&context->refcount);
+ _kgsl_context_get(context);
/* Remove ourselves from the master pending list */
list_del_init(&context->events_list);
@@ -324,7 +324,7 @@
* Increment the refcount to make sure that the list_del_init
* is called with a valid context's list
*/
- kref_get(&context->refcount);
+ _kgsl_context_get(context);
/*
* If kgsl_timestamp_expired_context returns 0 then it no longer
* has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 7af4575..14aae9f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -327,7 +327,7 @@
unsigned int no_page_fault_log = 0;
unsigned int curr_context_id = 0;
unsigned int curr_global_ts = 0;
- static struct kgsl_context *context;
+ struct kgsl_context *context;
ret = get_iommu_unit(dev, &mmu, &iommu_unit);
if (ret)
@@ -401,23 +401,16 @@
context = kgsl_context_get(device, curr_context_id);
if (context != NULL) {
- struct adreno_context *drawctxt = context->devctxt;
-
kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
- /*
- * Store pagefault's timestamp in adreno context,
- * this information will be used in GFT
- */
-
- if (drawctxt != NULL) {
- drawctxt->pagefault = 1;
- drawctxt->pagefault_ts = curr_global_ts;
- }
+ /* save pagefault timestamp for GFT */
+ set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
+ context->pagefault_ts = curr_global_ts;
kgsl_context_put(context);
+ context = NULL;
}
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5e6d24b..20391be 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1214,6 +1214,11 @@
}
}
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device)
+{
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0);
+}
/**
* kgsl_pre_hwaccess - Enforce preconditions for touching registers
@@ -1230,7 +1235,7 @@
/* In order to touch a register you must hold the device mutex...*/
BUG_ON(!mutex_is_locked(&device->mutex));
/* and have the clock on! */
- BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
+ BUG_ON(!kgsl_pwrctrl_isenabled(device));
}
EXPORT_SYMBOL(kgsl_pre_hwaccess);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 3bf65ee..b7d9226 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -110,6 +110,8 @@
void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
void kgsl_pwrctrl_enable(struct kgsl_device *device);
void kgsl_pwrctrl_disable(struct kgsl_device *device);
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
+
static inline unsigned long kgsl_get_clkrate(struct clk *clk)
{
return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 35f24d9..6094e04 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -109,7 +109,7 @@
struct kgsl_device *device;
if (context)
- device = context->dev_priv->device;
+ device = context->device;
else
device = (struct kgsl_device *)data;
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 1853996c..62ecdeb 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -239,7 +239,7 @@
char ktimeline_name[sizeof(context->timeline->name)] = {};
snprintf(ktimeline_name, sizeof(ktimeline_name),
"%s_%.15s(%d)-%.15s(%d)-%d",
- context->dev_priv->device->name,
+ context->device->name,
current->group_leader->comm, current->group_leader->pid,
current->comm, current->pid, context->id);
@@ -250,7 +250,7 @@
ktimeline = (struct kgsl_sync_timeline *) context->timeline;
ktimeline->last_timestamp = 0;
- ktimeline->device = context->dev_priv->device;
+ ktimeline->device = context->device;
ktimeline->context_id = context->id;
return 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index abb7c35..5981163 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -678,6 +678,28 @@
)
);
+TRACE_EVENT(kgsl_context_destroy,
+
+ TP_PROTO(struct kgsl_device *device, struct kgsl_context *context),
+
+ TP_ARGS(device, context),
+
+ TP_STRUCT__entry(
+ __string(device_name, device->name)
+ __field(unsigned int, id)
+ ),
+
+ TP_fast_assign(
+ __assign_str(device_name, device->name);
+ __entry->id = context->id;
+ ),
+
+ TP_printk(
+ "d_name=%s ctx=%u",
+ __get_str(device_name), __entry->id
+ )
+);
+
TRACE_EVENT(kgsl_mmu_pagefault,
TP_PROTO(struct kgsl_device *device, unsigned int page,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cc1819d..883417f 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -859,11 +859,30 @@
return status;
}
-static void
-z180_drawctxt_destroy(struct kgsl_device *device,
- struct kgsl_context *context)
+struct kgsl_context *
+z180_drawctxt_create(struct kgsl_device_private *dev_priv,
+ uint32_t *flags)
{
- struct z180_device *z180_dev = Z180_DEVICE(device);
+ int ret;
+ struct kgsl_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+ if (context == NULL)
+ return ERR_PTR(-ENOMEM);
+ ret = kgsl_context_init(dev_priv, context);
+ if (ret != 0) {
+ kfree(context);
+ return ERR_PTR(ret);
+ }
+ return context;
+}
+
+static void
+z180_drawctxt_detach(struct kgsl_context *context)
+{
+ struct kgsl_device *device;
+ struct z180_device *z180_dev;
+
+ device = context->device;
+ z180_dev = Z180_DEVICE(device);
z180_idle(device);
@@ -875,6 +894,12 @@
}
}
+static void
+z180_drawctxt_destroy(struct kgsl_context *context)
+{
+ kfree(context);
+}
+
static void z180_power_stats(struct kgsl_device *device,
struct kgsl_power_stats *stats)
{
@@ -941,7 +966,8 @@
.gpuid = z180_gpuid,
.irq_handler = z180_irq_handler,
/* Optional functions */
- .drawctxt_create = NULL,
+ .drawctxt_create = z180_drawctxt_create,
+ .drawctxt_detach = z180_drawctxt_detach,
.drawctxt_destroy = z180_drawctxt_destroy,
.ioctl = NULL,
.postmortem_dump = z180_dump,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index a587ed2..a309ceb 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -65,6 +65,8 @@
#define EPM_ADC_MILLI_VOLTS_SOURCE 4750
#define EPM_ADC_SCALE_FACTOR 64
#define GPIO_EPM_GLOBAL_ENABLE 86
+#define GPIO_EPM_MARKER1 85
+#define GPIO_EPM_MARKER2 96
#define EPM_ADC_CONVERSION_TIME_MIN 50000
#define EPM_ADC_CONVERSION_TIME_MAX 51000
/* PSoc Commands */
@@ -715,6 +717,56 @@
return 0;
}
+static int epm_set_marker1(struct epm_marker_level *marker_init)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_EPM_MARKER1, "EPM_MARKER1");
+ if (!rc) {
+ gpio_direction_output(GPIO_EPM_MARKER1, 1);
+ } else {
+ pr_err("%s: Configure MARKER1 GPIO Failed\n",
+ __func__);
+ return rc;
+ }
+
+ gpio_set_value(GPIO_EPM_MARKER1, marker_init->level);
+
+ return 0;
+}
+
+static int epm_set_marker2(struct epm_marker_level *marker_init)
+{
+ int rc = 0;
+
+ rc = gpio_request(GPIO_EPM_MARKER2, "EPM_MARKER2");
+ if (!rc) {
+ gpio_direction_output(GPIO_EPM_MARKER2, 1);
+ } else {
+ pr_err("%s: Configure MARKER2 GPIO Failed\n",
+ __func__);
+ return rc;
+ }
+
+ gpio_set_value(GPIO_EPM_MARKER2, marker_init->level);
+
+ return 0;
+}
+
+static int epm_marker1_release(void)
+{
+ gpio_free(GPIO_EPM_MARKER1);
+
+ return 0;
+}
+
+static int epm_marker2_release(void)
+{
+ gpio_free(GPIO_EPM_MARKER2);
+
+ return 0;
+}
+
static int epm_psoc_init(struct epm_adc_drv *epm_adc,
struct epm_psoc_init_resp *init_resp)
{
@@ -1296,6 +1348,58 @@
return -EFAULT;
break;
}
+ case EPM_MARKER1_REQUEST:
+ {
+ struct epm_marker_level marker_init;
+ uint32_t result;
+
+ if (copy_from_user(&marker_init, (void __user *)arg,
+ sizeof(struct epm_marker_level)))
+ return -EFAULT;
+
+ result = epm_set_marker1(&marker_init);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER2_REQUEST:
+ {
+ struct epm_marker_level marker_init;
+ uint32_t result;
+
+ if (copy_from_user(&marker_init, (void __user *)arg,
+ sizeof(struct epm_marker_level)))
+ return -EFAULT;
+
+ result = epm_set_marker2(&marker_init);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER1_RELEASE:
+ {
+ uint32_t result;
+ result = epm_marker1_release();
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
+ case EPM_MARKER2_RELEASE:
+ {
+ uint32_t result;
+ result = epm_marker2_release();
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
case EPM_PSOC_ADC_INIT:
{
struct epm_psoc_init_resp psoc_init;
@@ -1312,11 +1416,29 @@
return -EINVAL;
}
+ if (!rc) {
+ rc = epm_adc_psoc_gpio_init(true);
+ if (rc) {
+ pr_err("GPIO init failed\n");
+ return -EINVAL;
+ }
+ }
+
if (copy_to_user((void __user *)arg, &psoc_init,
sizeof(struct epm_psoc_init_resp)))
return -EFAULT;
break;
}
+ case EPM_PSOC_ADC_DEINIT:
+ {
+ uint32_t result;
+ result = epm_adc_psoc_gpio_init(false);
+
+ if (copy_to_user((void __user *)arg, &result,
+ sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ }
case EPM_PSOC_ADC_CHANNEL_ENABLE:
case EPM_PSOC_ADC_CHANNEL_DISABLE:
{
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 9570327..27818b4 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -530,6 +530,9 @@
uint16_t raw_data;
uint32_t mode_sel = 0;
+ if (!iadc || !iadc->iadc_initialized)
+ return -EPROBE_DEFER;
+
mutex_lock(&iadc->adc->adc_lock);
rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
@@ -541,11 +544,22 @@
iadc->adc->calib.gain_raw = raw_data;
- rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+ if (iadc->external_rsense) {
+ /* external offset calculation */
+ rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
&raw_data, mode_sel);
- if (rc < 0) {
- pr_err("qpnp adc result read failed with %d\n", rc);
- goto fail;
+ if (rc < 0) {
+ pr_err("qpnp adc result read failed with %d\n", rc);
+ goto fail;
+ }
+ } else {
+ /* internal offset calculation */
+ rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
+ &raw_data, mode_sel);
+ if (rc < 0) {
+ pr_err("qpnp adc result read failed with %d\n", rc);
+ goto fail;
+ }
}
iadc->adc->calib.offset_raw = raw_data;
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 6e8c809..982e4d4 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1343,3 +1343,17 @@
pkt->trigger_type = get_hfi_ssr_type(type);
return 0;
}
+
+int create_pkt_cmd_sys_image_version(
+ struct hfi_cmd_sys_get_property_packet *pkt)
+{
+ if (!pkt) {
+ dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt);
+ return -EINVAL;
+ }
+ pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet);
+ pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+ pkt->num_properties = 1;
+ pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+ return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index df93906..20619c0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -89,4 +89,7 @@
int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
struct hfi_cmd_sys_test_ssr_packet *pkt);
+
+int create_pkt_cmd_sys_image_version(
+ struct hfi_cmd_sys_get_property_packet *pkt);
#endif
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 859345f..44105ad 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/interrupt.h>
+#include <mach/msm_smem.h>
#include "vidc_hfi_helper.h"
#include "vidc_hfi_io.h"
#include "msm_vidc_debug.h"
@@ -1089,6 +1090,44 @@
callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
}
+void hfi_process_sys_property_info(
+ struct hfi_property_sys_image_version_info_type *pkt)
+{
+ int i = 0;
+ u32 smem_block_size = 0;
+ u8 *smem_table_ptr;
+ char version[256];
+ const u32 smem_image_index_venus = 14 * 128;
+
+ if (!pkt || !pkt->string_size) {
+ dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+ return;
+ }
+
+ if (pkt->string_size < sizeof(version)) {
+ /*
+ * The version string returned by firmware includes null
+ * characters at the start and in between. Replace the null
+ * characters with space, to print the version info.
+ */
+ for (i = 0; i < pkt->string_size; i++) {
+ if (pkt->str_image_version[i] != '\0')
+ version[i] = pkt->str_image_version[i];
+ else
+ version[i] = ' ';
+ }
+ version[i] = '\0';
+ dprintk(VIDC_INFO, "F/W version: %s\n", version);
+ }
+
+ smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+ &smem_block_size);
+ if (smem_table_ptr &&
+ ((smem_image_index_venus + 128) <= smem_block_size))
+ memcpy(smem_table_ptr + smem_image_index_venus,
+ (u8 *)pkt->str_image_version, 128);
+}
+
u32 hfi_process_msg_packet(
msm_vidc_callback callback, u32 device_id,
struct vidc_hal_msg_pkt_hdr *msg_hdr)
@@ -1121,6 +1160,11 @@
(struct hfi_msg_sys_session_init_done_packet *)
msg_hdr);
break;
+ case HFI_MSG_SYS_PROPERTY_INFO:
+ hfi_process_sys_property_info(
+ (struct hfi_property_sys_image_version_info_type *)
+ msg_hdr);
+ break;
case HFI_MSG_SYS_SESSION_END_DONE:
hfi_process_session_end_done(callback, device_id,
(struct hfi_msg_sys_session_end_done_packet *)
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7547464..7039929 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -934,6 +934,8 @@
struct hal_buffer_requirements *bufreq;
int extra_idx = 0;
struct hfi_device *hdev;
+ struct hal_buffer_count_actual new_buf_count;
+ enum hal_property property_id;
if (!q || !num_buffers || !num_planes
|| !sizes || !q->drv_priv) {
dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -960,6 +962,16 @@
i, inst->capability.height.max,
inst->capability.width.max);
}
+ property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+ new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+ new_buf_count.buffer_count_actual = *num_buffers;
+ rc = call_hfi_op(hdev, session_set_property,
+ inst->session, property_id, &new_buf_count);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to set new buffer count(%d) on FW, err: %d\n",
+ new_buf_count.buffer_count_actual, rc);
+ }
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
@@ -987,15 +999,11 @@
}
if (*num_buffers && *num_buffers >
bufreq->buffer_count_actual) {
- struct hal_buffer_count_actual new_buf_count;
- enum hal_property property_id =
- HAL_PARAM_BUFFER_COUNT_ACTUAL;
-
+ property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
new_buf_count.buffer_count_actual = *num_buffers;
rc = call_hfi_op(hdev, session_set_property,
inst->session, property_id, &new_buf_count);
-
}
if (bufreq->buffer_count_actual > *num_buffers)
*num_buffers = bufreq->buffer_count_actual;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 28ea41a..8ee9c32 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1030,6 +1030,7 @@
static int venus_hfi_core_init(void *device)
{
struct hfi_cmd_sys_init_packet pkt;
+ struct hfi_cmd_sys_get_property_packet version_pkt;
int rc = 0;
struct venus_hfi_device *dev;
@@ -1088,6 +1089,10 @@
rc = -ENOTEMPTY;
goto err_core_init;
}
+ rc = create_pkt_cmd_sys_image_version(&version_pkt);
+ if (rc || venus_hfi_iface_cmdq_write(dev, &version_pkt))
+ dprintk(VIDC_WARN, "Failed to send image version pkt to f/w");
+
return rc;
err_core_init:
disable_irq_nosync(dev->hal_data->irq);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index bb72da7..ac6cb02 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -335,7 +335,6 @@
#define HFI_MSG_SYS_OX_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
#define HFI_MSG_SYS_PING_ACK (HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_SYS_OX_START + 0x3)
#define HFI_MSG_SYS_SESSION_ABORT_DONE (HFI_MSG_SYS_OX_START + 0x4)
#define HFI_MSG_SESSION_OX_START \
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 2b6d6bb..0f1e896 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -197,6 +197,10 @@
(HFI_PROPERTY_SYS_COMMON_START + 0x003)
#define HFI_PROPERTY_SYS_IDLE_INDICATOR \
(HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL \
+ (HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define HFI_PROPERTY_SYS_IMAGE_VERSION \
+ (HFI_PROPERTY_SYS_COMMON_START + 0x006)
#define HFI_PROPERTY_PARAM_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -615,6 +619,11 @@
struct hfi_resource_ocmem_requirement rg_requirements[1];
};
+struct hfi_property_sys_image_version_info_type {
+ u32 string_size;
+ u8 str_image_version[1];
+};
+
struct hfi_venc_config_advanced {
u8 pipe2d;
u8 hw_mode;
@@ -703,6 +712,7 @@
#define HFI_MSG_SYS_SESSION_INIT_DONE (HFI_MSG_SYS_COMMON_START + 0x6)
#define HFI_MSG_SYS_SESSION_END_DONE (HFI_MSG_SYS_COMMON_START + 0x7)
#define HFI_MSG_SYS_IDLE (HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_SYS_COMMON_START + 0xA)
#define HFI_MSG_SESSION_COMMON_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + \
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 30a666d..6554947 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -715,6 +715,11 @@
if (rc)
WFD_MSG_ERR("Failed to stop MDP\n");
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+ ENCODE_FLUSH, (void *)inst->venc_inst);
+ if (rc)
+ WFD_MSG_ERR("Failed to flush encoder\n");
+
WFD_MSG_DBG("vsg stop\n");
rc = v4l2_subdev_call(&wfd_dev->vsg_sdev, core, ioctl,
VSG_STOP, NULL);
@@ -723,10 +728,6 @@
complete(&inst->stop_mdp_thread);
kthread_stop(inst->mdp_task);
- rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
- ENCODE_FLUSH, (void *)inst->venc_inst);
- if (rc)
- WFD_MSG_ERR("Failed to flush encoder\n");
WFD_MSG_DBG("enc stop\n");
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 9b9c1ed..2e9db1f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -892,9 +892,12 @@
MMC_SEND_TUNING_BLOCK_HS200);
mmc_host_clk_release(card->host);
- if (err)
- pr_warn("%s: %s: tuning execution failed %d\n",
- mmc_hostname(card->host), __func__, err);
+ if (err) {
+ pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+ mmc_hostname(card->host), __func__, err,
+ host->clk_scaling.curr_freq);
+ mmc_set_clock(host, host->clk_scaling.curr_freq);
+ }
}
out:
mmc_release_host(host);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index ddf9a87..a4498d2 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -666,9 +666,12 @@
MMC_SEND_TUNING_BLOCK);
mmc_host_clk_release(card->host);
- if (err)
- pr_warn("%s: %s: tuning execution failed %d\n",
- mmc_hostname(card->host), __func__, err);
+ if (err) {
+ pr_warn("%s: %s: tuning execution failed %d. Restoring to previous clock %lu\n",
+ mmc_hostname(card->host), __func__, err,
+ host->clk_scaling.curr_freq);
+ mmc_set_clock(host, host->clk_scaling.curr_freq);
+ }
}
out:
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b386318..89e3472 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -6065,6 +6065,10 @@
msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
+ /* Disable SDHCi mode if supported */
+ if (is_sdhci_supported(host))
+ writel_relaxed(0, (host->base + MCI_CORE_HC_MODE));
+
/* Apply Hard reset to SDCC to put it in power on default state */
msmsdcc_hard_reset(host);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index bcfde57..3668d75 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -197,6 +197,8 @@
#define MAX_TESTBUS 8
#define MCI_TESTBUS_ENA (1 << 3)
+#define MCI_CORE_HC_MODE 0x78
+
#define MCI_SDCC_DEBUG_REG 0x124
#define MCI_IRQENABLE \
@@ -456,6 +458,7 @@
#define MSMSDCC_SW_RST_CFG_BROKEN (1 << 11)
#define MSMSDCC_DATA_PEND_FOR_CMD53 (1 << 12)
#define MSMSDCC_TESTBUS_DEBUG (1 << 13)
+#define MSMSDCC_SDHCI_MODE_SUPPORTED (1 << 14)
#define set_hw_caps(h, val) ((h)->hw_caps |= val)
#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -473,6 +476,7 @@
((h)->hw_caps & MSMSDCC_SW_RST_CFG_BROKEN)
#define is_data_pend_for_cmd53(h) ((h)->hw_caps & MSMSDCC_DATA_PEND_FOR_CMD53)
#define is_testbus_debug(h) ((h)->hw_caps & MSMSDCC_TESTBUS_DEBUG)
+#define is_sdhci_supported(h) ((h)->hw_caps & MSMSDCC_SDHCI_MODE_SUPPORTED)
/* Set controller capabilities based on version */
static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -511,7 +515,8 @@
MSMSDCC_AUTO_CMD21 |
MSMSDCC_DATA_PEND_FOR_CMD53 |
MSMSDCC_TESTBUS_DEBUG |
- MSMSDCC_SW_RST_CFG_BROKEN;
+ MSMSDCC_SW_RST_CFG_BROKEN |
+ MSMSDCC_SDHCI_MODE_SUPPORTED;
}
int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 853f37b..3495f4d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -597,6 +597,7 @@
int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
unsigned long flags;
+ int tuning_seq_cnt = 3;
u8 phase, *data_buf, tuned_phases[16], tuned_phase_cnt = 0;
const u32 *tuning_block_pattern = tuning_block_64;
int size = sizeof(tuning_block_64); /* Tuning pattern size in bytes */
@@ -623,17 +624,18 @@
}
spin_unlock_irqrestore(&host->lock, flags);
- /* first of all reset the tuning block */
- rc = msm_init_cm_dll(host);
- if (rc)
- goto out;
-
data_buf = kmalloc(size, GFP_KERNEL);
if (!data_buf) {
rc = -ENOMEM;
goto out;
}
+retry:
+ /* first of all reset the tuning block */
+ rc = msm_init_cm_dll(host);
+ if (rc)
+ goto kfree;
+
phase = 0;
do {
struct mmc_command cmd = {0};
@@ -690,10 +692,12 @@
pr_debug("%s: %s: finally setting the tuning phase to %d\n",
mmc_hostname(mmc), __func__, phase);
} else {
+ if (--tuning_seq_cnt)
+ goto retry;
/* tuning failed */
pr_err("%s: %s: no tuning point found\n",
mmc_hostname(mmc), __func__);
- rc = -EAGAIN;
+ rc = -EIO;
}
kfree:
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 2aff67d..9527249 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1932,7 +1932,7 @@
if (host->ops->execute_tuning) {
spin_unlock(&host->lock);
enable_irq(host->irq);
- host->ops->execute_tuning(host, opcode);
+ err = host->ops->execute_tuning(host, opcode);
disable_irq(host->irq);
spin_lock(&host->lock);
goto out;
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 16012bd..7f02187 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2229,7 +2229,8 @@
return err;
}
-#define BAM_APPS_PIPE_LOCK_GRP 0
+#define BAM_APPS_PIPE_LOCK_GRP0 0
+#define BAM_APPS_PIPE_LOCK_GRP1 1
/*
* This function allocates, configures, connects an end point and
* also registers event notification for an end point. It also allocates
@@ -2273,7 +2274,13 @@
}
sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
- sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP;
+
+ if (pipe_index == SPS_DATA_PROD_PIPE_INDEX ||
+ pipe_index == SPS_DATA_CONS_PIPE_INDEX)
+ sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP0;
+ else if (pipe_index == SPS_CMD_CONS_PIPE_INDEX)
+ sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP1;
+
/*
* Descriptor FIFO is a cyclic FIFO. If SPS_MAX_DESC_NUM descriptors
* are allowed to be submitted before we get any ack for any of them,
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 0772592..d1f3748 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -200,8 +200,10 @@
dev->get_encap_failure_cnt++;
usb_unanchor_urb(dev->rcvurb);
usb_autopm_put_interface(dev->intf);
- dev_err(dev->devicep,
- "%s: Error submitting Read URB %d\n", __func__, status);
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error submitting Read URB %d\n",
+ __func__, status);
goto resubmit_int_urb;
}
@@ -214,7 +216,9 @@
status = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (status) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
__func__, status);
}
}
@@ -286,8 +290,10 @@
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
usb_unanchor_urb(urb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
- __func__, status);
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
+ __func__, status);
}
return;
@@ -383,7 +389,9 @@
status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
if (status) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
+ if (status != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Error re-submitting Int URB %d\n",
__func__, status);
}
}
@@ -397,8 +405,9 @@
retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (retval < 0) {
usb_unanchor_urb(dev->inturb);
- dev_err(dev->devicep, "%s Intr submit %d\n", __func__,
- retval);
+ if (retval != -ENODEV)
+ dev_err(dev->devicep,
+ "%s Intr submit %d\n", __func__, retval);
}
return retval;
@@ -527,7 +536,9 @@
dev->snd_encap_cmd_cnt++;
result = usb_submit_urb(sndurb, GFP_KERNEL);
if (result < 0) {
- dev_err(dev->devicep, "%s: Submit URB error %d\n",
+ if (result != -ENODEV)
+ dev_err(dev->devicep,
+ "%s: Submit URB error %d\n",
__func__, result);
dev->snd_encap_cmd_cnt--;
usb_autopm_put_interface(dev->intf);
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index dba4430..986892b 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -787,15 +787,11 @@
&producer->resource.state_lock, flags);
consumer_result = ipa_rm_resource_consumer_release(
(struct ipa_rm_resource_cons *)consumer);
- if (consumer_result == -EINPROGRESS) {
- result = -EINPROGRESS;
- } else {
- spin_lock_irqsave(
- &producer->resource.state_lock, flags);
- producer->pending_release--;
- spin_unlock_irqrestore(
- &producer->resource.state_lock, flags);
- }
+ spin_lock_irqsave(
+ &producer->resource.state_lock, flags);
+ producer->pending_release--;
+ spin_unlock_irqrestore(
+ &producer->resource.state_lock, flags);
}
}
spin_lock_irqsave(&producer->resource.state_lock, flags);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 1fd4434..a9af974 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -2118,6 +2118,10 @@
if (the_chip->start_percent == -EINVAL)
return prev_soc;
+ /* do not scale at 100 */
+ if (new_soc == 100)
+ return new_soc;
+
chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
if (catch_up_sec == 0)
@@ -2501,7 +2505,7 @@
}
/* last_soc < soc ... scale and catch up */
- if (last_soc != -EINVAL && last_soc < soc && soc != 100)
+ if (last_soc != -EINVAL && last_soc < soc)
soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
if (last_soc != -EINVAL) {
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 2a007ca..23941a9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -2352,7 +2352,8 @@
}
rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
qpnp_chg_bat_if_batt_pres_irq_handler,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+ | IRQF_SHARED | IRQF_ONESHOT,
"batt-pres", chip);
if (rc < 0) {
pr_err("Can't request %d batt-pres irq: %d\n",
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index 3355e19..d1b911a 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -642,6 +642,8 @@
if (ctxt->ch && ctxt->ch->priv_usb == ctxt)
ctxt->ch->priv_usb = NULL;
list_del(&ctxt->list_item);
+ /* Free any pending USB requests from last session */
+ free_reqs(ctxt);
kfree(ctxt);
}
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index eb65509..2a98e49 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2207,6 +2207,8 @@
/* Clear alt interrupt latch and enable bits */
ulpi_write(phy, 0x1F, 0x92);
ulpi_write(phy, 0x1F, 0x95);
+ /* re-enable DP and DM pull down resistors */
+ ulpi_write(phy, 0x6, 0xB);
break;
default:
break;
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 5833796..1a9059c 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -26,15 +26,6 @@
static int dsi_off(struct mdss_panel_data *pdata)
{
int rc = 0;
- if (!panel_common_data || !pdata)
- return -ENODEV;
-
- if (dsi_intf.op_mode_config)
- dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
-
- pr_debug("panel off commands\n");
- if (panel_common_data->off)
- panel_common_data->off(pdata);
pr_debug("turn off dsi controller\n");
if (dsi_intf.off)
@@ -44,11 +35,6 @@
pr_err("mdss_dsi_off DSI failed %d\n", rc);
return rc;
}
-
- pr_debug("turn off panel power\n");
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 0);
-
return rc;
}
@@ -56,13 +42,7 @@
{
int rc = 0;
- pr_debug("dsi_on\n");
-
- if (!panel_common_data || !pdata)
- return -ENODEV;
-
-
- pr_debug("dsi_on DSI controller ont\n");
+ pr_debug("dsi_on DSI controller on\n");
if (dsi_intf.on)
rc = dsi_intf.on(pdata);
@@ -70,17 +50,34 @@
pr_err("mdss_dsi_on DSI failed %d\n", rc);
return rc;
}
- pr_debug("dsi_on power on panel\n");
- if (panel_common_data->reset)
- panel_common_data->reset(pdata, 1);
+ return rc;
+}
+static int dsi_panel_handler(struct mdss_panel_data *pdata, int enable)
+{
+ int rc = 0;
- pr_debug("dsi_on DSI panel ont\n");
- if (panel_common_data->on)
- rc = panel_common_data->on(pdata);
+ pr_debug("dsi_panel_handler enable=%d\n", enable);
+ if (!panel_common_data || !pdata)
+ return -ENODEV;
- if (rc) {
- pr_err("mdss_dsi_on panel failed %d\n", rc);
- return rc;
+ if (enable) {
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 1);
+
+ if (panel_common_data->on)
+ rc = panel_common_data->on(pdata);
+
+ if (rc)
+ pr_err("dsi_panel_handler panel on failed %d\n", rc);
+ } else {
+ if (dsi_intf.op_mode_config)
+ dsi_intf.op_mode_config(DSI_CMD_MODE, pdata);
+
+ if (panel_common_data->off)
+ panel_common_data->off(pdata);
+
+ if (panel_common_data->reset)
+ panel_common_data->reset(pdata, 0);
}
return rc;
}
@@ -96,12 +93,18 @@
}
switch (event) {
- case MDSS_EVENT_PANEL_ON:
+ case MDSS_EVENT_UNBLANK:
rc = dsi_on(pdata);
break;
- case MDSS_EVENT_PANEL_OFF:
+ case MDSS_EVENT_BLANK:
rc = dsi_off(pdata);
break;
+ case MDSS_EVENT_PANEL_ON:
+ rc = dsi_panel_handler(pdata, 1);
+ break;
+ case MDSS_EVENT_PANEL_OFF:
+ rc = dsi_panel_handler(pdata, 0);
+ break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index bbf9b60..66418db 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -982,6 +982,92 @@
return xres * bpp;
}
+static int mdp3_fbmem_alloc(struct msm_fb_data_type *mfd)
+{
+ int ret = -ENOMEM, 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) {
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = 0;
+ return 0;
+ }
+
+ mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
+ SZ_1M,
+ ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+
+ if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
+ virt = ion_map_kernel(mdp3_res->ion_client,
+ mdp3_res->ion_handle);
+ if (IS_ERR(virt)) {
+ pr_err("%s map kernel error\n", __func__);
+ goto ion_map_kernel_err;
+ }
+
+ ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
+ &phys, &size);
+ if (ret) {
+ pr_err("%s ion_phys error\n", __func__);
+ goto ion_map_phys_err;
+ }
+ } else {
+ pr_err("%s ion alloc fail\n", __func__);
+ mdp3_res->ion_handle = NULL;
+ return -ENOMEM;
+ }
+
+ dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ ret = ion_map_iommu(mdp3_res->ion_client, mdp3_res->ion_handle,
+ dom, 0, SZ_4K, 0, &mfd->iova,
+ (unsigned long *)&size, 0, 0);
+
+ if (ret) {
+ pr_err("%s map IOMMU error\n", __func__);
+ goto ion_map_phys_err;
+ }
+
+ pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+ size, virt, phys, mfd->index);
+
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = size;
+ return 0;
+
+ion_map_phys_err:
+ ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ion_map_kernel_err:
+ ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+ mdp3_res->ion_handle = NULL;
+ return -ENOMEM;
+}
+
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd)
+{
+ pr_info("mdp3_fbmem_free\n");
+ if (mdp3_res->ion_handle) {
+ int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+ ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
+ ion_unmap_iommu(mdp3_res->ion_client, mdp3_res->ion_handle,
+ dom, 0);
+ ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
+ mdp3_res->ion_handle = NULL;
+ mfd->fbi->screen_base = 0;
+ mfd->fbi->fix.smem_start = 0;
+ mfd->fbi->fix.smem_len = 0;
+ mfd->iova = 0;
+ }
+}
+
struct mdp3_dma *mdp3_get_dma_pipe(int capability)
{
int i;
@@ -1023,6 +1109,7 @@
static struct msm_mdp_interface mdp3_interface = {
.init_fnc = mdp3_init,
.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
+ .fb_mem_alloc_fnc = mdp3_fbmem_alloc,
.fb_stride = mdp3_fb_stride,
};
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 0482844..d29e5b6 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -110,6 +110,7 @@
struct ion_client *ion_client;
struct mdp3_iommu_domain_map *domains;
struct mdp3_iommu_ctx_map *iommu_contexts;
+ struct ion_handle *ion_handle;
struct mdp3_dma dma[MDP3_DMA_MAX];
struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
@@ -150,6 +151,7 @@
int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
int mdp3_iommu_enable(int client);
int mdp3_iommu_disable(int client);
+void mdp3_fbmem_free(struct msm_fb_data_type *mfd);
#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)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index a875f21..04cd78c 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -427,8 +427,10 @@
}
panel = mdp3_session->panel;
- if (panel->event_handler)
- rc = panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ if (panel->event_handler) {
+ rc = panel->event_handler(panel, MDSS_EVENT_UNBLANK, NULL);
+ rc |= panel->event_handler(panel, MDSS_EVENT_PANEL_ON, NULL);
+ }
if (rc) {
pr_err("fail to turn on the panel\n");
goto on_error;
@@ -459,6 +461,10 @@
goto on_error;
}
+ if (panel->set_backlight)
+ panel->set_backlight(panel, panel->panel_info.bl_max);
+
+ pr_debug("mdp3_ctrl_on dma start\n");
if (mfd->fbi->screen_base) {
rc = mdp3_session->dma->start(mdp3_session->dma,
mdp3_session->intf);
@@ -490,6 +496,7 @@
return -ENODEV;
}
+ panel = mdp3_session->panel;
mutex_lock(&mdp3_session->lock);
if (!mdp3_session->status) {
@@ -497,32 +504,39 @@
goto off_error;
}
- pr_debug("mdp3_ctrl_off stop mdp3 dma engine\n");
-
mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);
- rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
+ pr_debug("mdp3_ctrl_off turn panel off\n");
+ if (panel->set_backlight)
+ panel->set_backlight(panel, 0);
- if (rc)
- pr_err("fail to stop the MDP3 dma\n");
-
- mdp3_irq_deregister();
-
- pr_debug("mdp3_ctrl_off stop dsi panel and controller\n");
- 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");
- pr_debug("mdp3_ctrl_off release bus and clock\n");
- rc = mdp3_ctrl_res_req_bus(mfd, 0);
+ rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
if (rc)
- pr_err("mdp bus resource release failed\n");
+ pr_err("fail to stop the MDP3 dma\n");
+
+ mdp3_irq_deregister();
+
+ pr_debug("mdp3_ctrl_off stop clock\n");
rc = mdp3_ctrl_res_req_clk(mfd, 0);
if (rc)
pr_err("mdp clock resource release failed\n");
+ pr_debug("mdp3_ctrl_off stop dsi controller\n");
+ if (panel->event_handler)
+ rc = panel->event_handler(panel, MDSS_EVENT_BLANK, NULL);
+ if (rc)
+ pr_err("fail to turn off the panel\n");
+
+ pr_debug("mdp3_ctrl_off release bus\n");
+ rc = mdp3_ctrl_res_req_bus(mfd, 0);
+ if (rc)
+ pr_err("mdp bus resource release failed\n");
+
rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
if (rc)
pr_err("fail to dettach MDP DMA SMMU\n");
@@ -670,6 +684,9 @@
if (mdp3_bufq_count(&mdp3_session->bufq_out) > 2) {
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
mdp3_put_img(data);
+
+ if (mfd->fbi->screen_base)
+ mdp3_fbmem_free(mfd);
}
mutex_unlock(&mdp3_session->lock);
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index fb0e8ba..44a5e62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -360,13 +360,13 @@
__func__, rc);
goto error;
}
- mp->vreg_config[i].peak_current = val_array[i];
+ mp->vreg_config[i].enable_load = val_array[i];
pr_debug("%s: %s min=%d, max=%d, pc=%d\n", __func__,
mp->vreg_config[i].vreg_name,
mp->vreg_config[i].min_voltage,
mp->vreg_config[i].max_voltage,
- mp->vreg_config[i].peak_current);
+ mp->vreg_config[i].enable_load);
}
devm_kfree(dev, val_array);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 91e5660..e4a6b86 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -87,6 +87,9 @@
static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable);
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+ bool wait_audio_tx);
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
struct mdss_hw hdmi_tx_hw = {
.hw_ndx = MDSS_HW_HDMI,
@@ -1676,10 +1679,11 @@
} /* hdmi_tx_powerdown_phy */
static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool enabled, int num_of_channels)
+ bool enabled)
{
/* Read first before writing */
u32 acr_pck_ctrl_reg;
+ u32 sample_rate;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -1687,6 +1691,8 @@
return -EINVAL;
}
+ sample_rate = hdmi_ctrl->audio_data.sample_rate;
+
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1721,18 +1727,19 @@
return -EPERM;
}
- n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
- cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
- layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ n = audio_acr->lut[sample_rate].n;
+ cts = audio_acr->lut[sample_rate].cts;
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
+ hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
if (
- (AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
multiplier = 4;
n >>= 2; /* divide N by 4 and use multiplier */
} else if (
- (AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
multiplier = 2;
n >>= 1; /* divide N by 2 and use multiplier */
} else {
@@ -1743,12 +1750,16 @@
/* AUDIO_PRIORITY | SOURCE */
acr_pck_ctrl_reg |= 0x80000100;
+
+ /* Reset multiplier bits */
+ acr_pck_ctrl_reg &= ~(7 << 16);
+
/* N_MULTIPLE(multiplier) */
acr_pck_ctrl_reg |= (multiplier & 7) << 16;
- if ((AUDIO_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+ if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
/* SELECT(3) */
acr_pck_ctrl_reg |= 3 << 4;
/* CTS_48 */
@@ -1759,9 +1770,9 @@
/* N */
DSS_REG_W(io, HDMI_ACR_48_1, n);
} else if (
- (AUDIO_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
- (AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+ (AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
+ (AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
/* SELECT(2) */
acr_pck_ctrl_reg |= 2 << 4;
/* CTS_44 */
@@ -1800,12 +1811,15 @@
} /* hdmi_tx_audio_acr_setup */
static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool enabled, u32 num_of_channels, u32 channel_allocation,
- u32 level_shift, bool down_mix)
+ bool enabled)
{
struct dss_io_data *io = NULL;
u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+ u32 num_of_channels;
+ u32 channel_allocation;
+ u32 level_shift;
+ u32 down_mix;
u32 check_sum, audio_info_0_reg, audio_info_1_reg;
u32 audio_info_ctrl_reg;
u32 aud_pck_ctrl_2_reg;
@@ -1816,6 +1830,11 @@
return -EINVAL;
}
+ num_of_channels = hdmi_ctrl->audio_data.channel_num;
+ channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
+ level_shift = hdmi_ctrl->audio_data.level_shift;
+ down_mix = hdmi_ctrl->audio_data.down_mix;
+
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1926,8 +1945,8 @@
} /* hdmi_tx_audio_iframe_setup */
static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
- u32 num_of_channels, u32 channel_allocation, u32 level_shift,
- bool down_mix)
+ u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
+ u32 level_shift, bool down_mix)
{
int rc = 0;
struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
@@ -1937,10 +1956,31 @@
return -ENODEV;
}
- if (hdmi_ctrl->panel_power_on) {
- rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true,
- num_of_channels, channel_allocation, level_shift,
- down_mix);
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) && hdmi_ctrl->panel_power_on) {
+
+ /* Map given sample rate to Enum */
+ if (sample_rate == 32000)
+ sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
+ else if (sample_rate == 44100)
+ sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
+ else if (sample_rate == 48000)
+ sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ else if (sample_rate == 88200)
+ sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
+ else if (sample_rate == 96000)
+ sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
+ else if (sample_rate == 176400)
+ sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
+ else if (sample_rate == 192000)
+ sample_rate = AUDIO_SAMPLE_RATE_192KHZ;
+
+ hdmi_ctrl->audio_data.sample_rate = sample_rate;
+ hdmi_ctrl->audio_data.channel_num = num_of_channels;
+ hdmi_ctrl->audio_data.spkr_alloc = channel_allocation;
+ hdmi_ctrl->audio_data.level_shift = level_shift;
+ hdmi_ctrl->audio_data.down_mix = down_mix;
+
+ rc = hdmi_tx_audio_setup(hdmi_ctrl);
if (rc)
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.rc=%d\n",
__func__, rc);
@@ -2047,7 +2087,6 @@
static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
- const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2061,14 +2100,14 @@
return -EINVAL;
}
- rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+ rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true);
if (rc) {
DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
__func__, rc);
return rc;
}
- rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true, channels, 0, 0, false);
+ rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true);
if (rc) {
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed. rc=%d\n",
__func__, rc);
@@ -2080,9 +2119,10 @@
return 0;
} /* hdmi_tx_audio_setup */
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+ bool wait_audio_tx)
{
- u32 i, status, sleep_us, timeout_us, timeout_sec = 15;
+ u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2096,33 +2136,43 @@
return;
}
- /* Check if audio engine is turned off by QDSP or not */
- /* send off notification after every 1 sec for 15 seconds */
- for (i = 0; i < timeout_sec; i++) {
- sleep_us = 5000; /* Maximum time to sleep between two reads */
- timeout_us = 1000 * 1000; /* Total time for condition to meet */
+ if (wait_audio_tx) {
+ /* Check if audio engine is turned off by QDSP or not */
+ /* send off notification after every 1 sec for 15 seconds */
+ for (i = 0; i < timeout_sec; i++) {
+ /* Maximum time to sleep between two reads */
+ sleep_us = 5000;
+ /* Total time for condition to meet */
+ timeout_us = 1000 * 1000;
- if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
- status, ((status & BIT(0)) == 0),
- sleep_us, timeout_us)) {
+ if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
+ status, ((status & BIT(0)) == 0),
+ sleep_us, timeout_us)) {
- DEV_ERR("%s: audio still on after %d sec. try again\n",
+ DEV_ERR(
+ "%s: audio still on after %d sec. try again\n",
__func__, i+1);
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, true);
- continue;
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
+ true);
+ continue;
+ }
+ break;
}
- break;
}
+
if (i == timeout_sec)
DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
- if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false, 0, 0, 0, false))
+ if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
- if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+ if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
+ hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
+
DEV_INFO("HDMI Audio: Disabled\n");
} /* hdmi_tx_audio_off */
@@ -2239,7 +2289,7 @@
if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
- hdmi_tx_audio_off(hdmi_ctrl);
+ hdmi_tx_audio_off(hdmi_ctrl, true);
}
hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2656,7 +2706,8 @@
INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
- hdmi_ctrl->audio_sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+ hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
hdmi_ctrl->sdev.name = "hdmi";
if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
@@ -3216,13 +3267,13 @@
__func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
- mp->vreg_config[j].peak_current = val_array[i];
+ mp->vreg_config[j].enable_load = val_array[i];
DEV_DBG("%s: %s min=%d, max=%d, pc=%d\n", __func__,
mp->vreg_config[j].vreg_name,
mp->vreg_config[j].min_voltage,
mp->vreg_config[j].max_voltage,
- mp->vreg_config[j].peak_current);
+ mp->vreg_config[j].enable_load);
ndx_mask >>= 1;
j++;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index d4f8e67..18ee782 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -38,12 +38,20 @@
struct dss_module_power power_data[HDMI_TX_MAX_PM];
};
+struct hdmi_audio {
+ int sample_rate;
+ int channel_num;
+ int spkr_alloc;
+ int level_shift;
+ int down_mix;
+};
+
struct hdmi_tx_ctrl {
struct platform_device *pdev;
struct hdmi_tx_platform_data pdata;
struct mdss_panel_data panel_data;
- int audio_sample_rate;
+ struct hdmi_audio audio_data;
struct mutex mutex;
struct kobject *kobj;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 31058f8..c862e78 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -213,7 +213,7 @@
}
msleep(in_vreg[i].pre_on_sleep);
rc = regulator_set_optimum_mode(in_vreg[i].vreg,
- in_vreg[i].peak_current);
+ in_vreg[i].enable_load);
if (rc < 0) {
DEV_ERR("%pS->%s: %s set opt m fail\n",
__builtin_return_address(0), __func__,
@@ -233,7 +233,8 @@
for (i = num_vreg-1; i >= 0; i--)
if (regulator_is_enabled(in_vreg[i].vreg)) {
msleep(in_vreg[i].pre_off_sleep);
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg,
+ in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
msleep(in_vreg[i].post_off_sleep);
}
@@ -241,12 +242,13 @@
return rc;
disable_vreg:
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg, in_vreg[i].disable_load);
vreg_set_opt_mode_fail:
for (i--; i >= 0; i--) {
msleep(in_vreg[i].pre_off_sleep);
- regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+ regulator_set_optimum_mode(in_vreg[i].vreg,
+ in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
msleep(in_vreg[i].post_off_sleep);
}
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index cb0fb70..6ad21e8 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -52,7 +52,8 @@
char vreg_name[32];
int min_voltage;
int max_voltage;
- int peak_current;
+ int enable_load;
+ int disable_load;
int pre_on_sleep;
int post_on_sleep;
int pre_off_sleep;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index d1e5e64..eaef12b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -30,6 +30,7 @@
static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
u32 reg, u32 val)
@@ -94,6 +95,11 @@
}
}
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
+{
+ return bitmap_weight(smp, SMP_MB_CNT) == 0;
+}
+
static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
{
u32 fetch_size, val, wm[3];
@@ -227,6 +233,8 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++) {
+ if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+ continue;
mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
pipe->smp_map[i].reserved);
cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -708,10 +716,9 @@
if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
opmode);
-
- mdss_mdp_smp_alloc(pipe);
}
+ mdss_mdp_smp_alloc(pipe);
ret = mdss_mdp_src_addr_setup(pipe, src_data);
if (ret) {
pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 4fa41b5..6f00df7 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -97,6 +97,23 @@
uint32_t gain;
};
+struct epm_marker_level {
+ uint8_t level;
+};
+
+struct epm_gpio_buffer_request {
+ uint8_t cmd;
+ uint8_t bitmask_monitor_pin;
+ uint8_t status;
+};
+
+struct epm_get_gpio_buffer_resp {
+ uint8_t cmd;
+ uint8_t status;
+ uint8_t bitmask_monitor_pin;
+ uint32_t timestamp;
+};
+
#ifdef __KERNEL__
struct epm_adc_platform_data {
struct epm_chan_properties *channel;
@@ -121,7 +138,19 @@
#define EPM_ADC_DEINIT _IOR(EPM_ADC_IOCTL_CODE, 3, \
uint32_t)
-#define EPM_PSOC_ADC_INIT _IOR(EPM_ADC_IOCTL_CODE, 4, \
+#define EPM_MARKER1_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 90, \
+ uint32_t)
+
+#define EPM_MARKER1_RELEASE _IOWR(EPM_ADC_IOCTL_CODE, 91, \
+ uint32_t)
+
+#define EPM_MARKER2_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 95, \
+ uint32_t)
+
+#define EPM_MARKER2_RELEASE _IOWR(EPM_ADC_IOCTL_CODE, 92, \
+ uint32_t)
+
+#define EPM_PSOC_ADC_INIT _IOWR(EPM_ADC_IOCTL_CODE, 4, \
struct epm_psoc_init_resp)
#define EPM_PSOC_ADC_CHANNEL_ENABLE _IOWR(EPM_ADC_IOCTL_CODE, 5, \
@@ -157,4 +186,13 @@
#define EPM_PSOC_ADC_SET_VADC_REFERENCE _IOWR(EPM_ADC_IOCTL_CODE, 15, \
struct epm_psoc_set_vadc)
+#define EPM_PSOC_ADC_DEINIT _IOWR(EPM_ADC_IOCTL_CODE, 16, \
+ uint32_t)
+
+#define EPM_PSOC_GPIO_BUFFER_REQUEST _IOWR(EPM_ADC_IOCTL_CODE, 17, \
+ uint32_t)
+
+#define EPM_PSOC_GET_GPIO_BUFFER_DATA _IOWR(EPM_ADC_IOCTL_CODE, 18, \
+ uint32_t)
+
#endif /* __EPM_ADC_H */
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 46bce9e..e5d5c32 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -113,7 +113,7 @@
channel_allocation);
codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
- num_channels, channel_allocation,
+ params_rate(params), num_channels, channel_allocation,
level_shift, down_mix);
return 0;