Merge "msm: vidc: Validate session_id in video hardware response"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index b618597..9319163 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -434,7 +434,8 @@
amplifier.
- qcom,headset-jack-type-NO: Adjust GPIO level based on the headset jack type.
-
+- qcom,tapan-codec-9302: Indicates that this device node is for WCD9302 audio
+ codec.
* APQ8074 ASoC Machine driver
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 69b2cd2..58fc698 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -290,6 +290,14 @@
timer counter page should be mapped by the kernel. User-space apps
will read directly from the page at this address.
+config ARCH_RANDOM
+ bool "SOC specific random number generation"
+ help
+ Allow the kernel to use an architecture specific implementation for
+ random number generation
+
+ If unsure, say N
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
diff --git a/arch/arm/boot/dts/apq8026-v1-mtp.dts b/arch/arm/boot/dts/apq8026-v1-mtp.dts
index 7900ddf..87a0271 100644
--- a/arch/arm/boot/dts/apq8026-v1-mtp.dts
+++ b/arch/arm/boot/dts/apq8026-v1-mtp.dts
@@ -22,8 +22,8 @@
};
&cci {
- /* Rotate rear camera to 0 degrees */
+ /* Rotate rear camera to 180 degrees */
qcom,camera@6f {
- qcom,mount-angle = <0>;
+ qcom,mount-angle = <180>;
};
};
diff --git a/arch/arm/boot/dts/batterydata-qrd-4v2-1300mah.dtsi b/arch/arm/boot/dts/batterydata-qrd-4v2-1300mah.dtsi
new file mode 100644
index 0000000..103da50
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-qrd-4v2-1300mah.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.
+ */
+
+qcom,qrd-4v2-1300mah-data {
+ qcom,fcc-mah = <1300>;
+ qcom,default-rbatt-mohm = <172>;
+ qcom,rbatt-capacitive-mohm = <0>;
+ qcom,flat-ocv-threshold-uv = <3800000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,chg-term-ua = <100000>;
+ qcom,batt-id-kohm = <100>;
+
+ qcom,rbatt-sf-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 15 10 9>,
+ <8 7 6 5 4>,
+ <3 2 1 0>;
+ qcom,lut-data = <604 192 100 79 71>,
+ <605 192 100 79 71>,
+ <641 205 103 81 72>,
+ <641 221 108 84 75>,
+ <622 238 115 87 77>,
+ <612 254 123 92 79>,
+ <605 252 137 96 83>,
+ <607 219 154 104 87>,
+ <613 202 135 109 89>,
+ <626 200 106 90 77>,
+ <656 201 101 82 75>,
+ <684 204 100 84 77>,
+ <710 211 100 85 79>,
+ <747 224 106 89 82>,
+ <806 241 116 90 80>,
+ <905 260 119 87 77>,
+ <1046 291 113 87 77>,
+ <1309 329 116 90 79>,
+ <1476 300 126 97 83>,
+ <1598 311 127 98 84>,
+ <1771 323 130 99 85>,
+ <1984 342 136 101 86>,
+ <2438 368 140 101 86>,
+ <3381 388 137 100 84>,
+ <4913 414 141 99 86>,
+ <6979 468 155 104 90>,
+ <9968 565 192 113 98>,
+ <16163 833 350 140 120>,
+ <36511 6483 4872 472 1095>;
+ };
+
+ qcom,fcc-temp-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-data = <1343 1353 1408 1345 1342>;
+ };
+
+ qcom,pc-temp-ocv-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 15 10 9>,
+ <8 7 6 5 4>,
+ <3 2 1 0>;
+ qcom,lut-data = <4177 4174 4199 4167 4162>,
+ <4107 4112 4141 4109 4106>,
+ <4058 4064 4091 4061 4059>,
+ <3996 4015 4044 4017 4015>,
+ <3947 3975 4001 3978 3976>,
+ <3909 3939 3962 3943 3940>,
+ <3874 3901 3926 3911 3907>,
+ <3845 3858 3892 3882 3878>,
+ <3821 3826 3851 3849 3846>,
+ <3801 3804 3815 3810 3808>,
+ <3788 3789 3793 3789 3787>,
+ <3778 3780 3778 3776 3773>,
+ <3769 3776 3770 3767 3764>,
+ <3757 3772 3766 3762 3757>,
+ <3740 3765 3762 3754 3744>,
+ <3714 3747 3750 3739 3724>,
+ <3668 3706 3717 3710 3697>,
+ <3602 3644 3662 3662 3654>,
+ <3533 3571 3601 3607 3605>,
+ <3518 3557 3583 3592 3590>,
+ <3500 3543 3565 3576 3574>,
+ <3478 3528 3546 3559 3557>,
+ <3451 3506 3521 3538 3534>,
+ <3417 3473 3481 3505 3496>,
+ <3377 3423 3424 3454 3444>,
+ <3327 3361 3351 3391 3380>,
+ <3261 3279 3258 3310 3297>,
+ <3165 3165 3138 3198 3182>,
+ <3000 3000 3000 3000 3000>;
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 5b7cc79..0b3fec4 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -61,7 +61,7 @@
29 01 00 00 00 00 03 D6 44 44
29 01 00 00 00 00 0D D7 00 00 00 00 00 00 00 00 00 00 00 00
29 01 00 00 00 00 0E D8 00 00 00 00 00 00 00 00 00 00 00 00 00
- 29 01 00 00 00 00 03 D9 00 28
+ 29 01 00 00 00 00 03 D9 03 06
29 01 00 00 00 00 03 E5 00 FF
29 01 00 00 00 00 05 E6 F3 EC E7 DF
29 01 00 00 00 00 0B E7 F3 D9 CC CD B3 A6 99 99 99 95
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index e4fc96c..049c71a 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -863,6 +863,18 @@
linux,name = "led:flash_1";
qcom,current = <625>;
};
- };
+
+ pm8226_torch: qcom,flash_torch {
+ qcom,max-current = <200>;
+ qcom,default-state = "off";
+ linux,default-trigger =
+ "torch_trigger";
+ label = "flash";
+ qcom,id = <1>;
+ linux,name = "led:flash_torch";
+ qcom,current = <120>;
+ qcom,torch-enable;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index f807814..5d7a7ec 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -18,6 +18,7 @@
compatible = "qcom,camera-led-flash";
qcom,flash-type = <1>;
qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+ qcom,torch-source = <&pm8226_torch>;
};
};
@@ -38,7 +39,7 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
- qcom,mount-angle = <0>;
+ qcom,mount-angle = <180>;
qcom,sensor-name = "ov8825";
cam_vdig-supply = <&pm8226_l5>;
cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 56e8a09..5d1e1c8 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -18,6 +18,7 @@
compatible = "qcom,camera-led-flash";
qcom,flash-type = <1>;
qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+ qcom,torch-source = <&pm8226_torch>;
};
};
@@ -38,7 +39,7 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
- qcom,mount-angle = <90>;
+ qcom,mount-angle = <270>;
qcom,sensor-name = "ov8825";
cam_vdig-supply = <&pm8226_l5>;
cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 64e4b6e..5822a4a 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -18,6 +18,7 @@
compatible = "qcom,camera-led-flash";
qcom,flash-type = <1>;
qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+ qcom,torch-source = <&pm8226_torch>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dtsi b/arch/arm/boot/dts/msm8226-cdp.dtsi
index e44ce07..cada48e 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -35,8 +35,6 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
- synaptics,power-down;
- synaptics,disable-gpios;
};
};
@@ -112,6 +110,24 @@
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
qcom,headset-jack-type-NO;
};
+
+ sound-9302 {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,headset-jack-type-NO;
+ };
};
&sdcc1 {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 3138b06..f04366c 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -35,8 +35,6 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
- synaptics,power-down;
- synaptics,disable-gpios;
};
};
@@ -106,14 +104,31 @@
"MIC BIAS1 External", "Handset Mic",
"AMIC2", "MIC BIAS2 External",
"MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "ANCRight Headset Mic",
"AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC5", "MIC BIAS2 External",
"MIC BIAS2 External", "ANCLeft Headset Mic";
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
};
+
+ sound-9302 {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 Internal1",
+ "MIC BIAS1 Internal1", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
+ };
};
&usb_otg {
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 8ab517a..53fb6bf 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -30,8 +30,6 @@
synaptics,irq-gpio = <&msmgpio 17 0x2008>;
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
- synaptics,power-down;
- synaptics,disable-gpios;
};
focaltech@38 {
compatible = "focaltech,5x06";
@@ -117,15 +115,33 @@
"MIC BIAS1 External", "Handset Mic",
"AMIC2", "MIC BIAS2 External",
"MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "ANCRight Headset Mic",
"AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC5", "MIC BIAS2 External",
"MIC BIAS2 External", "ANCLeft Headset Mic";
qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
qcom,cdc-us-euro-gpios = <&msmgpio 69 0>;
};
+
+ sound-9302 {
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-vdd-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-us-euro-gpios = <&msmgpio 69 0>;
+ };
};
&sdcc1 {
diff --git a/arch/arm/boot/dts/msm8226-v1-mtp.dts b/arch/arm/boot/dts/msm8226-v1-mtp.dts
index 6f03dca..c32adbe 100644
--- a/arch/arm/boot/dts/msm8226-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-v1-mtp.dts
@@ -25,8 +25,8 @@
};
&cci {
- /* Rotate rear camera to 0 degrees */
+ /* Rotate rear camera to 180 degrees */
qcom,camera@6f {
- qcom,mount-angle = <0>;
+ qcom,mount-angle = <180>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index 1cbf00d..59de631 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -113,6 +113,12 @@
status = "disabled";
};
};
+
+ qcom,pm8226@1 {
+ qcom,leds@d800 {
+ status = "disabled";
+ };
+ };
};
&pm8226_mpps {
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
index 9e98681..7aadd71 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-dvt.dts
@@ -35,3 +35,7 @@
&pm8226_bms {
qcom,use-external-rsense;
};
+
+&pm8226_iadc {
+ qcom,rsense = <10000000>;
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index fba41e5..76a3cc7 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -114,6 +114,12 @@
status = "disabled";
};
};
+
+ qcom,pm8226@1 {
+ qcom,leds@d800 {
+ status = "disabled";
+ };
+ };
};
&pm8226_mpps {
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 5e2c7bc..0ae0fc6 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -377,6 +377,18 @@
qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
};
+ sound-9302 {
+ compatible = "qcom,msm8226-audio-tapan";
+ qcom,model = "msm8226-tapan9302-snd-card";
+ qcom,tapan-mclk-clk-freq = <9600000>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 63 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 64 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
+ qcom,tapan-codec-9302;
+ };
+
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
qcom,msm-pcm-dsp-id = <0>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dtsi b/arch/arm/boot/dts/msm8610-cdp.dtsi
index bfccb78..7b545a6 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -238,8 +238,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 349c8f7..4bbc478 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -276,8 +276,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
index e73573a..bdcb285 100644
--- a/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-camera-sensor.dtsi
@@ -18,7 +18,7 @@
qcom,slave-id = <0x40 0x04 0xc0>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
- qcom,mount-angle = <270>;
+ qcom,mount-angle = <90>;
qcom,sensor-name = "hi256";
cam_vdig-supply = <&pm8110_l2>;
cam_vana-supply = <&pm8110_l19>;
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 49068b5..a88c9fb 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -247,8 +247,6 @@
&sdhc_1 {
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <200 400000>;
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
similarity index 100%
rename from arch/arm/boot/dts/msm8610-pm.dtsi
rename to arch/arm/boot/dts/msm8610-v1-pm.dtsi
diff --git a/arch/arm/boot/dts/msm8610-v1.dtsi b/arch/arm/boot/dts/msm8610-v1.dtsi
index 5052b96..6050a75 100644
--- a/arch/arm/boot/dts/msm8610-v1.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1.dtsi
@@ -17,3 +17,4 @@
*/
/include/ "msm8610.dtsi"
+/include/ "msm8610-v1-pm.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
new file mode 100644
index 0000000..a887d32
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -0,0 +1,292 @@
+/* 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.
+ */
+
+&soc {
+ qcom,spm@f9089000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9089000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x00>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x8>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ };
+
+ qcom,spm@f9099000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9099000 0x1000>;
+ qcom,core-id = <1>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x00>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x8>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ };
+
+ qcom,spm@f90a9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90a9000 0x1000>;
+ qcom,core-id = <2>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x00>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x8>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ };
+
+ qcom,spm@f90b9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90b9000 0x1000>;
+ qcom,core-id = <3>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x00>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x8>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 26 30 0f];
+ };
+
+ qcom,spm@f9012000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9012000 0x1000>;
+ qcom,core-id = <0xffff>; /* L2/APCS SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
+ qcom,saw2-pmic-data0 = <0x02030080>;
+ qcom,saw2-pmic-data1 = <0x00030000>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,pfm-port = <0x2>;
+ qcom,saw2-spm-cmd-ret = [00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 6b c0 e0 d0 42 07 50
+ 4e 02 02 d0 e0 c0 22 6b 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+ 50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_active";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = "wfi";
+ qcom,l2 = "l2_cache_active";
+ qcom,latency-us = <1>;
+ qcom,ss-power = <784>;
+ qcom,energy-overhead = <190000>;
+ qcom,time-overhead = <100>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = "standalone_pc";
+ qcom,l2 = "l2_cache_active";
+ qcom,latency-us = <3000>;
+ qcom,ss-power = <725>;
+ qcom,energy-overhead = <99500>;
+ qcom,time-overhead = <3130>;
+ };
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_gdhs";
+ qcom,latency-us = <20000>;
+ qcom,ss-power = <138>;
+ qcom,energy-overhead = <1208400>;
+ qcom,time-overhead = <9200>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_pc";
+ qcom,latency-us = <30000>;
+ qcom,ss-power = <110>;
+ qcom,energy-overhead = <1250300>;
+ qcom,time-overhead = <9500>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = "tz";
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <2 216>, /* tsens_upper_lower_int */
+ <0xff 56>, /* q6_wdog_expired_irq */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
+ <0xff 173>, /* o_wcss_apss_smd_hi */
+ <0xff 174>, /* o_wcss_apss_smd_med */
+ <0xff 175>, /* o_wcss_apss_smd_low */
+ <0xff 176>, /* o_wcss_apss_smsm_irq */
+ <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+ <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+ <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
+ <0xff 161>, /* lpass_irq_out_spare[4] /
+ <0xff 162>, /* lpass_irq_out_spare[5]*/
+ <0xff 234>, /* lpass_irq_out_spare[6]*/
+ <0xff 235>, /* lpass_irq_out_spare[7]*/
+ <0xff 188>, /* lpass_irq_out_apcs(0) */
+ <0xff 189>, /* lpass_irq_out_apcs(1) */
+ <0xff 190>, /* lpass_irq_out_apcs(2) */
+ <0xff 191>, /* lpass_irq_out_apcs(3) */
+ <0xff 192>, /* lpass_irq_out_apcs(4) */
+ <0xff 194>, /* lpass_irq_out_apcs(6) */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 258>, /* rpm_ipc(28) */
+ <0xff 259>, /* rpm_ipc(29) */
+ <0xff 275>, /* rpm_ipc(30) */
+ <0xff 276>, /* rpm_ipc(31) */
+ <0xff 269>, /* rpm_wdog_expired_irq */
+ <0xff 240>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <3 1>,
+ <4 4 >,
+ <5 5 >,
+ <6 9 >,
+ <7 13>,
+ <8 17>,
+ <9 21>,
+ <10 27>,
+ <11 29>,
+ <12 31>,
+ <13 33>,
+ <14 35>,
+ <15 37>,
+ <16 38>,
+ <17 39>,
+ <18 41>,
+ <19 46>,
+ <20 48>,
+ <21 49>,
+ <22 50>,
+ <23 51>,
+ <24 52>,
+ <25 54>,
+ <26 62>,
+ <27 63>,
+ <28 64>,
+ <29 65>,
+ <30 66>,
+ <31 67>,
+ <32 68>,
+ <33 69>,
+ <34 71>,
+ <35 72>,
+ <36 106>,
+ <37 107>,
+ <38 108>,
+ <39 109>,
+ <40 110>,
+ <54 111>,
+ <55 113>;
+ };
+
+ qcom,pm-8x60@fe805664 {
+ compatible = "qcom,pm-8x60";
+ reg = <0xfe805664 0x40>;
+ qcom,pc-mode = "tz_l2_int";
+ qcom,use-sync-timer;
+ qcom,pc-resets-timer;
+ };
+
+ qcom,cpu-sleep-status@f9088008{
+ compatible = "qcom,cpu-sleep-status";
+ reg = <0xf9088008 0x100>;
+ qcom,cpu-alias-addr = <0x10000>;
+ qcom,sleep-status-mask= <0x80000>;
+ };
+
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
+ qcom,rpm-stats@fc19dba0 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xfc19dba0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+
+ qcom,rpm-rbcpr-stats@fc000000 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0xfc000000 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-v2.dtsi b/arch/arm/boot/dts/msm8610-v2.dtsi
index 5052b96..89d8f74 100644
--- a/arch/arm/boot/dts/msm8610-v2.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2.dtsi
@@ -17,3 +17,4 @@
*/
/include/ "msm8610.dtsi"
+/include/ "msm8610-v2-pm.dtsi"
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index efa68b9..4851868 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -40,7 +40,6 @@
/include/ "msm8610-gpu.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8610-coresight.dtsi"
-/include/ "msm8610-pm.dtsi"
/include/ "msm8610-smp2p.dtsi"
/include/ "msm8610-bus.dtsi"
/include/ "msm8610-mdss.dtsi"
@@ -258,8 +257,6 @@
interrupt-names = "core_irq", "bam_irq";
vdd-supply = <&pm8110_l17>;
- qcom,vdd-always-on;
- qcom,vdd-lpm-sup;
qcom,vdd-voltage-level = <2900000 2900000>;
qcom,vdd-current-level = <9000 400000>;
diff --git a/arch/arm/include/asm/archrandom.h b/arch/arm/include/asm/archrandom.h
new file mode 100644
index 0000000..5530d45
--- /dev/null
+++ b/arch/arm/include/asm/archrandom.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef ARM_ASM_ARCHRANDOM_H
+#define ARM_ASM_ARCHRANDOM_H
+
+extern int arch_get_random_long(unsigned long *v);
+extern int arch_get_random_int(unsigned int *v);
+
+#endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 12ffa66..89eb589 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -431,3 +431,4 @@
obj-$(CONFIG_WALL_CLK) += wallclk.o
obj-$(CONFIG_WALL_CLK_SYSFS) += wallclk_sysfs.o
+obj-$(CONFIG_ARCH_RANDOM) += early_random.o
diff --git a/arch/arm/mach-msm/early_random.c b/arch/arm/mach-msm/early_random.c
new file mode 100644
index 0000000..e315b86
--- /dev/null
+++ b/arch/arm/mach-msm/early_random.c
@@ -0,0 +1,83 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include <mach/scm.h>
+
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+#define TZ_SVC_CRYPTO 10
+#define PRNG_CMD_ID 0x01
+
+static int use_arch_random = 1;
+struct tz_prng_data {
+ uint8_t *out_buf;
+ uint32_t out_buf_sz;
+} __packed;
+
+DEFINE_SCM_BUFFER(common_scm_buf)
+DEFINE_MUTEX(arch_random_lock);
+#define RANDOM_BUFFER_SIZE PAGE_SIZE
+char random_buffer[RANDOM_BUFFER_SIZE] __aligned(PAGE_SIZE);
+
+int arch_get_random_common(void *v, size_t size)
+{
+ struct tz_prng_data data;
+ int ret;
+ u32 resp;
+
+ if (!use_arch_random)
+ return 0;
+
+ if (size > sizeof(random_buffer))
+ return 0;
+
+ mutex_lock(&arch_random_lock);
+ data.out_buf = (uint8_t *) virt_to_phys(random_buffer);
+ data.out_buf_sz = size;
+
+ ret = scm_call_noalloc(TZ_SVC_CRYPTO, PRNG_CMD_ID, &data,
+ sizeof(data), &resp, sizeof(resp),
+ common_scm_buf, SCM_BUFFER_SIZE(common_scm_buf));
+ if (!ret) {
+ dmac_inv_range(random_buffer, random_buffer +
+ RANDOM_BUFFER_SIZE);
+ outer_inv_range(
+ (unsigned long) virt_to_phys(random_buffer),
+ (unsigned long) virt_to_phys(random_buffer) +
+ RANDOM_BUFFER_SIZE);
+ memcpy(v, random_buffer, size);
+ }
+ mutex_unlock(&arch_random_lock);
+ return !ret;
+}
+
+int arch_get_random_long(unsigned long *v)
+{
+ return arch_get_random_common(v, sizeof(unsigned long));
+}
+
+int arch_get_random_int(unsigned int *v)
+{
+ return arch_get_random_common(v, sizeof(unsigned int));
+}
+
+int arch_random_init(void)
+{
+ use_arch_random = 0;
+
+ return 0;
+}
+module_init(arch_random_init);
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 4186603..539dcf6 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -26,10 +26,22 @@
#define SCM_SVC_ES 0x10
#define SCM_SVC_TZSCHEDULER 0xFC
+#define DEFINE_SCM_BUFFER(__n) \
+static char __n[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+#define SCM_BUFFER_SIZE(__buf) sizeof(__buf)
+
+#define SCM_BUFFER_PHYS(__buf) virt_to_phys(__buf)
+
#ifdef CONFIG_MSM_SCM
extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
void *resp_buf, size_t resp_len);
+extern int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+ size_t cmd_len, void *resp_buf, size_t resp_len,
+ void *scm_buf, size_t scm_buf_size);
+
+
extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1);
extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2);
extern s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3);
@@ -50,6 +62,13 @@
return 0;
}
+static inline int scm_call_noalloc(u32 svc_id, u32 cmd_id,
+ const void *cmd_buf, size_t cmd_len, void *resp_buf,
+ size_t resp_len, void *scm_buf, size_t scm_buf_size)
+{
+ return 0;
+}
+
static inline s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
{
return 0;
diff --git a/arch/arm/mach-msm/mpm-of.c b/arch/arm/mach-msm/mpm-of.c
index a0746f9..e364393 100644
--- a/arch/arm/mach-msm/mpm-of.c
+++ b/arch/arm/mach-msm/mpm-of.c
@@ -219,12 +219,16 @@
hlist_for_each_entry(node, elem, &irq_hash[hashfn(d->hwirq)], node) {
if ((node->hwirq == d->hwirq)
&& (d->domain == node->domain)) {
- /* Update the linux irq mapping */
- msm_mpm_irqs_m2a[node->pin] = d->irq;
+ /*
+ * Update the linux irq mapping. No update required for
+ * bypass interrupts
+ */
+ if (node->pin != 0xff)
+ msm_mpm_irqs_m2a[node->pin] = d->irq;
break;
}
}
- return node ? node->pin : 0;
+ return elem ? node->pin : 0;
}
static int msm_mpm_enable_irq_exclusive(
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index e9f44e3..266b759 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -31,6 +31,9 @@
static DEFINE_MUTEX(scm_lock);
+#define SCM_BUF_LEN(__cmd_size, __resp_size) \
+ (sizeof(struct scm_command) + sizeof(struct scm_response) + \
+ __cmd_size + __resp_size)
/**
* struct scm_command - one SCM command buffer
* @len: total available memory for command and response
@@ -76,42 +79,6 @@
};
/**
- * alloc_scm_command() - Allocate an SCM command
- * @cmd_size: size of the command buffer
- * @resp_size: size of the response buffer
- *
- * Allocate an SCM command, including enough room for the command
- * and response headers as well as the command and response buffers.
- *
- * Returns a valid &scm_command on success or %NULL if the allocation fails.
- */
-static struct scm_command *alloc_scm_command(size_t cmd_size, size_t resp_size)
-{
- struct scm_command *cmd;
- size_t len = sizeof(*cmd) + sizeof(struct scm_response) + cmd_size +
- resp_size;
-
- cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
- if (cmd) {
- cmd->len = len;
- cmd->buf_offset = offsetof(struct scm_command, buf);
- cmd->resp_hdr_offset = cmd->buf_offset + cmd_size;
- }
- return cmd;
-}
-
-/**
- * free_scm_command() - Free an SCM command
- * @cmd: command to free
- *
- * Free an SCM command.
- */
-static inline void free_scm_command(struct scm_command *cmd)
-{
- kfree(cmd);
-}
-
-/**
* scm_command_to_response() - Get a pointer to a scm_response
* @cmd: command
*
@@ -224,6 +191,92 @@
}
/**
+ * scm_call_common() - Send an SCM command
+ * @svc_id: service identifier
+ * @cmd_id: command identifier
+ * @cmd_buf: command buffer
+ * @cmd_len: length of the command buffer
+ * @resp_buf: response buffer
+ * @resp_len: length of the response buffer
+ * @scm_buf: internal scm structure used for passing data
+ * @scm_buf_len: length of the internal scm structure
+ *
+ * Core function to scm call. Initializes the given cmd structure with
+ * appropriate values and makes the actual scm call. Validation of cmd
+ * pointer and length must occur in the calling function.
+ *
+ * Returns the appropriate error code from the scm call
+ */
+
+static int scm_call_common(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+ size_t cmd_len, void *resp_buf, size_t resp_len,
+ struct scm_command *scm_buf,
+ size_t scm_buf_length)
+{
+ int ret;
+ struct scm_response *rsp;
+ unsigned long start, end;
+
+ scm_buf->len = scm_buf_length;
+ scm_buf->buf_offset = offsetof(struct scm_command, buf);
+ scm_buf->resp_hdr_offset = scm_buf->buf_offset + cmd_len;
+ scm_buf->id = (svc_id << 10) | cmd_id;
+
+ if (cmd_buf)
+ memcpy(scm_get_command_buffer(scm_buf), cmd_buf, cmd_len);
+
+ mutex_lock(&scm_lock);
+ ret = __scm_call(scm_buf);
+ mutex_unlock(&scm_lock);
+ if (ret)
+ return ret;
+
+ rsp = scm_command_to_response(scm_buf);
+ start = (unsigned long)rsp;
+
+ do {
+ scm_inv_range(start, start + sizeof(*rsp));
+ } while (!rsp->is_complete);
+
+ end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
+ scm_inv_range(start, end);
+
+ if (resp_buf)
+ memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
+
+ return ret;
+}
+
+/**
+ * scm_call_noalloc - Send an SCM command
+ *
+ * Same as scm_call except clients pass in a buffer (@scm_buf) to be used for
+ * scm internal structures. The buffer should be allocated with
+ * DEFINE_SCM_BUFFER to account for the proper alignment and size.
+ */
+int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+ size_t cmd_len, void *resp_buf, size_t resp_len,
+ void *scm_buf, size_t scm_buf_len)
+{
+ int ret;
+ size_t len = SCM_BUF_LEN(cmd_len, resp_len);
+
+ if (cmd_len > scm_buf_len || resp_len > scm_buf_len ||
+ len > scm_buf_len)
+ return -EINVAL;
+
+ if (!IS_ALIGNED((unsigned long)scm_buf, PAGE_SIZE))
+ return -EINVAL;
+
+ memset(scm_buf, 0, scm_buf_len);
+
+ ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,
+ resp_len, scm_buf, len);
+ return ret;
+
+}
+
+/**
* scm_call() - Send an SCM command
* @svc_id: service identifier
* @cmd_id: command identifier
@@ -244,39 +297,20 @@
int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len,
void *resp_buf, size_t resp_len)
{
- int ret;
struct scm_command *cmd;
- struct scm_response *rsp;
- unsigned long start, end;
+ int ret;
+ size_t len = SCM_BUF_LEN(cmd_len, resp_len);
- cmd = alloc_scm_command(cmd_len, resp_len);
+ if (cmd_len > len || resp_len > len)
+ return -EINVAL;
+
+ cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
- cmd->id = (svc_id << 10) | cmd_id;
- if (cmd_buf)
- memcpy(scm_get_command_buffer(cmd), cmd_buf, cmd_len);
-
- mutex_lock(&scm_lock);
- ret = __scm_call(cmd);
- mutex_unlock(&scm_lock);
- if (ret)
- goto out;
-
- rsp = scm_command_to_response(cmd);
- start = (unsigned long)rsp;
-
- do {
- scm_inv_range(start, start + sizeof(*rsp));
- } while (!rsp->is_complete);
-
- end = (unsigned long)scm_get_response_buffer(rsp) + resp_len;
- scm_inv_range(start, end);
-
- if (resp_buf)
- memcpy(resp_buf, scm_get_response_buffer(rsp), resp_len);
-out:
- free_scm_command(cmd);
+ ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,
+ resp_len, cmd, len);
+ kfree(cmd);
return ret;
}
EXPORT_SYMBOL(scm_call);
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index d500c0a..3225817 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -45,6 +45,8 @@
#define tmc_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
#define tmc_readl(drvdata, off) __raw_readl(drvdata->base + off)
+#define tmc_readl_no_log(drvdata, off) __raw_readl_no_log(drvdata->base + off)
+
#define TMC_LOCK(drvdata) \
do { \
mb(); \
@@ -651,7 +653,7 @@
bufp = drvdata->buf;
while (1) {
for (i = 0; i < memwords; i++) {
- read_data = tmc_readl(drvdata, TMC_RRD);
+ read_data = tmc_readl_no_log(drvdata, TMC_RRD);
if (read_data == 0xFFFFFFFF)
goto out;
memcpy(bufp, &read_data, BYTES_PER_WORD);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 0c398c4..b5945da 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -240,6 +240,7 @@
#define A3XX_PC_PERFCOUNTER1_SELECT 0xC49
#define A3XX_PC_PERFCOUNTER2_SELECT 0xC4A
#define A3XX_PC_PERFCOUNTER3_SELECT 0xC4B
+#define A3XX_GRAS_TSE_DEBUG_ECO 0xC81
#define A3XX_GRAS_PERFCOUNTER0_SELECT 0xC88
#define A3XX_GRAS_PERFCOUNTER1_SELECT 0xC89
#define A3XX_GRAS_PERFCOUNTER2_SELECT 0xC8A
@@ -269,8 +270,10 @@
#define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6
#define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7
#define A3XX_RB_GMEM_BASE_ADDR 0xCC0
+#define A3XX_RB_DEBUG_ECO_CONTROLS_ADDR 0xCC1
#define A3XX_RB_PERFCOUNTER0_SELECT 0xCC6
#define A3XX_RB_PERFCOUNTER1_SELECT 0xCC7
+#define A3XX_RB_FRAME_BUFFER_DIMENSION 0xCE0
#define A3XX_HLSQ_PERFCOUNTER0_SELECT 0xE00
#define A3XX_HLSQ_PERFCOUNTER1_SELECT 0xE01
#define A3XX_HLSQ_PERFCOUNTER2_SELECT 0xE02
@@ -308,6 +311,9 @@
#define A3XX_GRAS_CL_CLIP_CNTL 0x2040
#define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044
#define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048
+#define A3XX_GRAS_CL_VPORT_XSCALE 0x2049
+#define A3XX_GRAS_CL_VPORT_YOFFSET 0x204A
+#define A3XX_GRAS_CL_VPORT_YSCALE 0x204B
#define A3XX_GRAS_CL_VPORT_ZOFFSET 0x204C
#define A3XX_GRAS_CL_VPORT_ZSCALE 0x204D
#define A3XX_GRAS_SU_POINT_MINMAX 0x2068
@@ -323,30 +329,75 @@
#define A3XX_RB_MODE_CONTROL 0x20C0
#define A3XX_RB_RENDER_CONTROL 0x20C1
#define A3XX_RB_MSAA_CONTROL 0x20C2
+#define A3XX_RB_ALPHA_REFERENCE 0x20C3
#define A3XX_RB_MRT_CONTROL0 0x20C4
#define A3XX_RB_MRT_BUF_INFO0 0x20C5
+#define A3XX_RB_MRT_BUF_BASE0 0x20C6
#define A3XX_RB_MRT_BLEND_CONTROL0 0x20C7
+#define A3XX_RB_MRT_CONTROL1 0x20C8
+#define A3XX_RB_MRT_BUF_INFO1 0x20C9
+#define A3XX_RB_MRT_BUF_BASE1 0x20CA
#define A3XX_RB_MRT_BLEND_CONTROL1 0x20CB
+#define A3XX_RB_MRT_CONTROL2 0x20CC
+#define A3XX_RB_MRT_BUF_INFO2 0x20CD
+#define A3XX_RB_MRT_BUF_BASE2 0x20CE
#define A3XX_RB_MRT_BLEND_CONTROL2 0x20CF
+#define A3XX_RB_MRT_CONTROL3 0x20D0
+#define A3XX_RB_MRT_BUF_INFO3 0x20D1
+#define A3XX_RB_MRT_BUF_BASE3 0x20D2
#define A3XX_RB_MRT_BLEND_CONTROL3 0x20D3
#define A3XX_RB_BLEND_RED 0x20E4
+#define A3XX_RB_BLEND_GREEN 0x20E5
+#define A3XX_RB_BLEND_BLUE 0x20E6
+#define A3XX_RB_BLEND_ALPHA 0x20E7
+#define A3XX_RB_CLEAR_COLOR_DW0 0x20E8
+#define A3XX_RB_CLEAR_COLOR_DW1 0x20E9
+#define A3XX_RB_CLEAR_COLOR_DW2 0x20EA
+#define A3XX_RB_CLEAR_COLOR_DW3 0x20EB
#define A3XX_RB_COPY_CONTROL 0x20EC
+#define A3XX_RB_COPY_DEST_BASE 0x20ED
+#define A3XX_RB_COPY_DEST_PITCH 0x20EE
#define A3XX_RB_COPY_DEST_INFO 0x20EF
#define A3XX_RB_DEPTH_CONTROL 0x2100
+#define A3XX_RB_DEPTH_CLEAR 0x2101
+#define A3XX_RB_DEPTH_BUF_INFO 0x2102
+#define A3XX_RB_DEPTH_BUF_PITCH 0x2103
#define A3XX_RB_STENCIL_CONTROL 0x2104
+#define A3XX_RB_STENCIL_CLEAR 0x2105
+#define A3XX_RB_STENCIL_BUF_INFO 0x2106
+#define A3XX_RB_STENCIL_BUF_PITCH 0x2107
+#define A3XX_RB_STENCIL_REF_MASK 0x2108
+#define A3XX_RB_STENCIL_REF_MASK_BF 0x2109
+#define A3XX_RB_LRZ_VSC_CONTROL 0x210C
+#define A3XX_RB_WINDOW_OFFSET 0x210E
+#define A3XX_RB_SAMPLE_COUNT_CONTROL 0x2110
+#define A3XX_RB_SAMPLE_COUNT_ADDR 0x2111
+#define A3XX_RB_Z_CLAMP_MIN 0x2114
+#define A3XX_RB_Z_CLAMP_MAX 0x2115
#define A3XX_PC_VSTREAM_CONTROL 0x21E4
#define A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x21EA
#define A3XX_PC_PRIM_VTX_CNTL 0x21EC
#define A3XX_PC_RESTART_INDEX 0x21ED
#define A3XX_HLSQ_CONTROL_0_REG 0x2200
+#define A3XX_HLSQ_CONTROL_1_REG 0x2201
+#define A3XX_HLSQ_CONTROL_2_REG 0x2202
+#define A3XX_HLSQ_CONTROL_3_REG 0x2203
#define A3XX_HLSQ_VS_CONTROL_REG 0x2204
+#define A3XX_HLSQ_FS_CONTROL_REG 0x2205
+#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG 0x2206
#define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG 0x2207
#define A3XX_HLSQ_CL_NDRANGE_0_REG 0x220A
+#define A3XX_HLSQ_CL_NDRANGE_1_REG 0x220B
#define A3XX_HLSQ_CL_NDRANGE_2_REG 0x220C
+#define A3XX_HLSQ_CL_NDRANGE_3_REG 0x220D
+#define A3XX_HLSQ_CL_NDRANGE_4_REG 0x220E
+#define A3XX_HLSQ_CL_NDRANGE_5_REG 0x220F
+#define A3XX_HLSQ_CL_NDRANGE_6_REG 0x2210
#define A3XX_HLSQ_CL_CONTROL_0_REG 0x2211
#define A3XX_HLSQ_CL_CONTROL_1_REG 0x2212
#define A3XX_HLSQ_CL_KERNEL_CONST_REG 0x2214
#define A3XX_HLSQ_CL_KERNEL_GROUP_X_REG 0x2215
+#define A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x2216
#define A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x2217
#define A3XX_HLSQ_CL_WG_OFFSET_REG 0x221A
#define A3XX_VFD_CONTROL_0 0x2240
@@ -363,10 +414,21 @@
#define A3XX_SP_VS_CTRL_REG0 0x22C4
#define A3XX_SP_VS_CTRL_REG1 0x22C5
#define A3XX_SP_VS_PARAM_REG 0x22C6
+#define A3XX_SP_VS_OUT_REG_0 0x22C7
+#define A3XX_SP_VS_OUT_REG_1 0x22C8
+#define A3XX_SP_VS_OUT_REG_2 0x22C9
+#define A3XX_SP_VS_OUT_REG_3 0x22CA
+#define A3XX_SP_VS_OUT_REG_4 0x22CB
+#define A3XX_SP_VS_OUT_REG_5 0x22CC
+#define A3XX_SP_VS_OUT_REG_6 0x22CD
#define A3XX_SP_VS_OUT_REG_7 0x22CE
#define A3XX_SP_VS_VPC_DST_REG_0 0x22D0
+#define A3XX_SP_VS_VPC_DST_REG_1 0x22D1
+#define A3XX_SP_VS_VPC_DST_REG_2 0x22D2
+#define A3XX_SP_VS_VPC_DST_REG_3 0x22D3
#define A3XX_SP_VS_OBJ_OFFSET_REG 0x22D4
#define A3XX_SP_VS_OBJ_START_REG 0x22D5
+#define A3XX_SP_VS_PVT_MEM_PARAM_REG 0x22D6
#define A3XX_SP_VS_PVT_MEM_ADDR_REG 0x22D7
#define A3XX_SP_VS_PVT_MEM_SIZE_REG 0x22D8
#define A3XX_SP_VS_LENGTH_REG 0x22DF
@@ -374,13 +436,19 @@
#define A3XX_SP_FS_CTRL_REG1 0x22E1
#define A3XX_SP_FS_OBJ_OFFSET_REG 0x22E2
#define A3XX_SP_FS_OBJ_START_REG 0x22E3
+#define A3XX_SP_FS_PVT_MEM_PARAM_REG 0x22E4
#define A3XX_SP_FS_PVT_MEM_ADDR_REG 0x22E5
#define A3XX_SP_FS_PVT_MEM_SIZE_REG 0x22E6
#define A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x22E8
#define A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x22E9
#define A3XX_SP_FS_OUTPUT_REG 0x22EC
#define A3XX_SP_FS_MRT_REG_0 0x22F0
+#define A3XX_SP_FS_MRT_REG_1 0x22F1
+#define A3XX_SP_FS_MRT_REG_2 0x22F2
+#define A3XX_SP_FS_MRT_REG_3 0x22F3
#define A3XX_SP_FS_IMAGE_OUTPUT_REG_0 0x22F4
+#define A3XX_SP_FS_IMAGE_OUTPUT_REG_1 0x22F5
+#define A3XX_SP_FS_IMAGE_OUTPUT_REG_2 0x22F6
#define A3XX_SP_FS_IMAGE_OUTPUT_REG_3 0x22F7
#define A3XX_SP_FS_LENGTH_REG 0x22FF
#define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b964620..2a6fe62 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -71,6 +71,8 @@
| (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \
| (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT))
+#define KGSL_LOG_LEVEL_DEFAULT 3
+
static const struct kgsl_functable adreno_functable;
static struct adreno_device device_3d0 = {
@@ -100,6 +102,13 @@
.iomemname = KGSL_3D0_REG_MEMORY,
.shadermemname = KGSL_3D0_SHADER_MEMORY,
.ftbl = &adreno_functable,
+ .cmd_log = KGSL_LOG_LEVEL_DEFAULT,
+ .ctxt_log = KGSL_LOG_LEVEL_DEFAULT,
+ .drv_log = KGSL_LOG_LEVEL_DEFAULT,
+ .mem_log = KGSL_LOG_LEVEL_DEFAULT,
+ .pwr_log = KGSL_LOG_LEVEL_DEFAULT,
+ .ft_log = KGSL_LOG_LEVEL_DEFAULT,
+ .pm_dump_enable = 0,
},
.gmem_base = 0,
.gmem_size = SZ_256K,
@@ -117,13 +126,7 @@
* If the values of these registers are same after
* KGSL_TIMEOUT_PART time, GPU hang is reported in
* kernel log.
- * *****ALERT******ALERT********ALERT*************
- * Order of registers below is important, registers
- * from LONG_IB_DETECT_REG_INDEX_START to
- * LONG_IB_DETECT_REG_INDEX_END are used in long ib detection.
*/
-#define LONG_IB_DETECT_REG_INDEX_START 1
-#define LONG_IB_DETECT_REG_INDEX_END 5
unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT];
@@ -631,36 +634,44 @@
kgsl_mmu_unmap(pagetable, &adreno_dev->profile.shared_buffer);
+ kgsl_mmu_unmap(pagetable, &adreno_dev->pwron_fixup);
+
kgsl_mmu_unmap(pagetable, &device->mmu.setstate_memory);
}
static int adreno_setup_pt(struct kgsl_device *device,
struct kgsl_pagetable *pagetable)
{
- int result = 0;
+ int result;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
- if (result)
- goto error;
- result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
- if (result)
- goto unmap_buffer_desc;
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
- result = kgsl_mmu_map_global(pagetable, &device->memstore);
- if (result)
- goto unmap_memptrs_desc;
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable, &device->memstore);
- result = kgsl_mmu_map_global(pagetable,
- &adreno_dev->profile.shared_buffer);
- if (result)
- goto unmap_profile_shared;
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable,
+ &adreno_dev->profile.shared_buffer);
- result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
- if (result)
- goto unmap_memstore_desc;
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable,
+ &adreno_dev->pwron_fixup);
+
+
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable,
+ &device->mmu.setstate_memory);
+
+ if (result) {
+ /* On error clean up what we have wrought */
+ adreno_cleanup_pt(device, pagetable);
+ return result;
+ }
/*
* Set the mpu end to the last "normal" global memory we use.
@@ -669,22 +680,8 @@
*/
device->mh.mpu_range = device->mmu.setstate_memory.gpuaddr +
device->mmu.setstate_memory.size;
- return result;
-unmap_profile_shared:
- kgsl_mmu_unmap(pagetable, &adreno_dev->profile.shared_buffer);
-
-unmap_memstore_desc:
- kgsl_mmu_unmap(pagetable, &device->memstore);
-
-unmap_memptrs_desc:
- kgsl_mmu_unmap(pagetable, &rb->memptrs_desc);
-
-unmap_buffer_desc:
- kgsl_mmu_unmap(pagetable, &rb->buffer_desc);
-
-error:
- return result;
+ return 0;
}
static unsigned int _adreno_iommu_setstate_v0(struct kgsl_device *device,
@@ -1693,6 +1690,10 @@
/* Power down the device */
kgsl_pwrctrl_disable(device);
+ /* Certain targets need the fixup. You know who you are */
+ if (adreno_is_a330v2(adreno_dev))
+ adreno_a3xx_pwron_fixup_init(adreno_dev);
+
return 0;
}
@@ -1715,6 +1716,9 @@
/* Power up the device */
kgsl_pwrctrl_enable(device);
+ /* Set the bit to indicate that we've just powered on */
+ set_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv);
+
/* Set up a2xx special case */
if (adreno_is_a2xx(adreno_dev)) {
/*
@@ -3326,6 +3330,9 @@
if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr, size))
return &device->memstore;
+ if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup, gpuaddr, size))
+ return &adreno_dev->pwron_fixup;
+
if (kgsl_gpuaddr_in_memdesc(&device->mmu.setstate_memory, gpuaddr,
size))
return &device->mmu.setstate_memory;
@@ -3553,7 +3560,6 @@
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
unsigned int curr_reg_val[FT_DETECT_REGS_COUNT];
unsigned int fast_hang_detected = 1;
- unsigned int long_ib_detected = 1;
unsigned int i;
static unsigned long next_hang_detect_time;
static unsigned int prev_global_ts;
@@ -3566,9 +3572,6 @@
if (!adreno_dev->fast_hang_detect)
fast_hang_detected = 0;
- if (!adreno_dev->long_ib_detect)
- long_ib_detected = 0;
-
if (!(adreno_dev->ringbuffer.flags & KGSL_FLAGS_STARTED))
return 0;
@@ -3653,17 +3656,8 @@
}
}
for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
- if (curr_reg_val[i] != prev_reg_val[i]) {
+ if (curr_reg_val[i] != prev_reg_val[i])
fast_hang_detected = 0;
-
- /* Check for long IB here */
- if ((i >=
- LONG_IB_DETECT_REG_INDEX_START)
- &&
- (i <=
- LONG_IB_DETECT_REG_INDEX_END))
- long_ib_detected = 0;
- }
}
if (fast_hang_detected) {
@@ -3685,15 +3679,12 @@
pid_name, curr_context->ib_gpu_time_used,
curr_global_ts+1);
- if ((long_ib_detected) &&
+ if ((adreno_dev->long_ib_detect) &&
(!(curr_context->flags &
- CTXT_FLAGS_NO_FAULT_TOLERANCE))) {
- curr_context->ib_gpu_time_used +=
- KGSL_TIMEOUT_PART;
- if (curr_context->ib_gpu_time_used >
- KGSL_TIMEOUT_LONG_IB_DETECTION) {
- if (adreno_dev->long_ib_ts !=
- curr_global_ts) {
+ CTXT_FLAGS_NO_FAULT_TOLERANCE)) &&
+ (curr_context->ib_gpu_time_used >
+ KGSL_TIMEOUT_LONG_IB_DETECTION) &&
+ (adreno_dev->long_ib_ts != curr_global_ts)) {
KGSL_FT_ERR(device,
"Proc %s, ctxt_id %d ts %d"
"used GPU for %d ms long ib "
@@ -3710,8 +3701,6 @@
curr_context->ib_gpu_time_used =
0;
return 1;
- }
- }
}
}
} else {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 72f15e7..9a070a6 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -40,6 +40,7 @@
#define KGSL_CMD_FLAGS_INTERNAL_ISSUE 0x00000002
#define KGSL_CMD_FLAGS_GET_INT 0x00000004
#define KGSL_CMD_FLAGS_PROFILE 0x00000008
+#define KGSL_CMD_FLAGS_PWRON_FIXUP 0x00000010
#define KGSL_CMD_FLAGS_EOF 0x00000100
/* Command identifiers */
@@ -52,6 +53,7 @@
#define KGSL_NOP_IB_IDENTIFIER 0x20F20F20
#define KGSL_START_OF_PROFILE_IDENTIFIER 0x2DEFADE1
#define KGSL_END_OF_PROFILE_IDENTIFIER 0x2DEFADE2
+#define KGSL_PWRON_FIXUP_IDENTIFIER 0x2AFAFAFA
#ifdef CONFIG_MSM_SCM
#define ADRENO_DEFAULT_PWRSCALE_POLICY (&kgsl_pwrscale_policy_tz)
@@ -100,6 +102,7 @@
struct adreno_device {
struct kgsl_device dev; /* Must be first field in this struct */
+ unsigned long priv;
unsigned int chip_id;
enum adreno_gpurev gpurev;
unsigned long gmem_base;
@@ -136,6 +139,19 @@
unsigned int ocmem_base;
unsigned int gpu_cycles;
struct adreno_profile profile;
+ struct kgsl_memdesc pwron_fixup;
+ unsigned int pwron_fixup_dwords;
+};
+
+/**
+ * enum adreno_device_flags - Private flags for the adreno_device
+ * @ADRENO_DEVICE_PWRON - Set during init after a power collapse
+ * @ADRENO_DEVICE_PWRON_FIXUP - Set if the target requires the shader fixup
+ * after power collapse
+ */
+enum adreno_device_flags {
+ ADRENO_DEVICE_PWRON = 0,
+ ADRENO_DEVICE_PWRON_FIXUP = 1,
};
#define PERFCOUNTER_FLAG_NONE 0x0
@@ -436,6 +452,7 @@
int adreno_soft_reset(struct kgsl_device *device);
+int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev);
static inline int adreno_is_a200(struct adreno_device *adreno_dev)
{
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index d96965c..f9110ea 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2510,6 +2510,478 @@
}
}
+static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = {
+ 0x00000000, 0x302CC300, 0x00000000, 0x302CC304,
+ 0x00000000, 0x302CC308, 0x00000000, 0x302CC30C,
+ 0x00000000, 0x302CC310, 0x00000000, 0x302CC314,
+ 0x00000000, 0x302CC318, 0x00000000, 0x302CC31C,
+ 0x00000000, 0x302CC320, 0x00000000, 0x302CC324,
+ 0x00000000, 0x302CC328, 0x00000000, 0x302CC32C,
+ 0x00000000, 0x302CC330, 0x00000000, 0x302CC334,
+ 0x00000000, 0x302CC338, 0x00000000, 0x302CC33C,
+ 0x00000000, 0x00000400, 0x00020000, 0x63808003,
+ 0x00060004, 0x63828007, 0x000A0008, 0x6384800B,
+ 0x000E000C, 0x6386800F, 0x00120010, 0x63888013,
+ 0x00160014, 0x638A8017, 0x001A0018, 0x638C801B,
+ 0x001E001C, 0x638E801F, 0x00220020, 0x63908023,
+ 0x00260024, 0x63928027, 0x002A0028, 0x6394802B,
+ 0x002E002C, 0x6396802F, 0x00320030, 0x63988033,
+ 0x00360034, 0x639A8037, 0x003A0038, 0x639C803B,
+ 0x003E003C, 0x639E803F, 0x00000000, 0x00000400,
+ 0x00000003, 0x80D60003, 0x00000007, 0x80D60007,
+ 0x0000000B, 0x80D6000B, 0x0000000F, 0x80D6000F,
+ 0x00000013, 0x80D60013, 0x00000017, 0x80D60017,
+ 0x0000001B, 0x80D6001B, 0x0000001F, 0x80D6001F,
+ 0x00000023, 0x80D60023, 0x00000027, 0x80D60027,
+ 0x0000002B, 0x80D6002B, 0x0000002F, 0x80D6002F,
+ 0x00000033, 0x80D60033, 0x00000037, 0x80D60037,
+ 0x0000003B, 0x80D6003B, 0x0000003F, 0x80D6003F,
+ 0x00000000, 0x03000000, 0x00000000, 0x00000000,
+};
+
+/**
+ * adreno_a3xx_pwron_fixup_init() - Initalize a special command buffer to run a
+ * post-power collapse shader workaround
+ * @adreno_dev: Pointer to a adreno_device struct
+ *
+ * Some targets require a special workaround shader to be executed after
+ * power-collapse. Construct the IB once at init time and keep it
+ * handy
+ *
+ * Returns: 0 on success or negative on error
+ */
+int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev)
+{
+ unsigned int *cmds;
+ int count = ARRAY_SIZE(_a3xx_pwron_fixup_fs_instructions);
+ int ret;
+
+ /* Return if the fixup is already in place */
+ if (test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
+ return 0;
+
+ ret = kgsl_allocate_contiguous(&adreno_dev->pwron_fixup, PAGE_SIZE);
+
+ if (ret)
+ return ret;
+
+ adreno_dev->pwron_fixup.flags |= KGSL_MEMFLAGS_GPUREADONLY;
+
+ cmds = adreno_dev->pwron_fixup.hostptr;
+
+ *cmds++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2);
+ *cmds++ = 0x00000000;
+ *cmds++ = 0x90000000;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_REG_RMW, 3);
+ *cmds++ = A3XX_RBBM_CLOCK_CTL;
+ *cmds++ = 0xFFFCFFFF;
+ *cmds++ = 0x00010000;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1);
+ *cmds++ = 0x1E000150;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+ *cmds++ = 0x1E000150;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1);
+ *cmds++ = 0x1E000150;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_1_REG, 1);
+ *cmds++ = 0x00000040;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_2_REG, 1);
+ *cmds++ = 0x80000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_3_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_VS_CONTROL_REG, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_FS_CONTROL_REG, 1);
+ *cmds++ = 0x0D001002;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_VSPRESV_RANGE_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_FSPRESV_RANGE_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_0_REG, 1);
+ *cmds++ = 0x00401101;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_1_REG, 1);
+ *cmds++ = 0x00000400;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_2_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_3_REG, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_4_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_5_REG, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_6_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_1_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_CONST_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG, 1);
+ *cmds++ = 0x00000010;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_WG_OFFSET_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_SP_CTRL_REG, 1);
+ *cmds++ = 0x00040000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1);
+ *cmds++ = 0x0000000A;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG1, 1);
+ *cmds++ = 0x00000001;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PARAM_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_4, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_5, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_6, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_7, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_OFFSET_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_START_REG, 1);
+ *cmds++ = 0x00000004;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_PARAM_REG, 1);
+ *cmds++ = 0x04008001;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_ADDR_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_VS_LENGTH_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1);
+ *cmds++ = 0x0DB0400A;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG1, 1);
+ *cmds++ = 0x00300402;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_OFFSET_REG, 1);
+ *cmds++ = 0x00010000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_START_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_PARAM_REG, 1);
+ *cmds++ = 0x04008001;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_ADDR_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_OUTPUT_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_SP_FS_LENGTH_REG, 1);
+ *cmds++ = 0x0000000D;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_CLIP_CNTL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_GB_CLIP_ADJ, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XOFFSET, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XSCALE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YOFFSET, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YSCALE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZOFFSET, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZSCALE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X4, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y4, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z4, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W4, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X5, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y5, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z5, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W5, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_MINMAX, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_SIZE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_OFFSET, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_SCALE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SU_MODE_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SC_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_BR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_BR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_TSE_DEBUG_ECO, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER1_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER2_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER3_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MODE_CONTROL, 1);
+ *cmds++ = 0x00008000;
+ *cmds++ = cp_type0_packet(A3XX_RB_RENDER_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MSAA_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_ALPHA_REFERENCE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_BLEND_RED, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_BLEND_GREEN, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_BLEND_BLUE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_BLEND_ALPHA, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW0, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW1, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW2, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW3, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_COPY_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_BASE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_PITCH, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_INFO, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CLEAR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_INFO, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_PITCH, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CLEAR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_INFO, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_PITCH, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK_BF, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_LRZ_VSC_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_WINDOW_OFFSET, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_CONTROL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_ADDR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MIN, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MAX, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_GMEM_BASE_ADDR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_DEBUG_ECO_CONTROLS_ADDR, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER0_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER1_SELECT, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_RB_FRAME_BUFFER_DIMENSION, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4);
+ *cmds++ = (1 << CP_LOADSTATE_DSTOFFSET_SHIFT) |
+ (0 << CP_LOADSTATE_STATESRC_SHIFT) |
+ (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) |
+ (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+ *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT) |
+ (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT);
+ *cmds++ = 0x00400000;
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4);
+ *cmds++ = (2 << CP_LOADSTATE_DSTOFFSET_SHIFT) |
+ (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) |
+ (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+ *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT);
+ *cmds++ = 0x00400220;
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4);
+ *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) |
+ (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+ *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT);
+ *cmds++ = 0x00000000;
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_LOAD_STATE, 2 + count);
+ *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) |
+ (13 << CP_LOADSTATE_NUMOFUNITS_SHIFT);
+ *cmds++ = 0x00000000;
+
+ memcpy(cmds, _a3xx_pwron_fixup_fs_instructions, count << 2);
+
+ cmds += count;
+
+ *cmds++ = cp_type3_packet(CP_EXEC_CL, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1);
+ *cmds++ = 0x1E000150;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG);
+ *cmds++ = 0x1E000050;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_REG_RMW, 3);
+ *cmds++ = A3XX_RBBM_CLOCK_CTL;
+ *cmds++ = 0xFFFCFFFF;
+ *cmds++ = 0x00000000;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ /*
+ * Remember the number of dwords in the command buffer for when we
+ * program the indirect buffer call in the ringbuffer
+ */
+ adreno_dev->pwron_fixup_dwords =
+ (cmds - (unsigned int *) adreno_dev->pwron_fixup.hostptr);
+
+ /* Mark the flag in ->priv to show that we have the fix */
+ set_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv);
+ return 0;
+}
+
static int a3xx_rb_init(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb)
{
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index f449870..d1e2b43 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -177,6 +177,8 @@
/* Load a buffer with pre-fetch enabled */
#define CP_INDIRECT_BUFFER_PFE 0x3F
+#define CP_EXEC_CL 0x31
+
#define CP_LOADSTATE_DSTOFFSET_SHIFT 0x00000000
#define CP_LOADSTATE_STATESRC_SHIFT 0x00000010
#define CP_LOADSTATE_STATEBLOCKID_SHIFT 0x00000013
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index b8cf21f..947324b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -644,6 +644,10 @@
if (profile_ready)
total_sizedwords += 6; /* space for pre_ib and post_ib */
+ /* Add space for the power on shader fixup if we need it */
+ if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP)
+ total_sizedwords += 5;
+
ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
if (!ringcmds)
return -ENOSPC;
@@ -660,6 +664,18 @@
KGSL_CMD_INTERNAL_IDENTIFIER);
}
+ if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP) {
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ KGSL_PWRON_FIXUP_IDENTIFIER);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ CP_HDR_INDIRECT_BUFFER_PFD);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ adreno_dev->pwron_fixup.gpuaddr);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ adreno_dev->pwron_fixup_dwords);
+ }
+
/* Add any IB required for profiling if it is enabled */
if (profile_ready)
adreno_profile_preib_processing(rb->device, context->base.id,
@@ -1143,6 +1159,10 @@
adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
+ if (test_and_clear_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv) &&
+ test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
+ flags |= KGSL_CMD_FLAGS_PWRON_FIXUP;
+
if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
KGSL_DRV_ERR(device,
@@ -1158,7 +1178,7 @@
ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
drawctxt,
- (flags & KGSL_CMD_FLAGS_EOF),
+ flags,
&link[0], (cmds - link));
if (ret)
goto done;
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 9ab8d22..e623515 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -19,7 +19,6 @@
#include "kgsl_sharedmem.h"
/*default log levels is error for everything*/
-#define KGSL_LOG_LEVEL_DEFAULT 3
#define KGSL_LOG_LEVEL_MAX 7
struct dentry *kgsl_debugfs_dir;
@@ -180,13 +179,6 @@
if (!device->d_debugfs || IS_ERR(device->d_debugfs))
return;
- device->cmd_log = KGSL_LOG_LEVEL_DEFAULT;
- device->ctxt_log = KGSL_LOG_LEVEL_DEFAULT;
- device->drv_log = KGSL_LOG_LEVEL_DEFAULT;
- device->mem_log = KGSL_LOG_LEVEL_DEFAULT;
- device->pwr_log = KGSL_LOG_LEVEL_DEFAULT;
- device->ft_log = KGSL_LOG_LEVEL_DEFAULT;
-
debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device,
&cmd_log_fops);
debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device,
@@ -215,7 +207,6 @@
&pm_regs_enabled_fops);
debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
&pm_ib_enabled_fops);
- device->pm_dump_enable = 0;
debugfs_create_file("enable", 0644, pm_d_debugfs, device,
&pm_enabled_fops);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 883417f..103a751 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -124,6 +124,8 @@
| (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \
| (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT))
+#define KGSL_LOG_LEVEL_DEFAULT 3
+
static const struct kgsl_functable z180_functable;
static struct z180_device device_2d0 = {
@@ -149,6 +151,13 @@
},
.iomemname = KGSL_2D0_REG_MEMORY,
.ftbl = &z180_functable,
+ .cmd_log = KGSL_LOG_LEVEL_DEFAULT,
+ .ctxt_log = KGSL_LOG_LEVEL_DEFAULT,
+ .drv_log = KGSL_LOG_LEVEL_DEFAULT,
+ .mem_log = KGSL_LOG_LEVEL_DEFAULT,
+ .pwr_log = KGSL_LOG_LEVEL_DEFAULT,
+ .ft_log = KGSL_LOG_LEVEL_DEFAULT,
+ .pm_dump_enable = 0,
},
.cmdwin_lock = __SPIN_LOCK_INITIALIZER(device_2d1.cmdwin_lock),
};
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 2a5fea7..385947f 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -32,14 +32,12 @@
#define SHOW_PROGRESS
#define MAX_FIRMWARE_ID_LEN 10
#define FORCE_UPDATE false
+#define DO_LOCKDOWN false
#define INSIDE_FIRMWARE_UPDATE
#define FW_IMAGE_OFFSET 0x100
-
-#define BOOTLOADER_ID_OFFSET 0
-#define FLASH_PROPERTIES_OFFSET 2
-#define BLOCK_SIZE_OFFSET 3
-#define FW_BLOCK_COUNT_OFFSET 5
+/* 0 to ignore flash block check to speed up flash time */
+#define CHECK_FLASH_BLOCK_STATUS 1
#define REG_MAP (1 << 0)
#define UNLOCKED (1 << 1)
@@ -49,9 +47,6 @@
#define HAS_DISP_CONFIG (1 << 5)
#define HAS_CTRL1 (1 << 6)
-#define BLOCK_NUMBER_OFFSET 0
-#define BLOCK_DATA_OFFSET 2
-
#define RMI4_INFO_MAX_LEN 200
#define RMI4_STORE_TS_INFO(buf, id, rev, fw_ver) \
@@ -70,6 +65,7 @@
enum flash_command {
CMD_WRITE_FW_BLOCK = 0x2,
CMD_ERASE_ALL = 0x3,
+ CMD_WRITE_LOCKDOWN_BLOCK = 0x4,
CMD_READ_CONFIG_BLOCK = 0x5,
CMD_WRITE_CONFIG_BLOCK = 0x6,
CMD_ERASE_CONFIG = 0x7,
@@ -91,6 +87,23 @@
OPTION_CONTAIN_BOOTLOADER = 1,
};
+enum flash_offset {
+ OFFSET_BOOTLOADER_ID,
+ OFFSET_FLASH_PROPERTIES,
+ OFFSET_BLOCK_SIZE,
+ OFFSET_FW_BLOCK_COUNT,
+ OFFSET_BLOCK_NUMBER,
+ OFFSET_BLOCK_DATA,
+ OFFSET_FLASH_CONTROL,
+ OFFSET_FLASH_STATUS
+};
+
+enum flash_update_mode {
+ NORMAL = 1,
+ FORCE = 2,
+ LOCKDOWN = 8
+};
+
#define SLEEP_MODE_NORMAL (0x00)
#define SLEEP_MODE_SENSOR_SLEEP (0x01)
#define SLEEP_MODE_RESERVED0 (0x02)
@@ -101,9 +114,7 @@
#define ERASE_WAIT_MS (5 * 1000)
#define RESET_WAIT_MS (500)
-#define POLLING_MODE 0
-
-#define SLEEP_TIME_US 50
+#define SLEEP_TIME_US 100
static int fwu_wait_for_idle(int timeout_ms);
@@ -141,7 +152,8 @@
};
};
-struct image_header {
+struct image_content {
+ bool is_contain_build_info;
unsigned int checksum;
unsigned int image_size;
unsigned int config_size;
@@ -152,7 +164,10 @@
u16 package_id;
u16 package_revision_id;
unsigned int firmware_id;
- bool is_contain_build_info;
+ const unsigned char *firmware_data;
+ const unsigned char *config_data;
+ const unsigned char *lockdown_data;
+ unsigned short lockdown_block_count;
};
struct pdt_properties {
@@ -194,11 +209,28 @@
struct f34_flash_control {
union {
+ /* version 0 */
struct {
- unsigned char command:4;
+ unsigned char command_v0:4;
unsigned char status:3;
unsigned char program_enabled:1;
} __packed;
+ /* version 1 */
+ struct {
+ unsigned char command_v1:6;
+ unsigned char reserved:2;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
+struct f34_flash_status {
+ union {
+ struct {
+ unsigned char status:6;
+ unsigned char reserved:1;
+ unsigned char program_enabled:1;
+ } __packed;
unsigned char data[1];
};
};
@@ -222,6 +254,9 @@
struct synaptics_rmi4_fwu_handle {
bool initialized;
bool force_update;
+ bool do_lockdown;
+ bool interrupt_flag;
+ bool polling_mode;
char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
unsigned int image_size;
unsigned int data_pos;
@@ -233,31 +268,33 @@
unsigned char *read_config_buf;
const unsigned char *firmware_data;
const unsigned char *config_data;
+ const unsigned char *lockdown_data;
unsigned short block_size;
unsigned short fw_block_count;
unsigned short config_block_count;
+ unsigned short lockdown_block_count;
unsigned short perm_config_block_count;
unsigned short bl_config_block_count;
unsigned short disp_config_block_count;
unsigned short config_size;
unsigned short config_area;
- unsigned short addr_f34_flash_control;
unsigned short addr_f01_interrupt_register;
+ const unsigned char *data_buffer;
struct synaptics_rmi4_fn_desc f01_fd;
struct synaptics_rmi4_fn_desc f34_fd;
struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
struct synaptics_rmi4_data *rmi4_data;
- struct f34_flash_control flash_control;
struct f34_flash_properties flash_properties;
struct workqueue_struct *fwu_workqueue;
struct delayed_work fwu_work;
- char firmware_name[NAME_BUFFER_SIZE];
+ char image_name[NAME_BUFFER_SIZE];
+ struct image_content image_content;
char *ts_info;
};
static struct synaptics_rmi4_fwu_handle *fwu;
-static struct completion remove_complete;
+DECLARE_COMPLETION(fwu_remove_complete);
static unsigned int extract_uint(const unsigned char *ptr)
{
@@ -295,42 +332,80 @@
pkg_id[3] << 8 | pkg_id[2], build_id);
}
-static void parse_header(struct image_header *header,
- const unsigned char *fw_image)
+static void parse_header(void)
{
- struct image_header_data *data = (struct image_header_data *)fw_image;
- header->checksum = extract_uint(data->file_checksum);
- header->bootloader_version = data->bootloader_version;
- header->image_size = extract_uint(data->firmware_size);
- header->config_size = extract_uint(data->config_size);
- memcpy(header->product_id, data->product_id,
+ struct image_content *img = &fwu->image_content;
+ struct image_header_data *data =
+ (struct image_header_data *)fwu->data_buffer;
+ img->checksum = extract_uint(data->file_checksum);
+ img->bootloader_version = data->bootloader_version;
+ img->image_size = extract_uint(data->firmware_size);
+ img->config_size = extract_uint(data->config_size);
+ memcpy(img->product_id, data->product_id,
sizeof(data->product_id));
- header->product_id[sizeof(data->product_id)] = 0;
+ img->product_id[sizeof(data->product_id)] = 0;
- memcpy(header->product_info, data->product_info,
+ img->product_id[sizeof(data->product_info)] = 0;
+ memcpy(img->product_info, data->product_info,
sizeof(data->product_info));
- header->is_contain_build_info =
+ img->is_contain_build_info =
(data->options_firmware_id == (1 << OPTION_BUILD_INFO));
- if (header->is_contain_build_info) {
- header->package_id = (data->pkg_id_rev_msb << 8) |
+
+ if (img->is_contain_build_info) {
+ img->firmware_id = extract_uint(data->firmware_id);
+ img->package_id = (data->pkg_id_rev_msb << 8) |
data->pkg_id_lsb;
- header->package_revision_id = (data->pkg_id_rev_msb << 8) |
+ img->package_revision_id = (data->pkg_id_rev_msb << 8) |
data->pkg_id_rev_lsb;
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s Package ID %d Rev %d\n", __func__,
- header->package_id, header->package_revision_id);
+ img->package_id, img->package_revision_id);
- header->firmware_id = extract_uint(data->firmware_id);
+ img->firmware_id = extract_uint(data->firmware_id);
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s Firwmare build id %d\n", __func__,
- header->firmware_id);
+ img->firmware_id);
}
dev_dbg(&fwu->rmi4_data->i2c_client->dev,
"Firwmare size %d, config size %d\n",
- header->image_size,
- header->config_size);
+ img->image_size,
+ img->config_size);
+
+ /* get UI firmware offset */
+ if (img->image_size)
+ img->firmware_data = fwu->data_buffer + FW_IMAGE_OFFSET;
+ /* get config offset*/
+ if (img->config_size)
+ img->config_data = fwu->data_buffer + FW_IMAGE_OFFSET +
+ img->image_size;
+ /* get lockdown offset*/
+ switch (img->bootloader_version) {
+ case 3:
+ case 4:
+ img->lockdown_block_count = 4;
+ break;
+ case 5:
+ case 6:
+ img->lockdown_block_count = 5;
+ break;
+ default:
+ dev_warn(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Not support lockdown in " \
+ "bootloader version V%d\n",
+ __func__, img->bootloader_version);
+ img->lockdown_data = NULL;
+ }
+
+ img->lockdown_data = fwu->data_buffer +
+ FW_IMAGE_OFFSET -
+ img->lockdown_block_count * fwu->block_size;
+
+ fwu->lockdown_block_count = img->lockdown_block_count;
+ fwu->lockdown_data = img->lockdown_data;
+ fwu->config_data = img->config_data;
+ fwu->firmware_data = img->firmware_data;
return;
}
@@ -352,6 +427,62 @@
return 0;
}
+static unsigned short fwu_get_address(enum flash_offset type)
+{
+ int offset;
+ unsigned short addr = 0;
+ struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
+
+ switch (type) {
+ case OFFSET_BOOTLOADER_ID:
+ offset = 0;
+ addr = fwu->f34_fd.query_base_addr + offset;
+ break;
+ case OFFSET_FLASH_PROPERTIES:
+ offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
+ addr = fwu->f34_fd.query_base_addr + offset;
+ break;
+ case OFFSET_BLOCK_SIZE:
+ offset = ((fwu->f34_fd.version == 0) ? 3 : 2);
+ addr = fwu->f34_fd.query_base_addr + offset;
+ break;
+ case OFFSET_FW_BLOCK_COUNT:
+ offset = ((fwu->f34_fd.version == 0) ? 5 : 3);
+ addr = fwu->f34_fd.query_base_addr + offset;
+ break;
+ case OFFSET_BLOCK_NUMBER:
+ offset = 0;
+ addr = fwu->f34_fd.data_base_addr + offset;
+ break;
+ case OFFSET_BLOCK_DATA:
+ offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
+ addr = fwu->f34_fd.data_base_addr + offset;
+ break;
+ case OFFSET_FLASH_CONTROL:
+ offset = ((fwu->f34_fd.version == 0) ?
+ 2 + (fwu->block_size) : 2);
+ addr = fwu->f34_fd.data_base_addr + offset;
+ break;
+ case OFFSET_FLASH_STATUS:
+ if (fwu->f34_fd.version == 1) {
+ offset = 3;
+ addr = fwu->f34_fd.data_base_addr + offset;
+ } else if (fwu->f34_fd.version == 0) {
+ dev_warn(&i2c_client->dev,
+ "%s: F$34 version 0 does not contain " \
+ "flash status register\n",
+ __func__);
+ }
+ break;
+ default:
+ dev_err(&i2c_client->dev,
+ "%s: Unknown flash offset (%d)\n",
+ __func__, type);
+ break;
+ }
+ return addr;
+}
+
static int fwu_read_f34_queries(void)
{
int retval;
@@ -360,7 +491,7 @@
struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
+ fwu_get_address(OFFSET_BOOTLOADER_ID),
fwu->bootloader_id,
sizeof(fwu->bootloader_id));
if (retval < 0) {
@@ -371,7 +502,7 @@
}
retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET,
+ fwu_get_address(OFFSET_FLASH_PROPERTIES),
fwu->flash_properties.data,
sizeof(fwu->flash_properties.data));
if (retval < 0) {
@@ -397,7 +528,7 @@
count += 2;
retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET,
+ fwu_get_address(OFFSET_BLOCK_SIZE),
buf,
2);
if (retval < 0) {
@@ -410,13 +541,13 @@
batohs(&fwu->block_size, &(buf[0]));
retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + FW_BLOCK_COUNT_OFFSET,
+ fwu_get_address(OFFSET_FW_BLOCK_COUNT),
buf,
count);
if (retval < 0) {
dev_err(&i2c_client->dev,
- "%s: Failed to read block count info\n",
- __func__);
+ "%s: Failed to read block count info\n",
+ __func__);
return retval;
}
@@ -438,9 +569,6 @@
if (fwu->flash_properties.has_display_config)
batohs(&fwu->disp_config_block_count, &(buf[count]));
- fwu->addr_f34_flash_control = fwu->f34_fd.data_base_addr +
- BLOCK_DATA_OFFSET +
- fwu->block_size;
return 0;
}
@@ -461,18 +589,36 @@
return interrupt_status;
}
-static int fwu_read_f34_flash_status(void)
+static int fwu_read_f34_flash_status(unsigned char *status)
{
int retval;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->addr_f34_flash_control,
- fwu->flash_control.data,
- sizeof(fwu->flash_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
+ struct f34_flash_control flash_control;
+ struct f34_flash_status flash_status;
+
+ if (fwu->f34_fd.version == 1) {
+ retval = fwu->fn_ptr->read(fwu->rmi4_data,
+ fwu_get_address(OFFSET_FLASH_STATUS),
+ flash_status.data,
+ sizeof(flash_status.data));
+ if (retval < 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Failed to read flash status\n",
__func__);
- return retval;
+ return -EIO;
+ }
+ *status = flash_status.status;
+ } else {
+ retval = fwu->fn_ptr->read(fwu->rmi4_data,
+ fwu_get_address(OFFSET_FLASH_CONTROL),
+ flash_control.data,
+ sizeof(flash_control.data));
+ if (retval < 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Failed to read flash status\n",
+ __func__);
+ return -EIO;
+ }
+ *status = flash_control.status;
}
return 0;
}
@@ -492,22 +638,27 @@
__func__);
return retval;
}
+
+ fwu->polling_mode = false;
+
return 0;
}
static int fwu_write_f34_command(unsigned char cmd)
{
int retval;
+ struct f34_flash_control flash_control;
- fwu->flash_control.data[0] = cmd;
+ flash_control.data[0] = cmd;
+ fwu->interrupt_flag = false;
retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->addr_f34_flash_control,
- fwu->flash_control.data,
- sizeof(fwu->flash_control.data));
+ fwu_get_address(OFFSET_FLASH_CONTROL),
+ flash_control.data,
+ sizeof(flash_control.data));
if (retval < 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Failed to write command 0x%02x\n",
- __func__, fwu->flash_control.data[0]);
+ __func__, flash_control.data[0]);
return retval;
}
return 0;
@@ -518,18 +669,21 @@
int count = 0;
int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
do {
- #if POLLING_MODE
- fwu_read_f34_flash_status();
- #endif
- if (fwu->flash_control.command == 0x00)
+ if (fwu->interrupt_flag)
return 0;
-
- usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 100);
+ if (fwu->polling_mode)
+ if (fwu->intr_mask & fwu_read_interrupt_status())
+ return 0;
+ usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 1);
} while (count++ < timeout_count);
- fwu_read_f34_flash_status();
- if (fwu->flash_control.command == 0x00)
+ if (fwu->intr_mask & fwu_read_interrupt_status()) {
+ fwu->polling_mode = true;
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Switch to polling mode\n",
+ __func__);
return 0;
+ }
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Timed out waiting for idle status\n",
@@ -538,7 +692,7 @@
return -ETIMEDOUT;
}
-static enum flash_area fwu_go_nogo(struct image_header *header)
+static enum flash_area fwu_go_nogo(void)
{
int retval = 0;
int index = 0;
@@ -554,30 +708,53 @@
enum flash_area flash_area = NONE;
struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
struct f01_device_status f01_device_status;
+ struct image_content *img = &fwu->image_content;
if (fwu->force_update) {
flash_area = UI_FIRMWARE;
goto exit;
}
- if (header->is_contain_build_info) {
+ if (img->is_contain_build_info) {
/* if package id does not match, do not update firmware */
fwu->fn_ptr->read(fwu->rmi4_data,
fwu->f01_fd.query_base_addr + 17,
pkg_id,
sizeof(pkg_id));
- if (header->package_id != ((pkg_id[1] << 8) | pkg_id[0])) {
+ if (img->package_id != ((pkg_id[1] << 8) | pkg_id[0])) {
flash_area = MISMATCH;
goto exit;
}
- if (header->package_revision_id !=
+ if (img->package_revision_id !=
((pkg_id[3] << 8) | pkg_id[2])) {
flash_area = MISMATCH;
goto exit;
}
}
+ /* check firmware size */
+ if (fwu->fw_block_count*fwu->block_size != img->image_size) {
+ dev_err(&i2c_client->dev,
+ "%s: firmware size of device (%d) != .img (%d)\n",
+ __func__,
+ fwu->config_block_count * fwu->block_size,
+ img->image_size);
+ flash_area = NONE;
+ goto exit;
+ }
+
+ /* check config size */
+ if (fwu->config_block_count*fwu->block_size != img->config_size) {
+ dev_err(&i2c_client->dev,
+ "%s: config size of device (%d) != .img (%d)\n",
+ __func__,
+ fwu->config_block_count * fwu->block_size,
+ img->config_size);
+ flash_area = NONE;
+ goto exit;
+ }
+
retval = fwu_read_f01_device_status(&f01_device_status);
if (retval < 0) {
flash_area = NONE;
@@ -608,14 +785,21 @@
deviceFirmwareID = extract_uint(firmware_id);
/* .img firmware id */
- if (header->is_contain_build_info) {
+ if (img->is_contain_build_info) {
dev_err(&i2c_client->dev,
"%s: Image option contains build info.\n",
__func__);
- imageFirmwareID = header->firmware_id;
+ imageFirmwareID = img->firmware_id;
} else {
- strptr = strnstr(fwu->firmware_name, "PR",
- sizeof(fwu->firmware_name));
+ if (!fwu->image_name) {
+ dev_info(&i2c_client->dev,
+ "%s: Unknown image file name\n",
+ __func__);
+ flash_area = UI_FIRMWARE;
+ goto exit;
+ }
+ strptr = strnstr(fwu->image_name, "PR",
+ sizeof(fwu->image_name));
if (!strptr) {
dev_err(&i2c_client->dev,
"No valid PR number (PRxxxxxxx)" \
@@ -771,21 +955,41 @@
unsigned char command)
{
int retval;
+ unsigned char flash_status;
unsigned char block_offset[] = {0, 0};
unsigned short block_num;
+ unsigned short addr_block_data = fwu_get_address(OFFSET_BLOCK_DATA);
+ unsigned short addr_block_num = fwu_get_address(OFFSET_BLOCK_NUMBER);
struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
#ifdef SHOW_PROGRESS
- unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ?
- 10 : 100;
+ unsigned int progress;
+ unsigned char command_str[10];
+ switch (command) {
+ case CMD_WRITE_CONFIG_BLOCK:
+ progress = 10;
+ strlcpy(command_str, "config", 10);
+ break;
+ case CMD_WRITE_FW_BLOCK:
+ progress = 100;
+ strlcpy(command_str, "firmware", 10);
+ break;
+ case CMD_WRITE_LOCKDOWN_BLOCK:
+ progress = 1;
+ strlcpy(command_str, "lockdown", 10);
+ break;
+ default:
+ progress = 1;
+ strlcpy(command_str, "unknown", 10);
+ break;
+ }
#endif
dev_dbg(&i2c_client->dev,
"%s: Start to update %s blocks\n",
__func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware");
+ command_str);
retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+ addr_block_num,
block_offset,
sizeof(block_offset));
if (retval < 0) {
@@ -801,12 +1005,11 @@
dev_info(&i2c_client->dev,
"%s: update %s %3d / %3d\n",
__func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
+ command_str,
block_num, block_cnt);
#endif
retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+ addr_block_data,
block_ptr,
fwu->block_size);
if (retval < 0) {
@@ -832,21 +1035,28 @@
return retval;
}
- if (fwu->flash_control.status != 0x00) {
+ #if CHECK_FLASH_BLOCK_STATUS
+ retval = fwu_read_f34_flash_status(&flash_status);
+ if (retval < 0) {
dev_err(&i2c_client->dev,
- "%s: Flash block %d failed, status 0x%02X\n",
- __func__, block_num, retval);
+ "%s: Failed to read flash status (block %d)\n",
+ __func__, block_num);
return retval;
}
-
+ if (flash_status != 0x00) {
+ dev_err(&i2c_client->dev,
+ "%s: Flash block %d failed, status 0x%02X\n",
+ __func__, block_num, flash_status);
+ return -EINVAL;
+ }
+ #endif
block_ptr += fwu->block_size;
}
#ifdef SHOW_PROGRESS
dev_info(&i2c_client->dev,
"%s: update %s %3d / %3d\n",
__func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
+ command_str,
block_cnt, block_cnt);
#endif
return 0;
@@ -864,6 +1074,12 @@
fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
}
+static int fwu_write_lockdown_block(void)
+{
+ return fwu_write_blocks((unsigned char *)fwu->lockdown_data,
+ fwu->lockdown_block_count, CMD_WRITE_LOCKDOWN_BLOCK);
+}
+
static int fwu_write_bootloader_id(void)
{
int retval;
@@ -874,7 +1090,7 @@
fwu->bootloader_id[1]);
retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+ fwu_get_address(OFFSET_BLOCK_DATA),
fwu->bootloader_id,
sizeof(fwu->bootloader_id));
if (retval < 0) {
@@ -887,7 +1103,7 @@
return 0;
}
-static int fwu_enter_flash_prog(void)
+static int fwu_enter_flash_prog(bool force)
{
int retval;
struct f01_device_status f01_device_status;
@@ -961,63 +1177,7 @@
__func__);
return retval;
}
-
- return retval;
-}
-
-static int fwu_do_reflash(void)
-{
- int retval;
-
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
-
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Bootloader ID written\n",
- __func__);
-
- retval = fwu_write_f34_command(CMD_ERASE_ALL);
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase all command written\n",
- __func__);
-
- retval = fwu_wait_for_idle(ERASE_WAIT_MS);
- if (retval < 0)
- return retval;
-
- if (fwu->flash_control.status != 0x00) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase all command failed, status 0x%02X\n",
- __func__, retval);
- return -1;
- }
-
- if (fwu->firmware_data) {
- retval = fwu_write_firmware();
- if (retval < 0)
- return retval;
- pr_notice("%s: Firmware programmed\n", __func__);
- }
-
- if (fwu->config_data) {
- retval = fwu_write_configuration();
- if (retval < 0)
- return retval;
- pr_notice("%s: Configuration programmed\n", __func__);
- }
-
+ fwu->polling_mode = false;
return retval;
}
@@ -1025,7 +1185,7 @@
{
int retval;
- retval = fwu_enter_flash_prog();
+ retval = fwu_enter_flash_prog(false);
if (retval < 0)
return retval;
@@ -1087,42 +1247,38 @@
static int fwu_start_write_config(void)
{
int retval;
- struct image_header header;
+ int block_count;
switch (fwu->config_area) {
case UI_CONFIG_AREA:
+ block_count = fwu->config_block_count;
break;
case PERM_CONFIG_AREA:
if (!fwu->flash_properties.has_perm_config)
return -EINVAL;
+ block_count = fwu->perm_config_block_count;
break;
case BL_CONFIG_AREA:
if (!fwu->flash_properties.has_bl_config)
return -EINVAL;
+ block_count = fwu->bl_config_block_count;
break;
case DISP_CONFIG_AREA:
if (!fwu->flash_properties.has_display_config)
return -EINVAL;
+ block_count = fwu->disp_config_block_count;
break;
default:
return -EINVAL;
}
- if (fwu->ext_data_source)
- fwu->config_data = fwu->ext_data_source;
- else
- return -EINVAL;
-
- if (fwu->config_area == UI_CONFIG_AREA) {
- parse_header(&header, fwu->ext_data_source);
-
- if (header.config_size) {
- fwu->config_data = fwu->ext_data_source +
- FW_IMAGE_OFFSET +
- header.image_size;
- } else {
- return -EINVAL;
- }
+ if (fwu->image_size == block_count*fwu->block_size) {
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s: write config from config file\n",
+ __func__);
+ fwu->config_data = fwu->data_buffer;
+ } else {
+ parse_header();
}
pr_notice("%s: Start of write config process\n", __func__);
@@ -1141,6 +1297,58 @@
return retval;
}
+static int fwu_do_write_lockdown(bool reset)
+{
+ int retval;
+
+ pr_notice("%s: Start of lockdown process\n", __func__);
+
+ retval = fwu_enter_flash_prog(false);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Entered flash prog mode\n",
+ __func__);
+
+ if (fwu->flash_properties.unlocked == 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Device has been locked!\n",
+ __func__);
+ if (reset)
+ goto exit;
+ else
+ return -EINVAL;
+ }
+
+ retval = fwu_write_lockdown_block();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s:Lockdown device\n",
+ __func__);
+
+exit:
+ if (reset)
+ retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
+ else
+ retval = fwu_enter_flash_prog(true);
+
+ if (retval < 0)
+ return retval;
+
+ pr_notice("%s: End of lockdown process\n", __func__);
+
+ return retval;
+}
+
+static int fwu_start_write_lockdown(void)
+{
+ parse_header();
+ return fwu_do_write_lockdown(true);
+}
+
static int fwu_do_read_config(void)
{
int retval;
@@ -1149,14 +1357,6 @@
unsigned short block_count;
unsigned short index = 0;
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- goto exit;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
-
switch (fwu->config_area) {
case UI_CONFIG_AREA:
block_count = fwu->config_block_count;
@@ -1195,7 +1395,7 @@
block_offset[1] |= (fwu->config_area << 5);
retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
+ fwu_get_address(OFFSET_BLOCK_NUMBER),
block_offset,
sizeof(block_offset));
if (retval < 0) {
@@ -1223,7 +1423,7 @@
}
retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
+ fwu_get_address(OFFSET_BLOCK_DATA),
&fwu->read_config_buf[index],
fwu->block_size);
if (retval < 0) {
@@ -1237,7 +1437,71 @@
}
exit:
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
+ return retval;
+}
+
+static int fwu_do_reflash(void)
+{
+ int retval;
+ unsigned char flash_status;
+
+ if (fwu->do_lockdown) {
+ retval = fwu_do_write_lockdown(false);
+ if (retval < 0)
+ dev_warn(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Skip lockdown process.\n",
+ __func__);
+ }
+ retval = fwu_enter_flash_prog(false);
+ if (retval < 0)
+ return retval;
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Entered flash prog mode\n",
+ __func__);
+
+ retval = fwu_write_bootloader_id();
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Bootloader ID written\n",
+ __func__);
+
+ retval = fwu_write_f34_command(CMD_ERASE_ALL);
+ if (retval < 0)
+ return retval;
+
+ dev_dbg(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Erase all command written\n",
+ __func__);
+
+ retval = fwu_wait_for_idle(ERASE_WAIT_MS);
+ if (retval < 0)
+ return retval;
+
+ retval = fwu_read_f34_flash_status(&flash_status);
+ if (retval < 0)
+ return retval;
+ if (flash_status != 0x00) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Erase all command failed, status 0x%02X\n",
+ __func__, flash_status);
+ return -EINVAL;
+ }
+
+ if (fwu->firmware_data) {
+ retval = fwu_write_firmware();
+ if (retval < 0)
+ return retval;
+ pr_notice("%s: Firmware programmed\n", __func__);
+ }
+
+ if (fwu->config_data) {
+ retval = fwu_write_configuration();
+ if (retval < 0)
+ return retval;
+ pr_notice("%s: Configuration programmed\n", __func__);
+ }
return retval;
}
@@ -1245,45 +1509,47 @@
static int fwu_start_reflash(void)
{
int retval = 0;
- struct image_header header;
- const unsigned char *fw_image;
const struct firmware *fw_entry = NULL;
struct f01_device_status f01_device_status;
enum flash_area flash_area;
pr_notice("%s: Start of reflash process\n", __func__);
- if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) == 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "Firmware image name not given, skipping update\n");
- return 0;
- }
-
- if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
- NAME_BUFFER_SIZE) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "Firmware image name exceeds max length (%d), " \
- "skipping update\n", NAME_BUFFER_SIZE);
- return 0;
- }
-
if (fwu->ext_data_source)
- fw_image = fwu->ext_data_source;
+ dev_info(&fwu->rmi4_data->i2c_client->dev,
+ "%s Load .img file from commandline.\n",
+ __func__);
else {
- snprintf(fwu->firmware_name, NAME_BUFFER_SIZE, "%s",
+ if (strnlen(fwu->rmi4_data->fw_image_name,
+ NAME_BUFFER_SIZE) == 0) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "Firmware image name not given, "\
+ "skipping update\n");
+ return 0;
+ }
+
+ if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
+ NAME_BUFFER_SIZE) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "Firmware image name exceeds max length " \
+ "(%d), skipping update\n", NAME_BUFFER_SIZE);
+ return 0;
+ }
+
+ snprintf(fwu->image_name, NAME_BUFFER_SIZE, "%s",
fwu->rmi4_data->fw_image_name);
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s: Requesting firmware image %s\n",
- __func__, fwu->firmware_name);
+ __func__, fwu->image_name);
retval = request_firmware(&fw_entry,
- fwu->firmware_name,
+ fwu->image_name,
&fwu->rmi4_data->i2c_client->dev);
if (retval != 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Firmware image %s not available\n",
__func__,
- fwu->firmware_name);
+ fwu->image_name);
return -EINVAL;
}
@@ -1291,22 +1557,20 @@
"%s: Firmware image size = %d\n",
__func__, fw_entry->size);
- fw_image = fw_entry->data;
+ fwu->data_buffer = fw_entry->data;
}
- parse_header(&header, fw_image);
+ parse_header();
+ flash_area = fwu_go_nogo();
- if (header.image_size)
- fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
- if (header.config_size) {
- fwu->config_data = fw_image + FW_IMAGE_OFFSET +
- header.image_size;
+ if (fwu->rmi4_data->sensor_sleep) {
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "%s: Sensor sleeping\n",
+ __func__);
+ retval = -ENODEV;
+ goto exit;
}
-
- if (fwu->ext_data_source)
- flash_area = UI_FIRMWARE;
- else
- flash_area = fwu_go_nogo(&header);
+ fwu->rmi4_data->stay_awake = true;
switch (flash_area) {
case NONE:
@@ -1326,14 +1590,14 @@
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Unknown flash area\n",
__func__);
+ retval = -EINVAL;
goto exit;
}
- if (retval < 0) {
+ if (retval < 0)
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Failed to do reflash\n",
__func__);
- }
/* reset device */
fwu_reset_device();
@@ -1353,8 +1617,6 @@
dev_info(&fwu->rmi4_data->i2c_client->dev,
"%s: Device is in flash prog mode 0x%02X\n",
__func__, f01_device_status.status_code);
- retval = 0;
- goto exit;
}
exit:
@@ -1362,10 +1624,11 @@
release_firmware(fw_entry);
pr_notice("%s: End of reflash process\n", __func__);
+ fwu->rmi4_data->stay_awake = false;
return retval;
}
-int synaptics_fw_updater(unsigned char *fw_data)
+int synaptics_fw_updater(void)
{
int retval;
@@ -1383,7 +1646,6 @@
return -EBUSY;
}
- fwu->ext_data_source = fw_data;
fwu->config_area = UI_CONFIG_AREA;
retval = fwu_start_reflash();
@@ -1421,12 +1683,13 @@
(const void *)buf,
count);
+ fwu->data_buffer = fwu->ext_data_source;
fwu->data_pos += count;
return count;
}
-static ssize_t fwu_sysfs_fw_name_store(struct device *dev,
+static ssize_t fwu_sysfs_image_name_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
@@ -1450,7 +1713,7 @@
return count;
}
-static ssize_t fwu_sysfs_fw_name_show(struct device *dev,
+static ssize_t fwu_sysfs_image_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
@@ -1476,9 +1739,11 @@
retval = -EINVAL;
goto exit;
}
+ if (LOCKDOWN)
+ fwu->do_lockdown = true;
fwu->force_update = true;
- retval = synaptics_fw_updater(fwu->ext_data_source);
+ retval = synaptics_fw_updater();
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
"%s: Failed to do reflash\n",
@@ -1491,6 +1756,8 @@
exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
return retval;
}
@@ -1506,15 +1773,58 @@
goto exit;
}
+ if (input & LOCKDOWN) {
+ fwu->do_lockdown = true;
+ input &= ~LOCKDOWN;
+ }
+
+ if ((input != NORMAL) && (input != FORCE)) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
+ if (input == FORCE)
+ fwu->force_update = true;
+
+ retval = synaptics_fw_updater();
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to do reflash\n",
+ __func__);
+ goto exit;
+ }
+
+ retval = count;
+
+exit:
+ kfree(fwu->ext_data_source);
+ fwu->ext_data_source = NULL;
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
+ return retval;
+}
+
+static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
+
+ if (sscanf(buf, "%u", &input) != 1) {
+ retval = -EINVAL;
+ goto exit;
+ }
+
if (input != 1) {
retval = -EINVAL;
goto exit;
}
- retval = synaptics_fw_updater(fwu->ext_data_source);
+ retval = fwu_start_write_lockdown();
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
+ "%s: Failed to write lockdown block\n",
__func__);
goto exit;
}
@@ -1524,6 +1834,8 @@
exit:
kfree(fwu->ext_data_source);
fwu->ext_data_source = NULL;
+ fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
return retval;
}
@@ -1714,7 +2026,7 @@
unsigned char intr_mask)
{
if (fwu->intr_mask & intr_mask)
- fwu_read_f34_flash_status();
+ fwu->interrupt_flag = true;
return;
}
@@ -1731,8 +2043,8 @@
static struct device_attribute attrs[] = {
__ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
- fwu_sysfs_fw_name_show,
- fwu_sysfs_fw_name_store),
+ fwu_sysfs_image_name_show,
+ fwu_sysfs_image_name_store),
__ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_force_reflash_store),
@@ -1742,6 +2054,9 @@
__ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_write_config_store),
+ __ATTR(writelockdown, S_IWUGO,
+ synaptics_rmi4_show_error,
+ fwu_sysfs_write_lockdown_store),
__ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
synaptics_rmi4_show_error,
fwu_sysfs_read_config_store),
@@ -1851,6 +2166,9 @@
fwu->initialized = true;
fwu->force_update = FORCE_UPDATE;
+ fwu->do_lockdown = DO_LOCKDOWN;
+ fwu->initialized = true;
+ fwu->polling_mode = false;
retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
&dev_attr_data);
@@ -1900,24 +2218,23 @@
msecs_to_jiffies(1000));
#endif
- init_completion(&remove_complete);
-
return 0;
exit_free_ts_info:
debugfs_remove(temp);
exit_remove_attrs:
-for (attr_count--; attr_count >= 0; attr_count--) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
-}
+ for (attr_count--; attr_count >= 0; attr_count--) {
+ sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
+ &attrs[attr_count].attr);
+ }
-sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+ sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
exit_free_mem:
kfree(fwu->fn_ptr);
exit_free_fwu:
kfree(fwu);
+ fwu = NULL;
exit:
return 0;
@@ -1934,10 +2251,11 @@
&attrs[attr_count].attr);
}
+ kfree(fwu->read_config_buf);
kfree(fwu->fn_ptr);
kfree(fwu);
- complete(&remove_complete);
+ complete(&fwu_remove_complete);
return;
}
@@ -1957,7 +2275,7 @@
synaptics_rmi4_fwu_init,
synaptics_rmi4_fwu_remove,
synaptics_rmi4_fwu_attn);
- wait_for_completion(&remove_complete);
+ wait_for_completion(&fwu_remove_complete);
return;
}
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 0b234ce..f8ab5f4 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -93,6 +93,8 @@
#define RMI4_I2C_LPM_LOAD_UA 10
#define RMI4_GPIO_SLEEP_LOW_US 10000
+#define F12_FINGERS_TO_SUPPORT 10
+#define MAX_F11_TOUCH_WIDTH 15
static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
unsigned short addr, unsigned char *data,
@@ -168,6 +170,131 @@
};
};
+struct synaptics_rmi4_f12_query_5 {
+ union {
+ struct {
+ unsigned char size_of_query6;
+ struct {
+ unsigned char ctrl0_is_present:1;
+ unsigned char ctrl1_is_present:1;
+ unsigned char ctrl2_is_present:1;
+ unsigned char ctrl3_is_present:1;
+ unsigned char ctrl4_is_present:1;
+ unsigned char ctrl5_is_present:1;
+ unsigned char ctrl6_is_present:1;
+ unsigned char ctrl7_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl8_is_present:1;
+ unsigned char ctrl9_is_present:1;
+ unsigned char ctrl10_is_present:1;
+ unsigned char ctrl11_is_present:1;
+ unsigned char ctrl12_is_present:1;
+ unsigned char ctrl13_is_present:1;
+ unsigned char ctrl14_is_present:1;
+ unsigned char ctrl15_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl16_is_present:1;
+ unsigned char ctrl17_is_present:1;
+ unsigned char ctrl18_is_present:1;
+ unsigned char ctrl19_is_present:1;
+ unsigned char ctrl20_is_present:1;
+ unsigned char ctrl21_is_present:1;
+ unsigned char ctrl22_is_present:1;
+ unsigned char ctrl23_is_present:1;
+ } __packed;
+ struct {
+ unsigned char ctrl24_is_present:1;
+ unsigned char ctrl25_is_present:1;
+ unsigned char ctrl26_is_present:1;
+ unsigned char ctrl27_is_present:1;
+ unsigned char ctrl28_is_present:1;
+ unsigned char ctrl29_is_present:1;
+ unsigned char ctrl30_is_present:1;
+ unsigned char ctrl31_is_present:1;
+ } __packed;
+ };
+ unsigned char data[5];
+ };
+};
+
+struct synaptics_rmi4_f12_query_8 {
+ union {
+ struct {
+ unsigned char size_of_query9;
+ struct {
+ unsigned char data0_is_present:1;
+ unsigned char data1_is_present:1;
+ unsigned char data2_is_present:1;
+ unsigned char data3_is_present:1;
+ unsigned char data4_is_present:1;
+ unsigned char data5_is_present:1;
+ unsigned char data6_is_present:1;
+ unsigned char data7_is_present:1;
+ } __packed;
+ struct {
+ unsigned char data8_is_present:1;
+ unsigned char data9_is_present:1;
+ unsigned char data10_is_present:1;
+ unsigned char data11_is_present:1;
+ unsigned char data12_is_present:1;
+ unsigned char data13_is_present:1;
+ unsigned char data14_is_present:1;
+ unsigned char data15_is_present:1;
+ } __packed;
+ };
+ unsigned char data[3];
+ };
+};
+
+struct synaptics_rmi4_f12_ctrl_8 {
+ union {
+ struct {
+ unsigned char max_x_coord_lsb;
+ unsigned char max_x_coord_msb;
+ unsigned char max_y_coord_lsb;
+ unsigned char max_y_coord_msb;
+ unsigned char rx_pitch_lsb;
+ unsigned char rx_pitch_msb;
+ unsigned char tx_pitch_lsb;
+ unsigned char tx_pitch_msb;
+ unsigned char low_rx_clip;
+ unsigned char high_rx_clip;
+ unsigned char low_tx_clip;
+ unsigned char high_tx_clip;
+ unsigned char num_of_rx;
+ unsigned char num_of_tx;
+ };
+ unsigned char data[14];
+ };
+};
+
+struct synaptics_rmi4_f12_ctrl_23 {
+ union {
+ struct {
+ unsigned char obj_type_enable;
+ unsigned char max_reported_objects;
+ };
+ unsigned char data[2];
+ };
+};
+
+struct synaptics_rmi4_f12_finger_data {
+ unsigned char object_type_and_status;
+ unsigned char x_lsb;
+ unsigned char x_msb;
+ unsigned char y_lsb;
+ unsigned char y_msb;
+#ifdef REPORT_2D_Z
+ unsigned char z;
+#endif
+#ifdef REPORT_2D_W
+ unsigned char wx;
+ unsigned char wy;
+#endif
+};
+
struct synaptics_rmi4_f1a_query {
union {
struct {
@@ -223,6 +350,13 @@
struct synaptics_rmi4_f1a_control button_control;
};
+struct synaptics_rmi4_f12_extra_data {
+ unsigned char data1_offset;
+ unsigned char data15_offset;
+ unsigned char data15_size;
+ unsigned char data15_data[(F12_FINGERS_TO_SUPPORT + 7) / 8];
+};
+
struct synaptics_rmi4_exp_fn {
enum exp_fn fn_type;
bool inserted;
@@ -360,8 +494,8 @@
retval = synaptics_rmi4_reset_device(rmi4_data);
if (retval < 0) {
dev_err(dev,
- "%s: Failed to issue reset command, error = %d\n",
- __func__, retval);
+ "%s: Failed to issue reset command, error = %d\n",
+ __func__, retval);
return retval;
}
@@ -817,10 +951,7 @@
if (!touch_count)
input_mt_sync(rmi4_data->input_dev);
#else
- /* sync after groups of events */
- #ifdef KERNEL_ABOVE_3_7
- input_mt_sync_frame(rmi4_data->input_dev);
- #endif
+ input_mt_report_pointer_emulation(rmi4_data->input_dev, false);
#endif
input_sync(rmi4_data->input_dev);
@@ -828,6 +959,125 @@
return touch_count;
}
+ /**
+ * synaptics_rmi4_f12_abs_report()
+ *
+ * Called by synaptics_rmi4_report_touch() when valid Function $12
+ * finger data has been detected.
+ *
+ * This function reads the Function $12 data registers, determines the
+ * status of each finger supported by the Function, processes any
+ * necessary coordinate manipulation, reports the finger data to
+ * the input subsystem, and returns the number of fingers detected.
+ */
+static int synaptics_rmi4_f12_abs_report(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ unsigned char touch_count = 0; /* number of touch points */
+ unsigned char finger;
+ unsigned char fingers_to_process;
+ unsigned char finger_status;
+ unsigned char size_of_2d_data;
+ unsigned short data_addr;
+ int x;
+ int y;
+ int wx;
+ int wy;
+ struct synaptics_rmi4_f12_extra_data *extra_data;
+ struct synaptics_rmi4_f12_finger_data *data;
+ struct synaptics_rmi4_f12_finger_data *finger_data;
+
+ fingers_to_process = fhandler->num_of_data_points;
+ data_addr = fhandler->full_addr.data_base;
+ extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+ size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ data_addr + extra_data->data1_offset,
+ (unsigned char *)fhandler->data,
+ fingers_to_process * size_of_2d_data);
+ if (retval < 0)
+ return 0;
+
+ data = (struct synaptics_rmi4_f12_finger_data *)fhandler->data;
+
+ for (finger = 0; finger < fingers_to_process; finger++) {
+ finger_data = data + finger;
+ finger_status = finger_data->object_type_and_status & MASK_2BIT;
+
+ /*
+ * Each 2-bit finger status field represents the following:
+ * 00 = finger not present
+ * 01 = finger present and data accurate
+ * 10 = finger present but data may be inaccurate
+ * 11 = reserved
+ */
+#ifdef TYPE_B_PROTOCOL
+ input_mt_slot(rmi4_data->input_dev, finger);
+ input_mt_report_slot_state(rmi4_data->input_dev,
+ MT_TOOL_FINGER, finger_status != 0);
+#endif
+
+ if (finger_status) {
+ x = (finger_data->x_msb << 8) | (finger_data->x_lsb);
+ y = (finger_data->y_msb << 8) | (finger_data->y_lsb);
+#ifdef REPORT_2D_W
+ wx = finger_data->wx;
+ wy = finger_data->wy;
+#endif
+
+ if (rmi4_data->board->x_flip)
+ x = rmi4_data->sensor_max_x - x;
+ if (rmi4_data->board->y_flip)
+ y = rmi4_data->sensor_max_y - y;
+
+ dev_dbg(&rmi4_data->i2c_client->dev,
+ "%s: Finger %d:\n"
+ "status = 0x%02x\n"
+ "x = %d\n"
+ "y = %d\n"
+ "wx = %d\n"
+ "wy = %d\n",
+ __func__, finger,
+ finger_status,
+ x, y, wx, wy);
+
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, 1);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, 1);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_X, x);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_POSITION_Y, y);
+#ifdef REPORT_2D_W
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MAJOR, max(wx, wy));
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MINOR, min(wx, wy));
+#endif
+#ifndef TYPE_B_PROTOCOL
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+ touch_count++;
+ }
+ }
+
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOUCH, touch_count > 0);
+ input_report_key(rmi4_data->input_dev,
+ BTN_TOOL_FINGER, touch_count > 0);
+#ifndef TYPE_B_PROTOCOL
+ if (!touch_count)
+ input_mt_sync(rmi4_data->input_dev);
+#endif
+ input_mt_report_pointer_emulation(rmi4_data->input_dev, false);
+ input_sync(rmi4_data->input_dev);
+
+ return touch_count;
+}
+
static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn *fhandler)
{
@@ -955,6 +1205,16 @@
rmi4_data->fingers_on_2d = false;
break;
+ case SYNAPTICS_RMI4_F12:
+ touch_count_2d = synaptics_rmi4_f12_abs_report(rmi4_data,
+ fhandler);
+
+ if (touch_count_2d)
+ rmi4_data->fingers_on_2d = true;
+ else
+ rmi4_data->fingers_on_2d = false;
+ break;
+
case SYNAPTICS_RMI4_F1A:
synaptics_rmi4_f1a_report(rmi4_data, fhandler);
break;
@@ -1045,6 +1305,7 @@
return IRQ_HANDLED;
}
+#ifdef CONFIG_OF
static int synaptics_rmi4_parse_dt(struct device *dev,
struct synaptics_rmi4_platform_data *rmi4_pdata)
{
@@ -1127,6 +1388,13 @@
}
return 0;
}
+#else
+static inline int synaptics_rmi4_parse_dt(struct device *dev,
+ struct synaptics_rmi4_platform_data *rmi4_pdata)
+{
+ return 0;
+}
+#endif
/**
* synaptics_rmi4_irq_enable()
@@ -1237,6 +1505,8 @@
rmi4_data->sensor_max_x,
rmi4_data->sensor_max_y);
+ rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH;
+
fhandler->intr_reg_num = (intr_count + 7) / 8;
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -1257,6 +1527,212 @@
return retval;
}
+static int synaptics_rmi4_f12_set_enables(struct synaptics_rmi4_data *rmi4_data,
+ unsigned short ctrl28)
+{
+ int retval;
+ static unsigned short ctrl_28_address;
+
+ if (ctrl28)
+ ctrl_28_address = ctrl28;
+
+ retval = synaptics_rmi4_i2c_write(rmi4_data,
+ ctrl_28_address,
+ &rmi4_data->report_enable,
+ sizeof(rmi4_data->report_enable));
+ if (retval < 0)
+ return retval;
+
+ return retval;
+}
+
+ /**
+ * synaptics_rmi4_f12_init()
+ *
+ * Called by synaptics_rmi4_query_device().
+ *
+ * This funtion parses information from the Function 12 registers and
+ * determines the number of fingers supported, offset to the data1
+ * register, x and y data ranges, offset to the associated interrupt
+ * status register, interrupt bit mask, and allocates memory resources
+ * for finger data acquisition.
+ */
+static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
+ struct synaptics_rmi4_fn *fhandler,
+ struct synaptics_rmi4_fn_desc *fd,
+ unsigned int intr_count)
+{
+ int retval;
+ unsigned char ii;
+ unsigned char intr_offset;
+ unsigned char size_of_2d_data;
+ unsigned char size_of_query8;
+ unsigned char ctrl_8_offset;
+ unsigned char ctrl_23_offset;
+ unsigned char ctrl_28_offset;
+ unsigned char num_of_fingers;
+ struct synaptics_rmi4_f12_extra_data *extra_data;
+ struct synaptics_rmi4_f12_query_5 query_5;
+ struct synaptics_rmi4_f12_query_8 query_8;
+ struct synaptics_rmi4_f12_ctrl_8 ctrl_8;
+ struct synaptics_rmi4_f12_ctrl_23 ctrl_23;
+
+ fhandler->fn_number = fd->fn_number;
+ fhandler->num_of_data_sources = fd->intr_src_count;
+ fhandler->extra = kmalloc(sizeof(*extra_data), GFP_KERNEL);
+ extra_data = (struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+ size_of_2d_data = sizeof(struct synaptics_rmi4_f12_finger_data);
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ fhandler->full_addr.query_base + 5,
+ query_5.data,
+ sizeof(query_5.data));
+ if (retval < 0)
+ return retval;
+
+ ctrl_8_offset = query_5.ctrl0_is_present +
+ query_5.ctrl1_is_present +
+ query_5.ctrl2_is_present +
+ query_5.ctrl3_is_present +
+ query_5.ctrl4_is_present +
+ query_5.ctrl5_is_present +
+ query_5.ctrl6_is_present +
+ query_5.ctrl7_is_present;
+
+ ctrl_23_offset = ctrl_8_offset +
+ query_5.ctrl8_is_present +
+ query_5.ctrl9_is_present +
+ query_5.ctrl10_is_present +
+ query_5.ctrl11_is_present +
+ query_5.ctrl12_is_present +
+ query_5.ctrl13_is_present +
+ query_5.ctrl14_is_present +
+ query_5.ctrl15_is_present +
+ query_5.ctrl16_is_present +
+ query_5.ctrl17_is_present +
+ query_5.ctrl18_is_present +
+ query_5.ctrl19_is_present +
+ query_5.ctrl20_is_present +
+ query_5.ctrl21_is_present +
+ query_5.ctrl22_is_present;
+
+ ctrl_28_offset = ctrl_23_offset +
+ query_5.ctrl23_is_present +
+ query_5.ctrl24_is_present +
+ query_5.ctrl25_is_present +
+ query_5.ctrl26_is_present +
+ query_5.ctrl27_is_present;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_23_offset,
+ ctrl_23.data,
+ sizeof(ctrl_23.data));
+ if (retval < 0)
+ return retval;
+
+ /* Maximum number of fingers supported */
+ fhandler->num_of_data_points = min(ctrl_23.max_reported_objects,
+ (unsigned char)F12_FINGERS_TO_SUPPORT);
+
+ num_of_fingers = fhandler->num_of_data_points;
+ rmi4_data->num_of_fingers = num_of_fingers;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ fhandler->full_addr.query_base + 7,
+ &size_of_query8,
+ sizeof(size_of_query8));
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ fhandler->full_addr.query_base + 8,
+ query_8.data,
+ size_of_query8);
+ if (retval < 0)
+ return retval;
+
+ /* Determine the presence of the Data0 register */
+ extra_data->data1_offset = query_8.data0_is_present;
+
+ if ((size_of_query8 >= 3) && (query_8.data15_is_present)) {
+ extra_data->data15_offset = query_8.data0_is_present +
+ query_8.data1_is_present +
+ query_8.data2_is_present +
+ query_8.data3_is_present +
+ query_8.data4_is_present +
+ query_8.data5_is_present +
+ query_8.data6_is_present +
+ query_8.data7_is_present +
+ query_8.data8_is_present +
+ query_8.data9_is_present +
+ query_8.data10_is_present +
+ query_8.data11_is_present +
+ query_8.data12_is_present +
+ query_8.data13_is_present +
+ query_8.data14_is_present;
+ extra_data->data15_size = (num_of_fingers + 7) / 8;
+ } else {
+ extra_data->data15_size = 0;
+ }
+
+ rmi4_data->report_enable = RPT_DEFAULT;
+#ifdef REPORT_2D_Z
+ rmi4_data->report_enable |= RPT_Z;
+#endif
+#ifdef REPORT_2D_W
+ rmi4_data->report_enable |= (RPT_WX | RPT_WY);
+#endif
+
+ retval = synaptics_rmi4_f12_set_enables(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_28_offset);
+ if (retval < 0)
+ return retval;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ fhandler->full_addr.ctrl_base + ctrl_8_offset,
+ ctrl_8.data,
+ sizeof(ctrl_8.data));
+ if (retval < 0)
+ return retval;
+
+ /* Maximum x and y */
+ rmi4_data->sensor_max_x =
+ ((unsigned short)ctrl_8.max_x_coord_lsb << 0) |
+ ((unsigned short)ctrl_8.max_x_coord_msb << 8);
+ rmi4_data->sensor_max_y =
+ ((unsigned short)ctrl_8.max_y_coord_lsb << 0) |
+ ((unsigned short)ctrl_8.max_y_coord_msb << 8);
+ dev_dbg(&rmi4_data->i2c_client->dev,
+ "%s: Function %02x max x = %d max y = %d\n",
+ __func__, fhandler->fn_number,
+ rmi4_data->sensor_max_x,
+ rmi4_data->sensor_max_y);
+
+ rmi4_data->num_of_rx = ctrl_8.num_of_rx;
+ rmi4_data->num_of_tx = ctrl_8.num_of_tx;
+ rmi4_data->max_touch_width = max(rmi4_data->num_of_rx,
+ rmi4_data->num_of_tx);
+
+ fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num != 0)
+ fhandler->intr_reg_num -= 1;
+
+ /* Set an enable bit for each data source */
+ intr_offset = intr_count % 8;
+ fhandler->intr_mask = 0;
+ for (ii = intr_offset;
+ ii < ((fd->intr_src_count & MASK_3BIT) +
+ intr_offset);
+ ii++)
+ fhandler->intr_mask |= 1 << ii;
+
+ /* Allocate memory for finger data storage space */
+ fhandler->data_size = num_of_fingers * size_of_2d_data;
+ fhandler->data = kmalloc(fhandler->data_size, GFP_KERNEL);
+
+ return retval;
+}
+
static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn *fhandler)
{
@@ -1601,6 +2077,26 @@
return retval;
break;
+ case SYNAPTICS_RMI4_F12:
+ if (rmi_fd.intr_src_count == 0)
+ break;
+
+ retval = synaptics_rmi4_alloc_fh(&fhandler,
+ &rmi_fd, page_number);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to alloc for F%d\n",
+ __func__,
+ rmi_fd.fn_number);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_f12_init(rmi4_data,
+ fhandler, &rmi_fd, intr_count);
+ if (retval < 0)
+ return retval;
+ break;
+
case SYNAPTICS_RMI4_F1A:
if (rmi_fd.intr_src_count == 0)
break;
@@ -1744,6 +2240,7 @@
{
int retval;
struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_fn *next_fhandler;
struct synaptics_rmi4_device_info *rmi;
rmi = &(rmi4_data->rmi4_mod_info);
@@ -1757,11 +2254,14 @@
}
if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ list_for_each_entry_safe(fhandler, next_fhandler,
+ &rmi->support_fn_list, link) {
if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
synaptics_rmi4_f1a_kfree(fhandler);
- else
+ else {
kfree(fhandler->data);
+ kfree(fhandler->extra);
+ }
kfree(fhandler);
}
}
@@ -2125,6 +2625,7 @@
unsigned char attr_count;
struct synaptics_rmi4_f1a_handle *f1a;
struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_fn *next_fhandler;
struct synaptics_rmi4_data *rmi4_data;
struct synaptics_rmi4_device_info *rmi;
struct synaptics_rmi4_platform_data *platform_data =
@@ -2260,7 +2761,10 @@
#ifdef REPORT_2D_W
input_set_abs_params(rmi4_data->input_dev,
ABS_MT_TOUCH_MAJOR, 0,
- MAX_ABS_MT_TOUCH_MAJOR, 0, 0);
+ rmi4_data->max_touch_width, 0, 0);
+ input_set_abs_params(rmi4_data->input_dev,
+ ABS_MT_TOUCH_MINOR, 0,
+ rmi4_data->max_touch_width, 0, 0);
#endif
#ifdef TYPE_B_PROTOCOL
@@ -2381,11 +2885,14 @@
err_register_input:
if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ list_for_each_entry_safe(fhandler, next_fhandler,
+ &rmi->support_fn_list, link) {
if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
synaptics_rmi4_f1a_kfree(fhandler);
- else
+ else {
kfree(fhandler->data);
+ kfree(fhandler->extra);
+ }
kfree(fhandler);
}
}
@@ -2421,6 +2928,7 @@
{
unsigned char attr_count;
struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_fn *next_fhandler;
struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client);
struct synaptics_rmi4_device_info *rmi;
@@ -2444,11 +2952,14 @@
input_unregister_device(rmi4_data->input_dev);
if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
+ list_for_each_entry_safe(fhandler, next_fhandler,
+ &rmi->support_fn_list, link) {
if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
synaptics_rmi4_f1a_kfree(fhandler);
- else
+ else {
kfree(fhandler->data);
+ kfree(fhandler->extra);
+ }
kfree(fhandler);
}
}
@@ -2591,6 +3102,11 @@
container_of(h, struct synaptics_rmi4_data,
early_suspend);
+ if (rmi4_data->stay_awake)
+ rmi4_data->staying_awake = true;
+ else
+ rmi4_data->staying_awake = false;
+
rmi4_data->touch_stopped = true;
wake_up(&rmi4_data->wait);
synaptics_rmi4_irq_enable(rmi4_data, false);
@@ -2617,6 +3133,9 @@
container_of(h, struct synaptics_rmi4_data,
early_suspend);
+ if (rmi4_data->staying_awake)
+ return;
+
if (rmi4_data->full_pm_cycle)
synaptics_rmi4_resume(&(rmi4_data->input_dev->dev));
@@ -2761,6 +3280,12 @@
struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
int retval;
+ if (rmi4_data->stay_awake) {
+ rmi4_data->staying_awake = true;
+ return 0;
+ } else
+ rmi4_data->staying_awake = false;
+
if (rmi4_data->suspended) {
dev_info(dev, "Already in suspend state\n");
return 0;
@@ -2812,6 +3337,9 @@
struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
int retval;
+ if (rmi4_data->staying_awake)
+ return 0;
+
if (!rmi4_data->suspended) {
dev_info(dev, "Already in awake state\n");
return 0;
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index 5f6d6ce..677a2fe 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -45,6 +45,7 @@
#define SYNAPTICS_RMI4_F01 (0x01)
#define SYNAPTICS_RMI4_F11 (0x11)
+#define SYNAPTICS_RMI4_F12 (0x12)
#define SYNAPTICS_RMI4_F1A (0x1a)
#define SYNAPTICS_RMI4_F34 (0x34)
#define SYNAPTICS_RMI4_F54 (0x54)
@@ -69,7 +70,7 @@
#define MASK_2BIT 0x03
#define MASK_1BIT 0x01
-#define NAME_BUFFER_SIZE 128
+#define NAME_BUFFER_SIZE 256
/*
* struct synaptics_rmi4_fn_desc - function descriptor fields in PDT
@@ -85,9 +86,12 @@
unsigned char cmd_base_addr;
unsigned char ctrl_base_addr;
unsigned char data_base_addr;
- unsigned char intr_src_count;
+ unsigned char intr_src_count:3;
+ unsigned char reserved_b3_b4:2;
+ unsigned char version:2;
+ unsigned char reserved_b7:1;
unsigned char fn_number;
-};
+} __packed;
/*
* synaptics_rmi4_fn_full_addr - full 16-bit base addresses
@@ -129,6 +133,7 @@
struct list_head link;
int data_size;
void *data;
+ void *extra;
};
/*
@@ -214,6 +219,8 @@
unsigned char num_of_rx;
unsigned char num_of_tx;
unsigned char num_of_fingers;
+ unsigned char max_touch_width;
+ unsigned char report_enable;
unsigned char intr_mask[MAX_INTR_REGISTERS];
unsigned short num_of_intr_regs;
unsigned short f01_query_base_addr;
@@ -232,6 +239,8 @@
bool fw_updating;
bool suspended;
wait_queue_head_t wait;
+ bool stay_awake;
+ bool staying_awake;
int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
unsigned char *data, unsigned short length);
int (*i2c_write)(struct synaptics_rmi4_data *pdata, unsigned short addr,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index 73226ed..3288e9c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -151,7 +151,7 @@
{0x03, 0x00},
{0x10, 0x13},
- {0x11, 0x93},
+ {0x11, 0x90}, /* no H/V flip */
{0x12, 0x00},
{0x0b, 0xaa},
{0x0c, 0xaa},
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 36a2658..a612e5f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -526,8 +526,15 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
- if (response)
+ if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
+ if (response->status) {
+ dprintk(VIDC_ERR,
+ "Load resource response from FW : 0x%x",
+ response->status);
+ msm_comm_generate_session_error(inst);
+ }
+ }
else
dprintk(VIDC_ERR,
"Failed to get valid response for load resource\n");
@@ -901,6 +908,7 @@
vb = list_first_entry(&q->vb2_bufq.queued_list,
struct vb2_buffer, queued_entry);
vb->v4l2_planes[0].bytesused = 0;
+ vb->v4l2_planes[0].data_offset = 0;
vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
mutex_lock(&q->lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
@@ -932,12 +940,14 @@
}
vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
+ vb->v4l2_planes[0].data_offset = fill_buf_done->offset1;
vb->v4l2_buf.flags = V4L2_QCOM_BUF_FLAG_CODECCONFIG;
vb->v4l2_buf.timestamp = ns_to_timeval(0);
- dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
+ dprintk(VIDC_DBG, "Filled length = %d; offset = %d; flags %x\n",
vb->v4l2_planes[0].bytesused,
+ vb->v4l2_planes[0].data_offset,
vb->v4l2_buf.flags);
mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
@@ -2341,6 +2351,7 @@
queued_entry);
if (vb) {
vb->v4l2_planes[0].bytesused = 0;
+ vb->v4l2_planes[0].data_offset = 0;
mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
vb2_buffer_done(vb,
VB2_BUF_STATE_DONE);
@@ -2358,6 +2369,7 @@
queued_entry);
if (vb) {
vb->v4l2_planes[0].bytesused = 0;
+ vb->v4l2_planes[0].data_offset = 0;
mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
vb2_buffer_done(vb,
VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 58e008d..e3c9b2a 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -134,10 +134,18 @@
static void wfd_vidbuf_wait_prepare(struct vb2_queue *q)
{
+ struct file *priv_data = (struct file *)(q->drv_priv);
+ struct wfd_inst *inst = file_to_inst(priv_data);
+
+ mutex_unlock(&inst->vb2_lock);
}
static void wfd_vidbuf_wait_finish(struct vb2_queue *q)
{
+ struct file *priv_data = (struct file *)(q->drv_priv);
+ struct wfd_inst *inst = file_to_inst(priv_data);
+
+ mutex_lock(&inst->vb2_lock);
}
static unsigned long wfd_enc_addr_to_mdp_addr(struct wfd_inst *inst,
@@ -1026,10 +1034,9 @@
WFD_MSG_DBG("Waiting to dequeue buffer\n");
- /* XXX: If we switch to non-blocking mode in the future,
- * we'll need to lock this with vb2_lock */
- rc = vb2_dqbuf(&inst->vid_bufq, b, false /* blocking */);
-
+ mutex_lock(&inst->vb2_lock);
+ rc = vb2_dqbuf(&inst->vid_bufq, b, false);
+ mutex_unlock(&inst->vb2_lock);
if (rc)
WFD_MSG_ERR("Failed to dequeue buffer\n");
else
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 9c35a55..6d80ebd 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -45,6 +45,9 @@
#define WCD9XXX_I2C_DIGITAL_1 2
#define WCD9XXX_I2C_DIGITAL_2 3
+#define ONDEMAND_REGULATOR true
+#define STATIC_REGULATOR (!ONDEMAND_REGULATOR)
+
/* Number of return values needs to be checked for each
* registration of Slimbus of I2C bus for each codec
*/
@@ -1277,17 +1280,18 @@
}
ret = wcd9xxx_process_supplies(dev, pdata, static_prop_name,
- static_cnt, false, 0);
+ static_cnt, STATIC_REGULATOR, 0);
if (ret)
goto err;
ret = wcd9xxx_process_supplies(dev, pdata, ond_prop_name,
- ond_cnt, true, static_cnt);
+ ond_cnt, ONDEMAND_REGULATOR, static_cnt);
if (ret)
goto err;
ret = wcd9xxx_process_supplies(dev, pdata, cp_supplies_name,
- cp_supplies_cnt, false, static_cnt + ond_cnt);
+ cp_supplies_cnt, ONDEMAND_REGULATOR,
+ static_cnt + ond_cnt);
if (ret)
goto err;
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 25b4b5e..4512d02 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2664,7 +2664,6 @@
struct msm_spi_platform_data * __init msm_spi_dt_to_pdata(
struct platform_device *pdev, struct msm_spi *dd)
{
- int i;
struct msm_spi_platform_data *pdata;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
@@ -2725,10 +2724,6 @@
pdata->use_bam = false;
}
}
-
- for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i)
- dd->cs_gpios[i].valid = (dd->cs_gpios[i].gpio_num >= 0);
-
return pdata;
}
@@ -2834,10 +2829,12 @@
i + ARRAY_SIZE(spi_rsrcs));
dd->cs_gpios[i].gpio_num = resource ?
resource->start : -1;
- dd->cs_gpios[i].valid = 0;
}
}
+ for (i = 0; i < ARRAY_SIZE(spi_cs_rsrcs); ++i)
+ dd->cs_gpios[i].valid = 0;
+
dd->pdata = pdata;
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!resource) {
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 0a41ef8..44d81c8 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -166,9 +166,10 @@
spin_lock(&mdss_lock);
hw = mdss_irq_handlers[hw_ndx];
+ spin_unlock(&mdss_lock);
+
if (hw)
rc = hw->irq_handler(irq, hw->ptr);
- spin_unlock(&mdss_lock);
return rc;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 6fb8883..3f3e51c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -479,9 +479,9 @@
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 1);
wmb();
- rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
+ rc = wait_for_completion_timeout(&ctx->vsync_comp,
usecs_to_jiffies(VSYNC_TIMEOUT_US));
- WARN(rc <= 0, "timeout (%d) enabling timegen on ctl=%d\n",
+ WARN(rc == 0, "timeout (%d) enabling timegen on ctl=%d\n",
rc, ctl->num);
ctx->timegen_en = true;
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 0a37573..ff977a9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -345,12 +345,12 @@
if (ctx->comp_cnt == 0)
return rc;
- rc = wait_for_completion_interruptible_timeout(&ctx->wb_comp,
+ rc = wait_for_completion_timeout(&ctx->wb_comp,
KOFF_TIMEOUT);
mdss_mdp_set_intr_callback(ctx->intr_type, ctx->intf_num,
NULL, NULL);
- if (rc <= 0) {
+ if (rc == 0) {
rc = -ENODEV;
WARN(1, "writeback kickoff timed out (%d) ctl=%d\n",
rc, ctl->num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 0c74137..72288c2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -533,11 +533,11 @@
goto kickoff_fail;
}
- ret = wait_for_completion_interruptible_timeout(&comp, KOFF_TIMEOUT);
- if (ret <= 0) {
+ ret = wait_for_completion_timeout(&comp, KOFF_TIMEOUT);
+ if (ret == 0)
WARN(1, "wfd kick off time out=%d ctl=%d", ret, ctl->num);
+ else
ret = 0;
- }
if (wb && node) {
mutex_lock(&wb->lock);
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index e688bd9..d54bf42 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -264,4 +264,16 @@
return 0;
}
#endif /* CONFIG_OF */
+static inline void wcd9xxx_reg_update(struct wcd9xxx *core,
+ unsigned short reg,
+ u8 mask, u8 val)
+{
+ u8 reg_val;
+
+ if (core) {
+ reg_val = wcd9xxx_reg_read(core, reg);
+ reg_val = (reg_val & ~mask) | (val & mask);
+ wcd9xxx_reg_write(core, reg, reg_val);
+ }
+}
#endif
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index fab9301..73b8014 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -126,6 +126,14 @@
MDP_BGR_888, /* BGR 888 */
MDP_Y_CBCR_H2V2_VENUS,
MDP_BGRX_8888, /* BGRX 8888 */
+ MDP_RGBA_8888_TILE, /* RGBA 8888 in tile format */
+ MDP_ARGB_8888_TILE, /* ARGB 8888 in tile format */
+ MDP_ABGR_8888_TILE, /* ABGR 8888 in tile format */
+ MDP_BGRA_8888_TILE, /* BGRA 8888 in tile format */
+ MDP_RGBX_8888_TILE, /* RGBX 8888 in tile format */
+ MDP_XRGB_8888_TILE, /* XRGB 8888 in tile format */
+ MDP_XBGR_8888_TILE, /* XBGR 8888 in tile format */
+ MDP_BGRX_8888_TILE, /* BGRX 8888 in tile format */
MDP_IMGTYPE_LIMIT,
MDP_RGB_BORDERFILL, /* border fill pipe */
MDP_FB_FORMAT = MDP_IMGTYPE2_START, /* framebuffer format */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 7886e84..e134dfd 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -967,7 +967,6 @@
enum snd_soc_pcm_subclass pcm_subclass;
struct snd_pcm_ops ops;
- unsigned int complete:1;
unsigned int dev_registered:1;
/* Dynamic PCM BE runtime data */
diff --git a/init/main.c b/init/main.c
index 737ab05..b2fc496 100644
--- a/init/main.c
+++ b/init/main.c
@@ -477,11 +477,6 @@
smp_setup_processor_id();
debug_objects_early_init();
- /*
- * Set up the the initial canary ASAP:
- */
- boot_init_stack_canary();
-
cgroup_init_early();
local_irq_disable();
@@ -496,6 +491,10 @@
page_address_init();
printk(KERN_NOTICE "%s", linux_banner);
setup_arch(&command_line);
+ /*
+ * Set up the the initial canary ASAP:
+ */
+ boot_init_stack_canary();
mm_init_owner(&init_mm, &init_task);
mm_init_cpumask(&init_mm);
setup_command_line(command_line);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index d9c4b64..5256d44 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -5202,9 +5202,6 @@
*/
rq->stop = NULL;
- /* Ensure any throttled groups are reachable by pick_next_task */
- unthrottle_offline_cfs_rqs(rq);
-
for ( ; ; ) {
/*
* There's this thread running, bail when that's the only
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 5d6ab86..2e98983 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2060,7 +2060,7 @@
hrtimer_cancel(&cfs_b->slack_timer);
}
-void unthrottle_offline_cfs_rqs(struct rq *rq)
+static void unthrottle_offline_cfs_rqs(struct rq *rq)
{
struct cfs_rq *cfs_rq;
@@ -2114,7 +2114,7 @@
return NULL;
}
static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
-void unthrottle_offline_cfs_rqs(struct rq *rq) {}
+static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {}
#endif /* CONFIG_CFS_BANDWIDTH */
@@ -5186,6 +5186,9 @@
static void rq_offline_fair(struct rq *rq)
{
update_sysctl();
+
+ /* Ensure any throttled groups are reachable by pick_next_task */
+ unthrottle_offline_cfs_rqs(rq);
}
#endif /* CONFIG_SMP */
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 8f32475..be427c5 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -685,6 +685,7 @@
* runtime - in which case borrowing doesn't make sense.
*/
rt_rq->rt_runtime = RUNTIME_INF;
+ rt_rq->rt_throttled = 0;
raw_spin_unlock(&rt_rq->rt_runtime_lock);
raw_spin_unlock(&rt_b->rt_runtime_lock);
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 5370bcb..55f6d9c 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1155,7 +1155,6 @@
extern void init_cfs_rq(struct cfs_rq *cfs_rq);
extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
-extern void unthrottle_offline_cfs_rqs(struct rq *rq);
extern void account_cfs_bandwidth_used(int enabled, int was_enabled);
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index bd55389..c0448f2 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -66,6 +66,9 @@
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+#define WCD9302_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+
#define NUM_DECIMATORS 4
#define NUM_INTERPOLATORS 4
#define BITS_PER_REG 8
@@ -973,7 +976,7 @@
static const struct snd_kcontrol_new class_h_dsm_mux =
SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
-static const struct snd_kcontrol_new tapan_snd_controls[] = {
+static const struct snd_kcontrol_new tapan_common_snd_controls[] = {
SOC_ENUM_EXT("EAR PA Gain", tapan_ear_pa_gain_enum[0],
tapan_pa_gain_get, tapan_pa_gain_put),
@@ -995,25 +998,17 @@
SOC_SINGLE_TLV("ADC2 Volume", TAPAN_A_TX_2_EN, 2, 19, 0, analog_gain),
SOC_SINGLE_TLV("ADC3 Volume", TAPAN_A_TX_3_EN, 2, 19, 0, analog_gain),
SOC_SINGLE_TLV("ADC4 Volume", TAPAN_A_TX_4_EN, 2, 19, 0, analog_gain),
- SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 19, 0, analog_gain),
-
SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAPAN_A_CDC_RX1_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAPAN_A_CDC_RX2_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAPAN_A_CDC_RX3_VOL_CTL_B2_CTL,
-84, 40, digital_gain),
- SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL,
- -84, 40, digital_gain),
SOC_SINGLE_S8_TLV("DEC1 Volume", TAPAN_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
digital_gain),
SOC_SINGLE_S8_TLV("DEC2 Volume", TAPAN_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
digital_gain),
- SOC_SINGLE_S8_TLV("DEC3 Volume", TAPAN_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
- digital_gain),
- SOC_SINGLE_S8_TLV("DEC4 Volume", TAPAN_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
- digital_gain),
SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAPAN_A_CDC_IIR1_GAIN_B1_CTL, -84,
40, digital_gain),
@@ -1024,10 +1019,6 @@
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAPAN_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
- SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tapan_get_anc_slot,
- tapan_put_anc_slot),
- SOC_ENUM_EXT("ANC Function", tapan_anc_func_enum, tapan_get_anc_func,
- tapan_put_anc_func),
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
@@ -1041,12 +1032,10 @@
SOC_SINGLE("RX1 HPF Switch", TAPAN_A_CDC_RX1_B5_CTL, 2, 1, 0),
SOC_SINGLE("RX2 HPF Switch", TAPAN_A_CDC_RX2_B5_CTL, 2, 1, 0),
SOC_SINGLE("RX3 HPF Switch", TAPAN_A_CDC_RX3_B5_CTL, 2, 1, 0),
- SOC_SINGLE("RX4 HPF Switch", TAPAN_A_CDC_RX4_B5_CTL, 2, 1, 0),
SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
- SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
tapan_get_iir_enable_audio_mixer, tapan_put_iir_enable_audio_mixer),
@@ -1089,6 +1078,23 @@
tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+};
+
+static const struct snd_kcontrol_new tapan_9306_snd_controls[] = {
+ SOC_SINGLE_TLV("ADC5 Volume", TAPAN_A_TX_5_EN, 2, 19, 0, analog_gain),
+
+ SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAPAN_A_CDC_RX4_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("DEC3 Volume", TAPAN_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC4 Volume", TAPAN_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, tapan_get_anc_slot,
+ tapan_put_anc_slot),
+ SOC_ENUM_EXT("ANC Function", tapan_anc_func_enum, tapan_get_anc_func,
+ tapan_put_anc_func),
+ SOC_SINGLE("RX4 HPF Switch", TAPAN_A_CDC_RX4_B5_CTL, 2, 1, 0),
+ SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
SOC_SINGLE_EXT("COMP0 Switch", SND_SOC_NOPM, COMPANDER_0, 1, 0,
tapan_get_compander, tapan_set_compander),
@@ -1096,7 +1102,6 @@
tapan_get_compander, tapan_set_compander),
SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
tapan_get_compander, tapan_set_compander),
-
};
static const char * const rx_1_2_mix1_text[] = {
@@ -1113,6 +1118,14 @@
"ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
};
+static const char * const rx_rdac3_text[] = {
+ "DEM1", "DEM2"
+};
+
+static const char * const rx_rdac4_text[] = {
+ "DEM3", "DEM2"
+};
+
static const char * const rx_rdac5_text[] = {
"DEM4", "DEM3_INV"
};
@@ -1219,6 +1232,12 @@
static const struct soc_enum rx4_mix2_inp2_chain_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX4_B3_CTL, 3, 5, rx_mix2_text);
+static const struct soc_enum rx_rdac3_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_RX2_B2_CTL, 4, 2, rx_rdac3_text);
+
+static const struct soc_enum rx_rdac4_enum =
+ SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 1, 2, rx_rdac4_text);
+
static const struct soc_enum rx_rdac5_enum =
SOC_ENUM_SINGLE(TAPAN_A_CDC_CONN_MISC, 2, 2, rx_rdac5_text);
@@ -1308,6 +1327,12 @@
static const struct snd_kcontrol_new rx4_mix2_inp2_mux =
SOC_DAPM_ENUM("RX4 MIX2 INP2 Mux", rx4_mix2_inp2_chain_enum);
+static const struct snd_kcontrol_new rx_dac3_mux =
+ SOC_DAPM_ENUM("RDAC3 MUX Mux", rx_rdac3_enum);
+
+static const struct snd_kcontrol_new rx_dac4_mux =
+ SOC_DAPM_ENUM("RDAC4 MUX Mux", rx_rdac4_enum);
+
static const struct snd_kcontrol_new rx_dac5_mux =
SOC_DAPM_ENUM("RDAC5 MUX Mux", rx_rdac5_enum);
@@ -2522,94 +2547,24 @@
{"SLIM TX2 MUX", NULL, "I2S_CLK"},
};
-static const struct snd_soc_dapm_route audio_map[] = {
- /* SLIMBUS Connections */
- {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
- {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
- {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
-
- /* SLIM_MIXER("AIF1_CAP Mixer"),*/
- {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
- {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
- /* SLIM_MIXER("AIF2_CAP Mixer"),*/
- {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
- {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
- /* SLIM_MIXER("AIF3_CAP Mixer"),*/
- {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
- {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
-
- {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX1 MUX", "DEC2", "DEC2 MUX"},
+static const struct snd_soc_dapm_route wcd9306_map[] = {
+ {"SLIM TX1 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX2 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX4 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
{"SLIM TX1 MUX", "DEC3", "DEC3 MUX"},
{"SLIM TX1 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX1 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX1 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX1 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX1 MUX", "RMIX4", "RX4 MIX1"},
-
- {"SLIM TX2 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
{"SLIM TX2 MUX", "DEC3", "DEC3 MUX"},
{"SLIM TX2 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX2 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX2 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX2 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX2 MUX", "RMIX4", "RX4 MIX1"},
-
{"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
- {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
-
{"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
- {"SLIM TX4 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX4 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX4 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX4 MUX", "RMIX4", "RX4 MIX1"},
-
- {"SLIM TX5 MUX", "DEC1", "DEC1 MUX"},
- {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
- {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
- {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
- {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
-
- /* Earpiece (RX MIX1) */
- {"EAR", NULL, "EAR PA"},
- {"EAR PA", NULL, "EAR_PA_MIXER"},
- {"EAR_PA_MIXER", NULL, "DAC1"},
- {"DAC1", NULL, "RX_BIAS"},
- {"DAC1", NULL, "CDC_CP_VDD"},
-
{"ANC EAR", NULL, "ANC EAR PA"},
{"ANC EAR PA", NULL, "EAR_PA_MIXER"},
{"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
{"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
- /* Headset (RX MIX1 and RX MIX2) */
- {"HEADPHONE", NULL, "HPHL"},
- {"HEADPHONE", NULL, "HPHR"},
-
- {"HPHL", NULL, "HPHL_PA_MIXER"},
- {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
- {"HPHL DAC", NULL, "RX_BIAS"},
- {"HPHL DAC", NULL, "CDC_CP_VDD"},
-
- {"HPHR", NULL, "HPHR_PA_MIXER"},
- {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
- {"HPHR DAC", NULL, "RX_BIAS"},
- {"HPHR DAC", NULL, "CDC_CP_VDD"},
-
{"ANC HEADPHONE", NULL, "ANC HPHL"},
{"ANC HEADPHONE", NULL, "ANC HPHR"},
@@ -2637,6 +2592,150 @@
{"ANC HPHR", NULL, "CDC_CONN"},
+ {"RDAC5 MUX", "DEM4", "RX4 MIX2"},
+ {"SPK DAC", "Switch", "RX4 MIX2"},
+
+ {"RX1 MIX2", NULL, "ANC1 MUX"},
+ {"RX2 MIX2", NULL, "ANC2 MUX"},
+
+ {"RX1 MIX1", NULL, "COMP1_CLK"},
+ {"RX2 MIX1", NULL, "COMP1_CLK"},
+ {"RX3 MIX1", NULL, "COMP2_CLK"},
+ {"RX4 MIX1", NULL, "COMP0_CLK"},
+
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
+ {"RX4 MIX2", NULL, "RX4 MIX1"},
+ {"RX4 MIX2", NULL, "RX4 MIX2 INP1"},
+ {"RX4 MIX2", NULL, "RX4 MIX2 INP2"},
+
+ {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX4 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX4 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX2 INP2", "IIR1", "IIR1"},
+
+ {"DEC1 MUX", "DMIC3", "DMIC3"},
+ {"DEC1 MUX", "DMIC4", "DMIC4"},
+ {"DEC2 MUX", "DMIC3", "DMIC3"},
+ {"DEC2 MUX", "DMIC4", "DMIC4"},
+
+ {"DEC3 MUX", "ADC1", "ADC1"},
+ {"DEC3 MUX", "ADC2", "ADC2"},
+ {"DEC3 MUX", "ADC3", "ADC3"},
+ {"DEC3 MUX", "ADC4", "ADC4"},
+ {"DEC3 MUX", "ADC5", "ADC5"},
+ {"DEC3 MUX", "DMIC1", "DMIC1"},
+ {"DEC3 MUX", "DMIC2", "DMIC2"},
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC3 MUX", "DMIC4", "DMIC4"},
+ {"DEC3 MUX", NULL, "CDC_CONN"},
+
+ {"DEC4 MUX", "ADC1", "ADC1"},
+ {"DEC4 MUX", "ADC2", "ADC2"},
+ {"DEC4 MUX", "ADC3", "ADC3"},
+ {"DEC4 MUX", "ADC4", "ADC4"},
+ {"DEC4 MUX", "ADC5", "ADC5"},
+ {"DEC4 MUX", "DMIC1", "DMIC1"},
+ {"DEC4 MUX", "DMIC2", "DMIC2"},
+ {"DEC4 MUX", "DMIC3", "DMIC3"},
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
+ {"DEC4 MUX", NULL, "CDC_CONN"},
+
+ {"ADC5", NULL, "AMIC5"},
+
+ {"AUX_PGA_Left", NULL, "AMIC5"},
+
+ {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
+ {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
+
+ {"MIC BIAS3 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS3 Internal2", NULL, "LDO_H"},
+ {"MIC BIAS3 External", NULL, "LDO_H"},
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* SLIMBUS Connections */
+ {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
+ {"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
+ {"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+
+ /* SLIM_MIXER("AIF1_CAP Mixer"),*/
+ {"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+ {"AIF1_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+ {"AIF1_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+ {"AIF1_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+ {"AIF1_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+ /* SLIM_MIXER("AIF2_CAP Mixer"),*/
+ {"AIF2_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+ {"AIF2_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+ {"AIF2_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+ {"AIF2_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+ {"AIF2_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+ /* SLIM_MIXER("AIF3_CAP Mixer"),*/
+ {"AIF3_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
+ {"AIF3_CAP Mixer", "SLIM TX2", "SLIM TX2 MUX"},
+ {"AIF3_CAP Mixer", "SLIM TX3", "SLIM TX3 MUX"},
+ {"AIF3_CAP Mixer", "SLIM TX4", "SLIM TX4 MUX"},
+ {"AIF3_CAP Mixer", "SLIM TX5", "SLIM TX5 MUX"},
+
+ {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX1 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX1 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX1 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX1 MUX", "RMIX3", "RX3 MIX1"},
+
+ {"SLIM TX2 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX2 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX2 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX2 MUX", "RMIX3", "RX3 MIX1"},
+
+ {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
+
+ {"SLIM TX4 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX4 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX4 MUX", "RMIX3", "RX3 MIX1"},
+
+ {"SLIM TX5 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
+
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR PA"},
+ {"EAR PA", NULL, "EAR_PA_MIXER"},
+ {"EAR_PA_MIXER", NULL, "DAC1"},
+ {"DAC1", NULL, "RX_BIAS"},
+ {"DAC1", NULL, "CDC_CP_VDD"},
+
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL"},
+ {"HEADPHONE", NULL, "HPHR"},
+
+ {"HPHL", NULL, "HPHL_PA_MIXER"},
+ {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+ {"HPHL DAC", NULL, "RX_BIAS"},
+ {"HPHL DAC", NULL, "CDC_CP_VDD"},
+
+ {"HPHR", NULL, "HPHR_PA_MIXER"},
+ {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+ {"HPHR DAC", NULL, "RX_BIAS"},
+ {"HPHR DAC", NULL, "CDC_CP_VDD"},
+
+
{"DAC1", "Switch", "CLASS_H_DSM MUX"},
{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
{"HPHR DAC", NULL, "RX2 CHAIN"},
@@ -2647,36 +2746,28 @@
{"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
{"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
-
{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
{"LINEOUT1 DAC", NULL, "RX3 MIX1"},
{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
- {"RDAC5 MUX", "DEM4", "RX4 MIX2"},
-
{"LINEOUT2 DAC", NULL, "RDAC5 MUX"},
{"SPK PA", NULL, "SPK DAC"},
- {"SPK DAC", "Switch", "RX4 MIX2"},
{"SPK DAC", NULL, "VDD_SPKDRV"},
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
{"CLASS_H_DSM MUX", "RX_HPHL", "RX1 CHAIN"},
- {"RX1 MIX2", NULL, "ANC1 MUX"},
- {"RX2 MIX2", NULL, "ANC2 MUX"},
{"LINEOUT1 DAC", NULL, "RX_BIAS"},
{"LINEOUT2 DAC", NULL, "RX_BIAS"},
{"LINEOUT1 DAC", NULL, "CDC_CP_VDD"},
{"LINEOUT2 DAC", NULL, "CDC_CP_VDD"},
- {"RX1 MIX1", NULL, "COMP1_CLK"},
- {"RX2 MIX1", NULL, "COMP1_CLK"},
- {"RX3 MIX1", NULL, "COMP2_CLK"},
- {"RX4 MIX1", NULL, "COMP0_CLK"},
+ {"RDAC3 MUX", "DEM2", "RX2 MIX1"},
+ {"RDAC3 MUX", "DEM1", "RX1 CHAIN"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
@@ -2685,17 +2776,12 @@
{"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
{"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
- {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
- {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
{"RX1 MIX2", NULL, "RX1 MIX1"},
{"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
{"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
{"RX2 MIX2", NULL, "RX2 MIX1"},
{"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
{"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
- {"RX4 MIX2", NULL, "RX4 MIX1"},
- {"RX4 MIX2", NULL, "RX4 MIX2 INP1"},
- {"RX4 MIX2", NULL, "RX4 MIX2 INP2"},
/* SLIM_MUX("AIF1_PB", "AIF1 PB"),*/
{"SLIM RX1 MUX", "AIF1_PB", "AIF1 PB"},
@@ -2763,25 +2849,11 @@
{"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
{"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
- {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
- {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
- {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
- {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
- {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
- {"RX4 MIX1 INP1", "IIR1", "IIR1"},
- {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
- {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
- {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
- {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
- {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
- {"RX4 MIX1 INP2", "IIR1", "IIR1"},
{"RX1 MIX2 INP1", "IIR1", "IIR1"},
{"RX1 MIX2 INP2", "IIR1", "IIR1"},
{"RX2 MIX2 INP1", "IIR1", "IIR1"},
{"RX2 MIX2 INP2", "IIR1", "IIR1"},
- {"RX4 MIX2 INP1", "IIR1", "IIR1"},
- {"RX4 MIX2 INP2", "IIR1", "IIR1"},
/* Decimator Inputs */
{"DEC1 MUX", "ADC1", "ADC1"},
@@ -2790,8 +2862,6 @@
{"DEC1 MUX", "ADC4", "ADC4"},
{"DEC1 MUX", "DMIC1", "DMIC1"},
{"DEC1 MUX", "DMIC2", "DMIC2"},
- {"DEC1 MUX", "DMIC3", "DMIC3"},
- {"DEC1 MUX", "DMIC4", "DMIC4"},
{"DEC1 MUX", NULL, "CDC_CONN"},
{"DEC2 MUX", "ADC1", "ADC1"},
@@ -2800,38 +2870,13 @@
{"DEC2 MUX", "ADC4", "ADC4"},
{"DEC2 MUX", "DMIC1", "DMIC1"},
{"DEC2 MUX", "DMIC2", "DMIC2"},
- {"DEC2 MUX", "DMIC3", "DMIC3"},
- {"DEC2 MUX", "DMIC4", "DMIC4"},
{"DEC2 MUX", NULL, "CDC_CONN"},
- {"DEC3 MUX", "ADC1", "ADC1"},
- {"DEC3 MUX", "ADC2", "ADC2"},
- {"DEC3 MUX", "ADC3", "ADC3"},
- {"DEC3 MUX", "ADC4", "ADC4"},
- {"DEC3 MUX", "ADC5", "ADC5"},
- {"DEC3 MUX", "DMIC1", "DMIC1"},
- {"DEC3 MUX", "DMIC2", "DMIC2"},
- {"DEC3 MUX", "DMIC3", "DMIC3"},
- {"DEC3 MUX", "DMIC4", "DMIC4"},
- {"DEC3 MUX", NULL, "CDC_CONN"},
-
- {"DEC4 MUX", "ADC1", "ADC1"},
- {"DEC4 MUX", "ADC2", "ADC2"},
- {"DEC4 MUX", "ADC3", "ADC3"},
- {"DEC4 MUX", "ADC4", "ADC4"},
- {"DEC4 MUX", "ADC5", "ADC5"},
- {"DEC4 MUX", "DMIC1", "DMIC1"},
- {"DEC4 MUX", "DMIC2", "DMIC2"},
- {"DEC4 MUX", "DMIC3", "DMIC3"},
- {"DEC4 MUX", "DMIC4", "DMIC4"},
- {"DEC4 MUX", NULL, "CDC_CONN"},
-
/* ADC Connections */
{"ADC1", NULL, "AMIC1"},
{"ADC2", NULL, "AMIC2"},
{"ADC3", NULL, "AMIC3"},
{"ADC4", NULL, "AMIC4"},
- {"ADC5", NULL, "AMIC5"},
/* AUX PGA Connections */
{"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
@@ -2839,13 +2884,10 @@
{"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
{"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
{"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
- {"AUX_PGA_Left", NULL, "AMIC5"},
{"IIR1", NULL, "IIR1 INP1 MUX"},
{"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
{"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
- {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
- {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
{"MIC BIAS1 Internal1", NULL, "LDO_H"},
{"MIC BIAS1 Internal2", NULL, "LDO_H"},
@@ -2854,9 +2896,17 @@
{"MIC BIAS2 Internal2", NULL, "LDO_H"},
{"MIC BIAS2 Internal3", NULL, "LDO_H"},
{"MIC BIAS2 External", NULL, "LDO_H"},
- {"MIC BIAS3 Internal1", NULL, "LDO_H"},
- {"MIC BIAS3 Internal2", NULL, "LDO_H"},
- {"MIC BIAS3 External", NULL, "LDO_H"},
+};
+
+static const struct snd_soc_dapm_route wcd9302_map[] = {
+ {"SPK DAC", "Switch", "RX3 MIX1"},
+
+ {"RDAC4 MUX", "DEM3", "RX3 MIX1"},
+ {"RDAC4 MUX", "DEM2", "RX2 CHAIN"},
+ {"LINEOUT1 DAC", NULL, "RDAC4 MUX"},
+
+ {"RDAC5 MUX", "DEM4", "RX3 MIX1"},
+ {"RDAC5 MUX", "DEM3_INV", "RDAC4 MUX"},
};
static int tapan_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -3471,6 +3521,93 @@
.get_channel_map = tapan_get_channel_map,
};
+static struct snd_soc_dai_driver tapan9302_dai[] = {
+ {
+ .name = "tapan9302_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &tapan_dai_ops,
+ },
+ {
+ .name = "tapan9302_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &tapan_dai_ops,
+ },
+ {
+ .name = "tapan9302_rx2",
+ .id = AIF2_PB,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &tapan_dai_ops,
+ },
+ {
+ .name = "tapan9302_tx2",
+ .id = AIF2_CAP,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &tapan_dai_ops,
+ },
+ {
+ .name = "tapan9302_tx3",
+ .id = AIF3_CAP,
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &tapan_dai_ops,
+ },
+ {
+ .name = "tapan9302_rx3",
+ .id = AIF3_PB,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .rates = WCD9302_RATES,
+ .formats = TAPAN_FORMATS,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &tapan_dai_ops,
+ },
+};
+
static struct snd_soc_dai_driver tapan_dai[] = {
{
.name = "tapan_rx1",
@@ -3876,10 +4013,93 @@
return 0;
}
+static const struct snd_soc_dapm_widget tapan_9306_dapm_widgets[] = {
+ /* RX4 MIX1 mux inputs */
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+
+ /* RX4 MIX2 mux inputs */
+ SND_SOC_DAPM_MUX("RX4 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix2_inp2_mux),
+
+ SND_SOC_DAPM_MIXER("RX4 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER_E("RX4 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+ 0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC3 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, tapan_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC4 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, tapan_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+ SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
+ tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_ADC_E("ADC5", NULL, TAPAN_A_TX_5_EN, 7, 0,
+ tapan_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+ SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+ SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
+ tapan_codec_enable_anc_hph,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
+ tapan_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_OUTPUT("ANC EAR"),
+ SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ tapan_codec_enable_anc_ear,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
+
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0,
+ tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+};
+
/* Todo: Have seperate dapm widgets for I2S and Slimbus.
* Might Need to have callbacks registered only for slimbus
*/
-static const struct snd_soc_dapm_widget tapan_dapm_widgets[] = {
+static const struct snd_soc_dapm_widget tapan_common_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN_E("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
AIF1_PB, 0, tapan_codec_enable_slimrx,
@@ -3933,14 +4153,6 @@
SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
&rx3_mix1_inp2_mux),
- /* RX4 MIX1 mux inputs */
- SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp1_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp2_mux),
- SND_SOC_DAPM_MUX("RX4 MIX1 INP3", SND_SOC_NOPM, 0, 0,
- &rx4_mix1_inp2_mux),
-
/* RX1 MIX2 mux inputs */
SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
&rx1_mix2_inp1_mux),
@@ -3953,16 +4165,8 @@
SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
&rx2_mix2_inp2_mux),
- /* RX4 MIX2 mux inputs */
- SND_SOC_DAPM_MUX("RX4 MIX2 INP1", SND_SOC_NOPM, 0, 0,
- &rx4_mix2_inp1_mux),
- SND_SOC_DAPM_MUX("RX4 MIX2 INP2", SND_SOC_NOPM, 0, 0,
- &rx4_mix2_inp2_mux),
-
-
SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
- SND_SOC_DAPM_MIXER("RX4 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
@@ -3973,9 +4177,6 @@
SND_SOC_DAPM_MIXER_E("RX3 MIX1", TAPAN_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_MIXER_E("RX4 MIX2", TAPAN_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
- 0, tapan_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MIXER("RX1 CHAIN", TAPAN_A_CDC_RX1_B6_CTL, 5, 0,
NULL, 0),
@@ -4036,6 +4237,13 @@
SND_SOC_DAPM_MUX("RDAC5 MUX", SND_SOC_NOPM, 0, 0,
&rx_dac5_mux),
+ /* LINEOUT1*/
+ SND_SOC_DAPM_MUX("RDAC4 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac4_mux),
+
+ SND_SOC_DAPM_MUX("RDAC3 MUX", SND_SOC_NOPM, 0, 0,
+ &rx_dac3_mux),
+
SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAPAN_A_RX_LINE_2_DAC_CTL, 7, 0
, tapan_lineout_dac_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
@@ -4098,29 +4306,9 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MUX_E("DEC3 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
- &dec3_mux, tapan_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_MUX_E("DEC4 MUX", TAPAN_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
- &dec4_mux, tapan_codec_enable_dec,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
-
SND_SOC_DAPM_SUPPLY("LDO_H", TAPAN_A_LDO_H_MODE_1, 7, 0,
tapan_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_SUPPLY("COMP0_CLK", SND_SOC_NOPM, 0, 0,
- tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 1, 0,
- tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 2, 0,
- tapan_config_compander, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD),
-
SND_SOC_DAPM_INPUT("AMIC1"),
SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAPAN_A_MICB_1_CTL, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
@@ -4149,29 +4337,6 @@
tapan_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_INPUT("AMIC5"),
- SND_SOC_DAPM_ADC_E("ADC5", NULL, TAPAN_A_TX_5_EN, 7, 0,
- tapan_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
-
- SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
- SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
-
- SND_SOC_DAPM_OUTPUT("ANC HEADPHONE"),
- SND_SOC_DAPM_PGA_E("ANC HPHL", SND_SOC_NOPM, 5, 0, NULL, 0,
- tapan_codec_enable_anc_hph,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
- SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_PGA_E("ANC HPHR", SND_SOC_NOPM, 4, 0, NULL, 0,
- tapan_codec_enable_anc_hph, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD |
- SND_SOC_DAPM_POST_PMU),
- SND_SOC_DAPM_OUTPUT("ANC EAR"),
- SND_SOC_DAPM_PGA_E("ANC EAR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
- tapan_codec_enable_anc_ear,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
-
SND_SOC_DAPM_INPUT("AMIC2"),
SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAPAN_A_MICB_2_CTL, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
@@ -4185,15 +4350,6 @@
SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAPAN_A_MICB_2_CTL, 7, 0,
tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAPAN_A_MICB_3_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAPAN_A_MICB_3_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAPAN_A_MICB_3_CTL, 7, 0,
- tapan_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_AIF_OUT_E("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
AIF1_CAP, 0, tapan_codec_enable_slimtx,
@@ -4216,14 +4372,6 @@
tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
- tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
- tapan_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMD),
-
/* Sidetone */
SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
SND_SOC_DAPM_PGA("IIR1", TAPAN_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
@@ -4839,6 +4987,78 @@
return NULL;
}
+static void tapan_enable_config_rco(struct wcd9xxx *core, bool enable)
+{
+ if (enable) {
+ /* Enable RC Oscillator */
+ wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x10, 0x00);
+ wcd9xxx_reg_write(core, WCD9XXX_A_BIAS_OSC_BG_CTL, 0x17);
+ usleep_range(5, 5);
+ wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_FREQ, 0x80, 0x80);
+ wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_TEST, 0x80, 0x80);
+ usleep_range(10, 10);
+ wcd9xxx_reg_update(core, WCD9XXX_A_RC_OSC_TEST, 0x80, 0x00);
+ usleep_range(20, 20);
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x08, 0x08);
+ /* Enable MCLK and wait 1ms till it gets enabled */
+ wcd9xxx_reg_write(core, WCD9XXX_A_CLK_BUFF_EN2, 0x02);
+ usleep_range(1000, 1000);
+ /* Enable CLK BUFF and wait for 1.2ms */
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x01, 0x01);
+ usleep_range(1000, 1200);
+
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x02, 0x00);
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x04, 0x04);
+ wcd9xxx_reg_update(core, WCD9XXX_A_CDC_CLK_MCLK_CTL,
+ 0x01, 0x01);
+ usleep_range(50, 50);
+ } else {
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x04, 0x00);
+ usleep_range(50, 50);
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN2, 0x02, 0x02);
+ wcd9xxx_reg_update(core, WCD9XXX_A_CLK_BUFF_EN1, 0x05, 0x00);
+ usleep_range(50, 50);
+ }
+
+}
+
+static bool tapan_check_wcd9306(struct device *cdc_dev, bool sensed)
+{
+ struct wcd9xxx *core = dev_get_drvdata(cdc_dev->parent);
+ u8 reg_val;
+ bool ret = true;
+ unsigned long timeout;
+ bool timedout;
+
+ if (!core) {
+ dev_err(cdc_dev, "%s: core not initialized\n", __func__);
+ return -EINVAL;
+ }
+
+ tapan_enable_config_rco(core, 1);
+
+ if (sensed == false) {
+ reg_val = wcd9xxx_reg_read(core, TAPAN_A_QFUSE_CTL);
+ wcd9xxx_reg_write(core, TAPAN_A_QFUSE_CTL, (reg_val | 0x03));
+ }
+
+ timeout = jiffies + HZ;
+ do {
+ if ((wcd9xxx_reg_read(core, TAPAN_A_QFUSE_STATUS)))
+ break;
+ } while (!(timedout = time_after(jiffies, timeout)));
+
+ if (wcd9xxx_reg_read(core, TAPAN_A_QFUSE_DATA_OUT1) ||
+ wcd9xxx_reg_read(core, TAPAN_A_QFUSE_DATA_OUT2)) {
+ dev_info(cdc_dev, "%s: wcd9302 detected\n", __func__);
+ ret = false;
+ } else
+ dev_info(cdc_dev, "%s: wcd9306 detected\n", __func__);
+
+ tapan_enable_config_rco(core, 0);
+ return ret;
+};
+
static int tapan_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -4956,6 +5176,18 @@
}
}
+ if (tapan_check_wcd9306(codec->dev, false) == true) {
+ snd_soc_add_codec_controls(codec, tapan_9306_snd_controls,
+ ARRAY_SIZE(tapan_9306_snd_controls));
+ snd_soc_dapm_new_controls(dapm, tapan_9306_dapm_widgets,
+ ARRAY_SIZE(tapan_9306_dapm_widgets));
+ snd_soc_dapm_add_routes(dapm, wcd9306_map,
+ ARRAY_SIZE(wcd9306_map));
+ } else {
+ snd_soc_dapm_add_routes(dapm, wcd9302_map,
+ ARRAY_SIZE(wcd9302_map));
+ }
+
control->num_rx_port = TAPAN_RX_MAX;
control->rx_chs = ptr;
memcpy(control->rx_chs, tapan_rx_chs, sizeof(tapan_rx_chs));
@@ -5032,10 +5264,10 @@
.reg_cache_default = tapan_reset_reg_defaults,
.reg_word_size = 1,
- .controls = tapan_snd_controls,
- .num_controls = ARRAY_SIZE(tapan_snd_controls),
- .dapm_widgets = tapan_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(tapan_dapm_widgets),
+ .controls = tapan_common_snd_controls,
+ .num_controls = ARRAY_SIZE(tapan_common_snd_controls),
+ .dapm_widgets = tapan_common_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tapan_common_dapm_widgets),
.dapm_routes = audio_map,
.num_dapm_routes = ARRAY_SIZE(audio_map),
};
@@ -5066,12 +5298,35 @@
static int __devinit tapan_probe(struct platform_device *pdev)
{
int ret = 0;
- if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
- ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tapan,
- tapan_dai, ARRAY_SIZE(tapan_dai));
- else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
- ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_tapan,
- tapan_i2s_dai, ARRAY_SIZE(tapan_i2s_dai));
+ bool is_wcd9306;
+
+ is_wcd9306 = tapan_check_wcd9306(&pdev->dev, false);
+ if (is_wcd9306 < 0) {
+ dev_info(&pdev->dev, "%s: cannot find codec type, default to 9306\n",
+ __func__);
+ is_wcd9306 = true;
+ }
+
+ if (!is_wcd9306) {
+ if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ ret = snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_tapan,
+ tapan9302_dai, ARRAY_SIZE(tapan9302_dai));
+ else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+ ret = snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_tapan,
+ tapan_i2s_dai, ARRAY_SIZE(tapan_i2s_dai));
+ } else {
+ if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ ret = snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_tapan,
+ tapan_dai, ARRAY_SIZE(tapan_dai));
+ else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+ ret = snd_soc_register_codec(&pdev->dev,
+ &soc_codec_dev_tapan,
+ tapan_i2s_dai, ARRAY_SIZE(tapan_i2s_dai));
+ }
+
return ret;
}
static int __devexit tapan_remove(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index 19d717e..55a5e57 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -904,7 +904,7 @@
};
/* Digital audio interface glue - connects codec <---> CPU */
-static struct snd_soc_dai_link msm8226_dai[] = {
+static struct snd_soc_dai_link msm8226_common_dai[] = {
/* FrontEnd DAI Links */
{
.name = "MSM8226 Media1",
@@ -1289,6 +1289,61 @@
.ops = &msm_auxpcm_be_ops,
.ignore_suspend = 1
},
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE_PLAYBACK_TX,
+ .stream_name = "Voice Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32773",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music 2 BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE2_PLAYBACK_TX,
+ .stream_name = "Voice2 Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32770",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm8226_9306_dai[] = {
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -1402,64 +1457,142 @@
.ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
- /* Incall Record Uplink BACK END DAI Link */
+};
+
+static struct snd_soc_dai_link msm8226_9302_dai[] = {
+ /* Backend DAI Links */
{
- .name = LPASS_BE_INCALL_RECORD_TX,
- .stream_name = "Voice Uplink Capture",
- .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16384",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-tx",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_rx1",
.no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm_audrx_init,
+ .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_pmdown_time = 1, /* dai link has playback support */
.ignore_suspend = 1,
},
- /* Incall Record Downlink BACK END DAI Link */
{
- .name = LPASS_BE_INCALL_RECORD_RX,
- .stream_name = "Voice Downlink Capture",
- .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16385",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-tx",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
.no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
- /* Incall Music BACK END DAI Link */
{
- .name = LPASS_BE_VOICE_PLAYBACK_TX,
- .stream_name = "Voice Farend Playback",
- .cpu_dai_name = "msm-dai-q6-dev.32773",
+ .name = LPASS_BE_SLIMBUS_1_RX,
+ .stream_name = "Slimbus1 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16386",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-rx",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_rx1",
.no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
.ignore_suspend = 1,
},
- /* Incall Music 2 BACK END DAI Link */
{
- .name = LPASS_BE_VOICE2_PLAYBACK_TX,
- .stream_name = "Voice2 Farend Playback",
- .cpu_dai_name = "msm-dai-q6-dev.32770",
+ .name = LPASS_BE_SLIMBUS_1_TX,
+ .stream_name = "Slimbus1 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16387",
.platform_name = "msm-pcm-routing",
- .codec_name = "msm-stub-codec.1",
- .codec_dai_name = "msm-stub-rx",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
.no_pcm = 1,
- .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_RX,
+ .stream_name = "Slimbus3 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16390",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_rx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_TX,
+ .stream_name = "Slimbus3 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16391",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_4_RX,
+ .stream_name = "Slimbus4 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16392",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_rx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tapan_codec",
+ .codec_dai_name = "tapan9302_tx1",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
+ .ops = &msm8226_be_ops,
.ignore_suspend = 1,
},
};
+static struct snd_soc_dai_link msm8226_9306_dai_links[
+ ARRAY_SIZE(msm8226_common_dai) +
+ ARRAY_SIZE(msm8226_9306_dai)];
+
+static struct snd_soc_dai_link msm8226_9302_dai_links[
+ ARRAY_SIZE(msm8226_common_dai) +
+ ARRAY_SIZE(msm8226_9302_dai)];
+
struct snd_soc_card snd_soc_card_msm8226 = {
.name = "msm8226-tapan-snd-card",
- .dai_link = msm8226_dai,
- .num_links = ARRAY_SIZE(msm8226_dai),
+ .dai_link = msm8226_9306_dai_links,
+ .num_links = ARRAY_SIZE(msm8226_9306_dai_links),
+};
+
+struct snd_soc_card snd_soc_card_9302_msm8226 = {
+ .name = "msm8226-tapan9302-snd-card",
+ .dai_link = msm8226_9302_dai_links,
+ .num_links = ARRAY_SIZE(msm8226_9302_dai_links),
};
static int msm8226_dtparse_auxpcm(struct platform_device *pdev,
@@ -1534,7 +1667,7 @@
ret = gpio_request(pdata->mclk_gpio, "TAPAN_CODEC_PMIC_MCLK");
if (ret) {
dev_err(card->dev,
- "%s: Failed to request taiko mclk gpio %d\n",
+ "%s: Failed to request tapan mclk gpio %d\n",
__func__, pdata->mclk_gpio);
return ret;
}
@@ -1580,9 +1713,36 @@
return 0;
}
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+
+ struct snd_soc_card *card;
+
+ if (of_property_read_bool(dev->of_node,
+ "qcom,tapan-codec-9302")) {
+ card = &snd_soc_card_9302_msm8226;
+
+ memcpy(msm8226_9302_dai_links, msm8226_common_dai,
+ sizeof(msm8226_common_dai));
+ memcpy(msm8226_9302_dai_links + ARRAY_SIZE(msm8226_common_dai),
+ msm8226_9302_dai, sizeof(msm8226_9302_dai));
+
+ } else {
+
+ card = &snd_soc_card_msm8226;
+
+ memcpy(msm8226_9306_dai_links, msm8226_common_dai,
+ sizeof(msm8226_common_dai));
+ memcpy(msm8226_9306_dai_links + ARRAY_SIZE(msm8226_common_dai),
+ msm8226_9306_dai, sizeof(msm8226_9306_dai));
+ }
+
+ return card;
+}
+
static __devinit int msm8226_asoc_machine_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = &snd_soc_card_msm8226;
+ struct snd_soc_card *card;
struct msm8226_asoc_mach_data *pdata;
int ret;
const char *auxpcm_pri_gpio_set = NULL;
@@ -1600,14 +1760,7 @@
goto err;
}
- /* Parse AUXPCM info from DT */
- ret = msm8226_dtparse_auxpcm(pdev, &pdata->auxpcm_ctrl,
- msm_auxpcm_gpio_name);
- if (ret) {
- dev_err(&pdev->dev,
- "%s: Auxpcm pin data parse failed\n", __func__);
- goto err;
- }
+ card = populate_snd_card_dailinks(&pdev->dev);
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
@@ -1649,6 +1802,33 @@
goto err;
}
+ ret = msm8226_prepare_codec_mclk(card);
+ if (ret)
+ goto err1;
+
+ mutex_init(&cdc_mclk_mutex);
+
+ mbhc_cfg.gpio_level_insert = of_property_read_bool(pdev->dev.of_node,
+ "qcom,headset-jack-type-NO");
+
+ ret = snd_soc_register_card(card);
+ if (ret == -EPROBE_DEFER)
+ goto err;
+ else if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err;
+ }
+
+ /* Parse AUXPCM info from DT */
+ ret = msm8226_dtparse_auxpcm(pdev, &pdata->auxpcm_ctrl,
+ msm_auxpcm_gpio_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Auxpcm pin data parse failed\n", __func__);
+ goto err;
+ }
+
vdd_spkr_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,cdc-vdd-spkr-gpios", 0);
if (vdd_spkr_gpio < 0) {
@@ -1686,22 +1866,8 @@
}
}
- mbhc_cfg.gpio_level_insert = of_property_read_bool(pdev->dev.of_node,
- "qcom,headset-jack-type-NO");
msm8226_setup_hs_jack(pdev, pdata);
- ret = msm8226_prepare_codec_mclk(card);
- if (ret)
- goto err_lineout_spkr;
-
- ret = snd_soc_register_card(card);
- if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
- ret);
- goto err_lineout_spkr;
- }
- mutex_init(&cdc_mclk_mutex);
-
ret = of_property_read_string(pdev->dev.of_node,
"qcom,prim-auxpcm-gpio-set", &auxpcm_pri_gpio_set);
if (ret) {
@@ -1747,6 +1913,7 @@
gpio_free(pdata->mclk_gpio);
pdata->mclk_gpio = 0;
}
+err1:
devm_kfree(&pdev->dev, pdata);
return ret;
}
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 769b8eb..25bc86b 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -269,7 +269,9 @@
static void msm8974_liquid_ext_ult_spk_power_amp_enable(u32 on)
{
if (on) {
- regulator_enable(ext_spk_amp_regulator);
+ if (regulator_enable(ext_spk_amp_regulator))
+ pr_err("%s: enable failed ext_spk_amp_reg\n",
+ __func__);
gpio_direction_output(ext_ult_spk_amp_gpio, 1);
/* time takes enable the external power class AB amplifier */
usleep_range(EXT_CLASS_AB_EN_DELAY,
@@ -289,7 +291,9 @@
static void msm8974_liquid_ext_spk_power_amp_enable(u32 on)
{
if (on) {
- regulator_enable(ext_spk_amp_regulator);
+ if (regulator_enable(ext_spk_amp_regulator))
+ pr_err("%s: enable failed ext_spk_amp_reg\n",
+ __func__);
gpio_direction_output(ext_spk_amp_gpio, on);
/*time takes enable the external power amplifier*/
usleep_range(EXT_CLASS_D_EN_DELAY,
@@ -2659,24 +2663,6 @@
return -ENOMEM;
}
- /* Parse Primary AUXPCM info from DT */
- ret = msm8974_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
- msm_prim_auxpcm_gpio_name);
- if (ret) {
- dev_err(&pdev->dev,
- "%s: Primary Auxpcm pin data parse failed\n", __func__);
- goto err;
- }
-
- /* Parse Secondary AUXPCM info from DT */
- ret = msm8974_dtparse_auxpcm(pdev, &pdata->sec_auxpcm_ctrl,
- msm_sec_auxpcm_gpio_name);
- if (ret) {
- dev_err(&pdev->dev,
- "%s: Secondary Auxpcm pin data parse failed\n", __func__);
- goto err;
- }
-
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, pdata);
@@ -2717,26 +2703,9 @@
goto err;
}
- ext_ult_lo_amp_gpio = of_get_named_gpio(pdev->dev.of_node,
- prop_name_ult_lo_gpio, 0);
- if (!gpio_is_valid(ext_ult_lo_amp_gpio)) {
- dev_dbg(&pdev->dev,
- "Couldn't find %s property in node %s, %d\n",
- prop_name_ult_lo_gpio, pdev->dev.of_node->full_name,
- ext_ult_lo_amp_gpio);
- } else {
- ret = gpio_request(ext_ult_lo_amp_gpio, "US_AMP_GPIO");
- if (ret) {
- dev_err(card->dev,
- "%s: Failed to request US amp gpio %d\n",
- __func__, ext_ult_lo_amp_gpio);
- goto err;
- }
- }
-
ret = msm8974_prepare_codec_mclk(card);
if (ret)
- goto err1;
+ goto err;
if (of_property_read_bool(pdev->dev.of_node, "qcom,hdmi-audio-rx")) {
dev_info(&pdev->dev, "%s(): hdmi audio support present\n",
@@ -2756,6 +2725,58 @@
card->dai_link = msm8974_common_dai_links;
card->num_links = ARRAY_SIZE(msm8974_common_dai_links);
}
+ mutex_init(&cdc_mclk_mutex);
+ atomic_set(&prim_auxpcm_rsc_ref, 0);
+ atomic_set(&sec_auxpcm_rsc_ref, 0);
+ spdev = pdev;
+ ext_spk_amp_regulator = NULL;
+ msm8974_liquid_dock_dev = NULL;
+
+ ret = snd_soc_register_card(card);
+ if (ret == -EPROBE_DEFER)
+ goto err;
+ else if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err;
+ }
+
+ /* Parse Primary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
+ msm_prim_auxpcm_gpio_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Primary Auxpcm pin data parse failed\n", __func__);
+ goto err;
+ }
+
+ /* Parse Secondary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->sec_auxpcm_ctrl,
+ msm_sec_auxpcm_gpio_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Secondary Auxpcm pin data parse failed\n", __func__);
+ goto err;
+ }
+
+
+ ext_ult_lo_amp_gpio = of_get_named_gpio(pdev->dev.of_node,
+ prop_name_ult_lo_gpio, 0);
+ if (!gpio_is_valid(ext_ult_lo_amp_gpio)) {
+ dev_dbg(&pdev->dev,
+ "Couldn't find %s property in node %s, %d\n",
+ prop_name_ult_lo_gpio, pdev->dev.of_node->full_name,
+ ext_ult_lo_amp_gpio);
+ } else {
+ ret = gpio_request(ext_ult_lo_amp_gpio, "US_AMP_GPIO");
+ if (ret) {
+ dev_err(card->dev,
+ "%s: Failed to request US amp gpio %d\n",
+ __func__, ext_ult_lo_amp_gpio);
+ goto err;
+ }
+ }
+
pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,us-euro-gpios", 0);
@@ -2774,20 +2795,6 @@
dev_err(&pdev->dev, "msm8974_prepare_us_euro failed (%d)\n",
ret);
- mutex_init(&cdc_mclk_mutex);
- atomic_set(&prim_auxpcm_rsc_ref, 0);
- atomic_set(&sec_auxpcm_rsc_ref, 0);
- spdev = pdev;
- ext_spk_amp_regulator = NULL;
- msm8974_liquid_dock_dev = NULL;
-
- ret = snd_soc_register_card(card);
- if (ret) {
- dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
- ret);
- goto err1;
- }
-
ret = of_property_read_string(pdev->dev.of_node,
"qcom,prim-auxpcm-gpio-set", &auxpcm_pri_gpio_set);
if (ret) {
@@ -2820,7 +2827,8 @@
return 0;
err1:
- gpio_free(ext_ult_lo_amp_gpio);
+ if (ext_ult_lo_amp_gpio >= 0)
+ gpio_free(ext_ult_lo_amp_gpio);
ext_ult_lo_amp_gpio = -1;
err:
if (pdata->mclk_gpio > 0) {
@@ -2835,6 +2843,7 @@
gpio_free(pdata->us_euro_gpio);
pdata->us_euro_gpio = 0;
}
+ mutex_destroy(&cdc_mclk_mutex);
devm_kfree(&pdev->dev, pdata);
return ret;
}
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index e1f1efc..7871900 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -463,9 +463,8 @@
ret = snd_soc_jack_new(codec, "Headset Jack",
SND_JACK_HEADSET, &hs_jack);
- if (ret) {
+ if (ret)
pr_err("%s: Failed to create headset jack\n", __func__);
- }
return ret;
}
@@ -885,19 +884,35 @@
if (ret)
goto err;
+ mutex_init(&cdc_mclk_mutex);
pcbcr = ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CBCR, 4);
+ if (!pcbcr) {
+ ret = -ENOMEM;
+ goto err1;
+ }
prcgr = ioremap(MSM8X10_DINO_LPASS_DIGCODEC_CMD_RCGR, 4);
-
+ if (!prcgr) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+ atomic_set(&mclk_rsc_ref, 0);
spdev = pdev;
+
ret = snd_soc_register_card(card);
- if (ret) {
+ if (ret == -EPROBE_DEFER)
+ goto err1;
+ else if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
ret);
- goto err;
+ goto err1;
}
- mutex_init(&cdc_mclk_mutex);
- atomic_set(&mclk_rsc_ref, 0);
return 0;
+err1:
+ mutex_destroy(&cdc_mclk_mutex);
+ if (pcbcr)
+ iounmap(pcbcr);
+ if (prcgr)
+ iounmap(prcgr);
err:
return ret;
}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 79016b5..36a4ba4 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -55,7 +55,6 @@
#endif
static DEFINE_MUTEX(client_mutex);
-static LIST_HEAD(card_list);
static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
@@ -850,15 +849,9 @@
struct snd_soc_dai *codec_dai, *cpu_dai;
const char *platform_name;
- if (rtd->complete)
- return 1;
dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
- /* do we already have the CPU DAI for this link ? */
- if (rtd->cpu_dai) {
- goto find_codec;
- }
- /* no, then find CPU DAI from registered DAIs*/
+ /* Find CPU DAI from registered DAIs*/
list_for_each_entry(cpu_dai, &dai_list, list) {
if (dai_link->cpu_dai_of_node) {
if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node)
@@ -869,15 +862,13 @@
}
rtd->cpu_dai = cpu_dai;
- goto find_codec;
}
- dev_dbg(card->dev, "CPU DAI %s not registered\n",
- dai_link->cpu_dai_name);
-find_codec:
- /* do we already have the CODEC for this link ? */
- if (rtd->codec) {
- goto find_platform;
+ if (!rtd->cpu_dai) {
+ dev_dbg(card->dev, "CPU DAI %s not registered\n",
+ dai_link->cpu_dai_name);
+ return -EPROBE_DEFER;
+
}
/* no, then find CODEC from registered CODECs*/
@@ -902,21 +893,21 @@
dai_link->codec_dai_name)) {
rtd->codec_dai = codec_dai;
- goto find_platform;
}
}
- dev_dbg(card->dev, "CODEC DAI %s not registered\n",
+ if (!rtd->codec_dai) {
+ dev_dbg(card->dev, "CODEC DAI %s not registered\n",
dai_link->codec_dai_name);
+ return -EPROBE_DEFER;
+ }
- goto find_platform;
}
- dev_dbg(card->dev, "CODEC %s not registered\n",
- dai_link->codec_name);
-find_platform:
- /* do we need a platform? */
- if (rtd->platform)
- goto out;
+ if (!rtd->codec) {
+ dev_dbg(card->dev, "CODEC %s not registered\n",
+ dai_link->codec_name);
+ return -EPROBE_DEFER;
+ }
/* if there's no platform we match on the empty platform */
platform_name = dai_link->platform_name;
@@ -935,20 +926,17 @@
}
rtd->platform = platform;
- goto out;
}
-
- dev_dbg(card->dev, "platform %s not registered\n",
+ if (!rtd->platform) {
+ dev_dbg(card->dev, "platform %s not registered\n",
dai_link->platform_name);
+
+ return -EPROBE_DEFER;
+ }
+ card->num_rtd++;
+
return 0;
-out:
- /* mark rtd as complete if we found all 4 of our client devices */
- if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
- rtd->complete = 1;
- card->num_rtd++;
- }
- return 1;
}
static void soc_remove_codec(struct snd_soc_codec *codec)
@@ -1399,6 +1387,20 @@
}
#endif
+static int soc_check_aux_dev(struct snd_soc_card *card, int num)
+{
+ struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
+ struct snd_soc_codec *codec;
+
+ /* find CODEC from registered CODECs*/
+ list_for_each_entry(codec, &codec_list, list) {
+ if (!strcmp(codec->name, aux_dev->codec_name))
+ return 0;
+ }
+
+ return -EPROBE_DEFER;
+}
+
static int soc_probe_aux_dev(struct snd_soc_card *card, int num)
{
struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num];
@@ -1419,7 +1421,7 @@
}
/* codec not found */
dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name);
- goto out;
+ return -EPROBE_DEFER;
found:
ret = soc_probe_codec(card, codec);
@@ -1559,7 +1561,7 @@
}
-static void snd_soc_instantiate_card(struct snd_soc_card *card)
+static int snd_soc_instantiate_card(struct snd_soc_card *card)
{
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
@@ -1569,19 +1571,19 @@
mutex_lock(&card->mutex);
- if (card->instantiated) {
- mutex_unlock(&card->mutex);
- return;
- }
/* bind DAIs */
- for (i = 0; i < card->num_links; i++)
- soc_bind_dai_link(card, i);
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_bind_dai_link(card, i);
+ if (ret != 0)
+ goto base_error;
+ }
- /* bind completed ? */
- if (card->num_rtd != card->num_links) {
- mutex_unlock(&card->mutex);
- return;
+ /* check aux_devs too */
+ for (i = 0; i < card->num_aux_devs; i++) {
+ ret = soc_check_aux_dev(card, i);
+ if (ret != 0)
+ goto base_error;
}
/* initialize the register cache for each available codec */
@@ -1601,10 +1603,8 @@
}
}
ret = snd_soc_init_codec_cache(codec, compress_type);
- if (ret < 0) {
- mutex_unlock(&card->mutex);
- return;
- }
+ if (ret < 0)
+ goto base_error;
}
/* card bind complete so register a sound card */
@@ -1613,8 +1613,7 @@
if (ret < 0) {
printk(KERN_ERR "asoc: can't create sound card for card %s\n",
card->name);
- mutex_unlock(&card->mutex);
- return;
+ goto base_error;
}
card->snd_card->dev = card->dev;
@@ -1751,7 +1750,7 @@
card->instantiated = 1;
snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex);
- return;
+ return 0;
probe_aux_dev_err:
for (i = 0; i < card->num_aux_devs; i++)
@@ -1765,19 +1764,9 @@
card->remove(card);
snd_card_free(card->snd_card);
-
+base_error:
mutex_unlock(&card->mutex);
-}
-
-/*
- * Attempt to initialise any uninitialised cards. Must be called with
- * client_mutex.
- */
-static void snd_soc_instantiate_cards(void)
-{
- struct snd_soc_card *card;
- list_for_each_entry(card, &card_list, list)
- snd_soc_instantiate_card(card);
+ return ret;
}
/* probes a new socdev */
@@ -3233,12 +3222,10 @@
mutex_init(&card->dpcm_mutex);
mutex_init(&card->dapm_power_mutex);
- mutex_lock(&client_mutex);
- list_add(&card->list, &card_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
+ ret = snd_soc_instantiate_card(card);
+ if (ret != 0)
+ soc_cleanup_card_debugfs(card);
- dev_dbg(card->dev, "Registered card '%s'\n", card->name);
return ret;
}
@@ -3254,9 +3241,6 @@
{
if (card->instantiated)
soc_cleanup_card_resources(card);
- mutex_lock(&client_mutex);
- list_del(&card->list);
- mutex_unlock(&client_mutex);
dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
return 0;
@@ -3352,7 +3336,6 @@
mutex_lock(&client_mutex);
list_add(&dai->list, &dai_list);
- snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered DAI '%s'\n", dai->name);
@@ -3434,9 +3417,6 @@
pr_debug("Registered DAI '%s'\n", dai->name);
}
- mutex_lock(&client_mutex);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
return 0;
err:
@@ -3493,7 +3473,6 @@
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
- snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered platform '%s'\n", platform->name);
@@ -3651,7 +3630,6 @@
mutex_lock(&client_mutex);
list_add(&codec->list, &codec_list);
- snd_soc_instantiate_cards();
mutex_unlock(&client_mutex);
pr_debug("Registered codec '%s'\n", codec->name);