Merge "ARM: dts: msm8226: increase PWM frequency to avoid flicker"
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 9524360..f7e50eb 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -45,9 +45,9 @@
- qcom,saftey-timer: include for safety timer use, otherwise watchdog timer will be used
- linux,default-trigger: trigger the led from external modules such as display
- qcom,default-state: default state of the led, should be "on" or "off"
-- qcom,torch-enable: set flash led to torch mode
-- flash_boost-supply: SMBB regulator for LED flash mode
-- torch_boost-supply: SMBB regulator for LED torch mode
+- qcom,torch-enable: set flash led to torch mode functionality and triggers software workaround for torch if hardware does not support
+- flash-boost-supply: SMBB regulator for LED flash mode
+- torch-boost-supply: SMBB regulator for LED torch mode
RGB Led is a tri-colored led, Red, Blue & Green.
@@ -222,8 +222,8 @@
qcom,leds@d300 {
compatible = "qcom,leds-qpnp";
status = "okay";
- flash_boost-supply = <&pm8941_chg_boost>;
- torch_boost-supply = <&pm8941_boost>;
+ flash-boost-supply = <&pm8941_chg_boost>;
+ torch-boost-supply = <&pm8941_boost>;
qcom,flash_0 {
qcom,max-current = <1000>;
qcom,default-state = "off";
@@ -238,6 +238,7 @@
linux,name = "led:flash_0";
qcom,current = <625>;
qcom,id = <1>;
+ qcom,no-torch-module;
};
};
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/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/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2c5e57f..049c71a 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -826,43 +826,55 @@
status = "disabled";
};
- qcom,leds@d300 {
- compatible = "qcom,leds-qpnp";
- status = "okay";
- reg = <0xd300 0x100>;
- label = "flash";
- flash_boost-supply = <&pm8226_chg_boost>;
- pm8226_flash0: qcom,flash_0 {
- qcom,max-current = <1000>;
- qcom,default-state = "off";
- qcom,headroom = <0>;
- qcom,duration = <1280>;
- qcom,clamp-curr = <200>;
- qcom,startup-dly = <1>;
- qcom,safety-timer;
- label = "flash";
- linux,default-trigger =
- "flash0_trigger";
- qcom,id = <1>;
- linux,name = "led:flash_0";
- qcom,current = <625>;
- };
+ qcom,leds@d300 {
+ compatible = "qcom,leds-qpnp";
+ status = "okay";
+ reg = <0xd300 0x100>;
+ label = "flash";
+ flash-boost-supply = <&pm8226_chg_boost>;
+ pm8226_flash0: qcom,flash_0 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <0>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <1>;
+ qcom,safety-timer;
+ label = "flash";
+ linux,default-trigger =
+ "flash0_trigger";
+ qcom,id = <1>;
+ linux,name = "led:flash_0";
+ qcom,current = <625>;
+ };
- pm8226_flash1: qcom,flash_1 {
- qcom,max-current = <1000>;
- qcom,default-state = "off";
- qcom,headroom = <0>;
- qcom,duration = <1280>;
- qcom,clamp-curr = <200>;
- qcom,startup-dly = <1>;
- qcom,safety-timer;
- linux,default-trigger =
- "flash1_trigger";
- label = "flash";
- qcom,id = <2>;
- linux,name = "led:flash_1";
- qcom,current = <625>;
- };
+ pm8226_flash1: qcom,flash_1 {
+ qcom,max-current = <1000>;
+ qcom,default-state = "off";
+ qcom,headroom = <0>;
+ qcom,duration = <1280>;
+ qcom,clamp-curr = <200>;
+ qcom,startup-dly = <1>;
+ qcom,safety-timer;
+ linux,default-trigger =
+ "flash1_trigger";
+ label = "flash";
+ qcom,id = <2>;
+ linux,name = "led:flash_1";
+ qcom,current = <625>;
+ };
+
+ 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/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index ed5756f..583cd3c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -1253,8 +1253,8 @@
compatible = "qcom,leds-qpnp";
reg = <0xd300 0x100>;
label = "flash";
- flash_boost-supply = <&pm8941_chg_boost>;
- torch_boost-supply = <&pm8941_boost>;
+ flash-boost-supply = <&pm8941_chg_boost>;
+ torch-boost-supply = <&pm8941_boost>;
};
qcom,leds@d400 {
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index f807814..a487ccf 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>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 56e8a09..618b1d0 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>;
};
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index fb24a25..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>;
};
};
@@ -30,6 +31,79 @@
qcom,cci-master = <0>;
};
+ eeprom0: qcom,eeprom@6c {
+ cell-index = <0>;
+ reg = <0x6c 0x0>;
+ qcom,eeprom-name = "truly_cm7700";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,cci-master = <0>;
+ qcom,num-blocks = <9>;
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0 1 1>;
+ qcom,mem0 = <0 0x0 2 0 1 0>;
+ qcom,page1 = <1 0x3d84 2 0x8 1 1>;
+ qcom,pageen1 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <32 0x3d00 2 0 1 0>;
+ qcom,page2 = <1 0x3d84 2 0x9 1 1>;
+ qcom,pageen2 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <32 0x3d00 2 0 1 0>;
+ qcom,page3 = <1 0x3d84 2 0xa 1 1>;
+ qcom,pageen3 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <32 0x3d00 2 0 1 0>;
+ qcom,page4 = <1 0x3d84 2 0xb 1 1>;
+ qcom,pageen4 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll4 = <0 0x0 2 0 1 1>;
+ qcom,mem4 = <32 0x3d00 2 0 1 0>;
+ qcom,page5 = <1 0x3d84 2 0xc 1 1>;
+ qcom,pageen5 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll5 = <0 0x0 2 0 1 1>;
+ qcom,mem5 = <32 0x3d00 2 0 1 0>;
+ qcom,page6 = <1 0x3d84 2 0xd 1 1>;
+ qcom,pageen6 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll6 = <0 0x0 2 0 1 1>;
+ qcom,mem6 = <32 0x3d00 2 0 1 0>;
+ qcom,page7 = <1 0x3d84 2 0xe 1 1>;
+ qcom,pageen7 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll7 = <0 0x0 2 0 1 1>;
+ qcom,mem7 = <32 0x3d00 2 0 1 0>;
+ qcom,page8 = <1 0x3d84 2 0xf 1 1>;
+ qcom,pageen8 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll8 = <0 0x0 2 0 1 1>;
+ qcom,mem8 = <32 0x3d00 2 0 1 0>;
+
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio";
+ qcom,cam-vreg-type = <0 1>;
+ qcom,cam-vreg-min-voltage = <1200000 0>;
+ qcom,cam-vreg-max-voltage = <1200000 0>;
+ qcom,cam-vreg-op-mode = <200000 0>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,cam-power-seq-type = "sensor_vreg",
+ "sensor_vreg", "sensor_clk",
+ "sensor_gpio", "sensor_gpio";
+ qcom,cam-power-seq-val = "cam_vdig",
+ "cam_vio", "sensor_cam_mclk",
+ "sensor_gpio_reset",
+ "sensor_gpio_standby";
+ qcom,cam-power-seq-cfg-val = <1 1 24000000 1 1>;
+ qcom,cam-power-seq-delay = <1 1 5 5 10>;
+ };
+
qcom,camera@6f {
compatible = "qcom,ov8825";
reg = <0x6f>;
@@ -38,7 +112,8 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
- qcom,mount-angle = <270>;
+ qcom,eeprom-src = <&eeprom0>;
+ qcom,mount-angle = <90>;
qcom,sensor-name = "ov8825";
cam_vdig-supply = <&pm8226_l5>;
cam_vana-supply = <&pm8226_l19>;
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-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 da52984..0ae0fc6 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -331,13 +331,9 @@
qcom,cdc-vdd-px-voltage = <1800000 1800000>;
qcom,cdc-vdd-px-current = <25000>;
- cdc-vdd-a-1p2v-supply = <&pm8226_l4>;
- qcom,cdc-vdd-a-1p2v-voltage = <1200000 1200000>;
- qcom,cdc-vdd-a-1p2v-current = <10000>;
-
cdc-vdd-cx-supply = <&pm8226_l4>;
qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
- qcom,cdc-vdd-cx-current = <10000>;
+ qcom,cdc-vdd-cx-current = <2000>;
cdc-vdd-buckhelper-supply = <&pm8226_l25>;
qcom,cdc-vdd-buckhelper-voltage = <1775000 2125000>;
@@ -345,7 +341,6 @@
qcom,cdc-static-supplies = "cdc-vdd-h",
"cdc-vdd-px",
- "cdc-vdd-a-1p2v",
"cdc-vdd-cx";
qcom,cdc-cp-supplies = "cdc-vdd-buck",
@@ -382,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.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index efa68b9..184a979 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -258,8 +258,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/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 9159ba2..4b96b66 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-v2-pm.dtsi"
/ {
model = "Qualcomm MSM 8926";
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 47b425c..ca20e04 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -290,6 +290,7 @@
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
CONFIG_OV12830=y
+CONFIG_IMX135=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_EEPROM=y
CONFIG_MSM_CPP=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 97c3664..d8ae340 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -294,6 +294,7 @@
# CONFIG_MSM_CAMERA is not set
CONFIG_OV8825=y
CONFIG_OV12830=y
+CONFIG_IMX135=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_EEPROM=y
CONFIG_MSM_CPP=y
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/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 8a79687..c4097ca 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3400,6 +3400,10 @@
/* eeprom clocks */
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,eeprom"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,eeprom"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "18.qcom,eeprom"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "18.qcom,eeprom"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6b.qcom,eeprom"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6b.qcom,eeprom"),
/* CCI clocks */
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
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/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 755f0a1..9c27180 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -28,7 +28,6 @@
#define ALL_EQUIP_ID 100
#define ALL_SSID -1
-#define MAX_SSID_PER_RANGE 100
#define FEATURE_MASK_LEN_BYTES 2
@@ -135,6 +134,7 @@
uint8_t *ptr = driver->msg_masks;
uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
+ uint32_t copy_len = (end - start + 1) * sizeof(int);
mutex_lock(&driver->diagchar_mutex);
/* First SSID can be zero : So check that last is non-zero */
@@ -153,11 +153,19 @@
actual_last = end;
*(uint32_t *)(actual_last_ptr) = end;
}
+ if (actual_last-first >= MAX_SSID_PER_RANGE) {
+ pr_err("diag: In %s, truncating ssid range, %d-%d to max allowed: %d",
+ __func__, first, actual_last,
+ MAX_SSID_PER_RANGE);
+ copy_len = MAX_SSID_PER_RANGE;
+ actual_last = first + MAX_SSID_PER_RANGE;
+ *(uint32_t *)actual_last_ptr = actual_last;
+ }
if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
- (((end - start)+1)*4))) {
+ copy_len)) {
pr_debug("diag: update ssid start %d, end %d\n",
start, end);
- memcpy(ptr, buf , ((end - start)+1)*4);
+ memcpy(ptr, buf, copy_len);
} else
pr_alert("diag: Not enough space MSG_MASK\n");
found = 1;
@@ -311,11 +319,11 @@
return;
}
+ diag_send_feature_mask_update(smd_info);
diag_send_msg_mask_update(smd_info->ch, ALL_SSID, ALL_SSID,
smd_info->peripheral);
diag_send_log_mask_update(smd_info->ch, ALL_EQUIP_ID);
diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
- diag_send_feature_mask_update(smd_info);
if (smd_info->notify_context == SMD_EVENT_OPEN)
diag_send_diag_mode_update_by_smd(smd_info,
@@ -493,6 +501,16 @@
case DIAG_CTRL_MASK_VALID:
driver->msg_mask->msg_mask_size = actual_last -
first + 1;
+ /* Limit the msg_mask_size to MAX_SSID_PER_RANGE */
+ if (driver->msg_mask->msg_mask_size >
+ MAX_SSID_PER_RANGE) {
+ pr_err("diag: in %s, Invalid msg mask size %d, max: %d",
+ __func__,
+ driver->msg_mask->msg_mask_size,
+ MAX_SSID_PER_RANGE);
+ driver->msg_mask->msg_mask_size =
+ MAX_SSID_PER_RANGE;
+ }
memcpy(buf+header_size, ptr,
4 * (driver->msg_mask->msg_mask_size));
break;
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 45314d9..e5acb6c 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -64,6 +64,8 @@
#define NUM_MEMORY_POOLS 4
#endif
+#define MAX_SSID_PER_RANGE 200
+
#define MODEM_DATA 0
#define LPASS_DATA 1
#define WCNSS_DATA 2
@@ -73,7 +75,13 @@
#define HSIC_2_DATA 6
#define SMUX_DATA 10
#define APPS_PROC 1
-#define MSG_MASK_SIZE 10000
+/*
+ * Each row contains First (uint32_t), Last (uint32_t), Actual
+ * last (uint32_t) values along with the range of SSIDs
+ * (MAX_SSID_PER_RANGE*uint32_t).
+ * And there are MSG_MASK_TBL_CNT rows.
+ */
+#define MSG_MASK_SIZE ((MAX_SSID_PER_RANGE+3) * 4 * MSG_MASK_TBL_CNT)
#define LOG_MASK_SIZE 8000
#define EVENT_MASK_SIZE 1000
#define USER_SPACE_DATA 8192
diff --git a/drivers/char/diag/diagchar_hdlc.c b/drivers/char/diag/diagchar_hdlc.c
index 2369c4d..7b24591 100644
--- a/drivers/char/diag/diagchar_hdlc.c
+++ b/drivers/char/diag/diagchar_hdlc.c
@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/uaccess.h>
+#include <linux/ratelimit.h>
#include <linux/crc-ccitt.h>
#include "diagchar_hdlc.h"
#include "diagchar.h"
@@ -234,3 +235,37 @@
return pkt_bnd;
}
+
+int crc_check(uint8_t *buf, uint16_t len)
+{
+ uint16_t crc = CRC_16_L_SEED;
+ uint8_t sent_crc[2] = {0, 0};
+
+ /*
+ * The minimum length of a valid incoming packet is 4. 1 byte
+ * of data and 3 bytes for CRC
+ */
+ if (!buf || len < 4) {
+ pr_err_ratelimited("diag: In %s, invalid packet or length, buf: 0x%x, len: %d",
+ __func__, (int)buf, len);
+ return -EIO;
+ }
+
+ /*
+ * Run CRC check for the original input. Skip the last 3 CRC
+ * bytes
+ */
+ crc = crc_ccitt(crc, buf, len-3);
+ crc ^= CRC_16_L_SEED;
+
+ /* Check the computed CRC against the original CRC bytes. */
+ sent_crc[0] = buf[len-3];
+ sent_crc[1] = buf[len-2];
+ if (crc != *((uint16_t *)sent_crc)) {
+ pr_debug("diag: In %s, crc mismatch. expected: %x, sent %x.\n",
+ __func__, crc, *((uint16_t *)sent_crc));
+ return -EIO;
+ }
+
+ return 0;
+}
diff --git a/drivers/char/diag/diagchar_hdlc.h b/drivers/char/diag/diagchar_hdlc.h
index e3378ac..2ba46f5 100644
--- a/drivers/char/diag/diagchar_hdlc.h
+++ b/drivers/char/diag/diagchar_hdlc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2009, 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -53,6 +53,8 @@
int diag_hdlc_decode(struct diag_hdlc_decode_type *hdlc);
+int crc_check(uint8_t *buf, uint16_t len);
+
#define ESC_CHAR 0x7D
#define ESC_MASK 0x20
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a1f6b2c..1e8b0ba 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1514,7 +1514,7 @@
void diag_process_hdlc(void *data, unsigned len)
{
struct diag_hdlc_decode_type hdlc;
- int ret, type = 0;
+ int ret, type = 0, crc_chk = 0;
mutex_lock(&driver->diag_hdlc_mutex);
@@ -1528,6 +1528,16 @@
hdlc.escaping = 0;
ret = diag_hdlc_decode(&hdlc);
+ if (ret) {
+ crc_chk = crc_check(hdlc.dest_ptr, hdlc.dest_idx);
+ if (crc_chk) {
+ /* CRC check failed. */
+ pr_err_ratelimited("diag: In %s, bad CRC. Dropping packet\n",
+ __func__);
+ mutex_unlock(&driver->diag_hdlc_mutex);
+ return;
+ }
+ }
/*
* If the message is 3 bytes or less in length then the message is
@@ -1550,9 +1560,8 @@
return;
}
} else if (driver->debug_flag) {
- printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
- " errors or partial packet received, packet"
- " length = %d\n", len);
+ pr_err("diag: In %s, partial packet received, dropping packet, len: %d\n",
+ __func__, len);
print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
DUMP_PREFIX_ADDRESS, data, len, 1);
driver->debug_flag = 0;
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 1ea3cd2..d9e9e09 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -136,12 +136,18 @@
return NULL;
}
-static int ion_iommu_buffer_zero(struct ion_iommu_priv_data *data)
+static int ion_iommu_buffer_zero(struct ion_iommu_priv_data *data,
+ bool is_cached)
{
- int i, j;
+ int i, j, k;
unsigned int npages_to_vmap;
unsigned int total_pages;
void *ptr = NULL;
+ /*
+ * It's cheaper just to use writecombine memory and skip the
+ * cache vs. using a cache memory and trying to flush it afterwards
+ */
+ pgprot_t pgprot = pgprot_writecombine(pgprot_kernel);
/*
* As an optimization, we manually zero out all of the
@@ -161,7 +167,7 @@
for (j = 0; j < MAX_VMAP_RETRIES && npages_to_vmap;
++j) {
ptr = vmap(&data->pages[i], npages_to_vmap,
- VM_IOREMAP, pgprot_kernel);
+ VM_IOREMAP, pgprot);
if (ptr)
break;
else
@@ -171,6 +177,20 @@
return -ENOMEM;
memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
+ if (is_cached) {
+ /*
+ * invalidate the cache to pick up the zeroing
+ */
+ for (k = 0; k < npages_to_vmap; k++) {
+ void *p = kmap_atomic(data->pages[i + k]);
+ phys_addr_t phys = page_to_phys(
+ data->pages[i + k]);
+
+ dmac_inv_range(p, p + PAGE_SIZE);
+ outer_inv_range(phys, phys + PAGE_SIZE);
+ kunmap_atomic(p);
+ }
+ }
vunmap(ptr);
}
@@ -269,7 +289,7 @@
if (flags & ION_FLAG_POOL_FORCE_ALLOC) {
- ret = ion_iommu_buffer_zero(data);
+ ret = ion_iommu_buffer_zero(data, ION_IS_CACHED(flags));
if (ret) {
pr_err("Couldn't vmap the pages for zeroing\n");
goto err3;
@@ -328,7 +348,7 @@
return;
if (!(buffer->flags & ION_FLAG_POOL_FORCE_ALLOC))
- ion_iommu_buffer_zero(data);
+ ion_iommu_buffer_zero(data, ION_IS_CACHED(buffer->flags));
for_each_sg(table->sgl, sg, table->nents, i) {
int order = get_order(sg_dma_len(sg));
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b964620..5102f8f 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,12 @@
.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,
+ .pm_dump_enable = 0,
},
.gmem_base = 0,
.gmem_size = SZ_256K,
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..5c40c8b 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,12 @@
},
.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,
+ .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/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index a1453ae..a90b8f0 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -95,6 +95,7 @@
#define FLASH_LED_UNLOCK_SECURE(base) (base + 0xD0)
#define FLASH_LED_TORCH(base) (base + 0xE4)
#define FLASH_FAULT_DETECT(base) (base + 0x51)
+#define FLASH_PERIPHERAL_SUBTYPE(base) (base + 0x05)
#define FLASH_MAX_LEVEL 0x4F
#define TORCH_MAX_LEVEL 0x0F
@@ -144,6 +145,9 @@
#define FLASH_UNLOCK_SECURE 0xA5
#define FLASH_SECURE_MASK 0xFF
+#define FLASH_SUBTYPE_DUAL 0x01
+#define FLASH_SUBTYPE_SINGLE 0x02
+
#define LED_TRIGGER_DEFAULT "none"
#define RGB_LED_SRC_SEL(base) (base + 0x45)
@@ -366,6 +370,7 @@
* @trigger_flash - trigger flash
* @startup_dly - startup delay for flash
* @strobe_type - select between sw and hw strobe
+ * @peripheral_subtype - module peripheral subtype
* @current_addr - address to write for current
* @second_addr - address of secondary flash to be written
* @safety_timer - enable safety timer or watchdog timer
@@ -385,6 +390,7 @@
u8 trigger_flash;
u8 startup_dly;
u8 strobe_type;
+ u8 peripheral_subtype;
u16 current_addr;
u16 second_addr;
bool safety_timer;
@@ -788,12 +794,40 @@
/* Set led current */
if (val > 0) {
if (led->flash_cfg->torch_enable) {
- rc = qpnp_torch_regulator_operate(led, true);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
+ if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_DUAL) {
+ rc = qpnp_torch_regulator_operate(led, true);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
"Torch regulator operate failed(%d)\n",
rc);
- return rc;
+ return rc;
+ }
+ } else if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_SINGLE) {
+ rc = qpnp_flash_regulator_operate(led, true);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Flash regulator operate failed(%d)\n",
+ rc);
+ goto error_flash_set;
+ }
+
+ /*
+ * Write 0x80 to MODULE_ENABLE before writing
+ * 0xE0 in order to avoid a hardware bug caused
+ * by register value going from 0x00 to 0xE0.
+ */
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MODULE_MASK,
+ FLASH_ENABLE_MODULE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
}
rc = qpnp_led_masked_write(led,
@@ -802,7 +836,7 @@
if (rc) {
dev_err(&led->spmi_dev->dev,
"Secure reg write failed(%d)\n", rc);
- goto error_torch_set;
+ goto error_reg_write;
}
rc = qpnp_led_masked_write(led,
@@ -811,7 +845,7 @@
if (rc) {
dev_err(&led->spmi_dev->dev,
"Torch reg write failed(%d)\n", rc);
- goto error_torch_set;
+ goto error_reg_write;
}
rc = qpnp_led_masked_write(led,
@@ -821,7 +855,7 @@
if (rc) {
dev_err(&led->spmi_dev->dev,
"Current reg write failed(%d)\n", rc);
- goto error_torch_set;
+ goto error_reg_write;
}
rc = qpnp_led_masked_write(led,
@@ -832,7 +866,7 @@
dev_err(&led->spmi_dev->dev,
"2nd Current reg write failed(%d)\n",
rc);
- goto error_torch_set;
+ goto error_reg_write;
}
qpnp_led_masked_write(led, FLASH_MAX_CURR(led->base),
@@ -842,16 +876,31 @@
dev_err(&led->spmi_dev->dev,
"Max current reg write failed(%d)\n",
rc);
- goto error_torch_set;
+ goto error_reg_write;
}
- rc = qpnp_led_masked_write(led,
- FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MASK, FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- goto error_torch_set;
+ if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_DUAL) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK, FLASH_ENABLE_MODULE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n",
+ rc);
+ goto error_torch_set;
+ }
+ } else if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_SINGLE) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK, FLASH_ENABLE_ALL);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n",
+ rc);
+ goto error_flash_set;
+ }
}
} else {
rc = qpnp_flash_regulator_operate(led, true);
@@ -897,9 +946,10 @@
goto error_flash_set;
}
- /* Write 0x80 to MODULE_ENABLE before writing 0xE0
- * in order to avoid reg value goes from 0x00 to
- * 0xE0. This causes a hardware bug.
+ /*
+ * Write 0x80 to MODULE_ENABLE before writing
+ * 0xE0 in order to avoid a hardware bug caused
+ * by register value going from 0x00 to 0xE0.
*/
rc = qpnp_led_masked_write(led,
FLASH_ENABLE_CONTROL(led->base),
@@ -1014,12 +1064,24 @@
goto error_torch_set;
}
- rc = qpnp_torch_regulator_operate(led, false);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Torch regulator operate failed(%d)\n",
- rc);
- return rc;
+ if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_DUAL) {
+ rc = qpnp_torch_regulator_operate(led, false);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Torch regulator operate failed(%d)\n",
+ rc);
+ return rc;
+ }
+ } else if (led->flash_cfg->peripheral_subtype ==
+ FLASH_SUBTYPE_SINGLE) {
+ rc = qpnp_flash_regulator_operate(led, false);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Flash regulator operate failed(%d)\n",
+ rc);
+ return rc;
+ }
}
} else {
rc = qpnp_flash_regulator_operate(led, false);
@@ -1036,6 +1098,10 @@
return 0;
+error_reg_write:
+ if (led->flash_cfg->peripheral_subtype == FLASH_SUBTYPE_SINGLE)
+ goto error_flash_set;
+
error_torch_set:
error = qpnp_torch_regulator_operate(led, false);
if (error) {
@@ -2465,6 +2531,15 @@
return -ENOMEM;
}
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ FLASH_PERIPHERAL_SUBTYPE(led->base),
+ &led->flash_cfg->peripheral_subtype, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read from addr=%x, rc(%d)\n",
+ FLASH_PERIPHERAL_SUBTYPE(led->base), rc);
+ }
+
if (led->id == QPNP_ID_FLASH1_LED0) {
led->flash_cfg->enable_module = FLASH_ENABLE_ALL;
led->flash_cfg->current_addr = FLASH_LED_0_CURR(led->base);
@@ -2473,7 +2548,7 @@
if (!*reg_set) {
led->flash_cfg->flash_boost_reg =
regulator_get(&led->spmi_dev->dev,
- "flash_boost");
+ "flash-boost");
if (IS_ERR(led->flash_cfg->flash_boost_reg)) {
rc = PTR_ERR(led->flash_cfg->flash_boost_reg);
dev_err(&led->spmi_dev->dev,
@@ -2492,7 +2567,7 @@
if (!*reg_set) {
led->flash_cfg->flash_boost_reg =
regulator_get(&led->spmi_dev->dev,
- "flash_boost");
+ "flash-boost");
if (IS_ERR(led->flash_cfg->flash_boost_reg)) {
rc = PTR_ERR(led->flash_cfg->flash_boost_reg);
dev_err(&led->spmi_dev->dev,
@@ -2512,13 +2587,17 @@
of_property_read_bool(node, "qcom,torch-enable");
if (led->flash_cfg->torch_enable) {
- led->flash_cfg->torch_boost_reg =
- regulator_get(&led->spmi_dev->dev, "torch_boost");
- if (IS_ERR(led->flash_cfg->torch_boost_reg)) {
- rc = PTR_ERR(led->flash_cfg->torch_boost_reg);
- dev_err(&led->spmi_dev->dev,
- "Torch regulator get failed(%d)\n", rc);
- goto error_get_torch_reg;
+ if (of_find_property(of_get_parent(node), "torch-boost-supply",
+ NULL)) {
+ led->flash_cfg->torch_boost_reg =
+ regulator_get(&led->spmi_dev->dev,
+ "torch-boost");
+ if (IS_ERR(led->flash_cfg->torch_boost_reg)) {
+ rc = PTR_ERR(led->flash_cfg->torch_boost_reg);
+ dev_err(&led->spmi_dev->dev,
+ "Torch regulator get failed(%d)\n", rc);
+ goto error_get_torch_reg;
+ }
}
}
@@ -3018,7 +3097,7 @@
}
} else if (strncmp(led_label, "flash", sizeof("flash"))
== 0) {
- if (!of_find_property(node, "flash_boost-supply", NULL))
+ if (!of_find_property(node, "flash-boost-supply", NULL))
regulator_probe = true;
rc = qpnp_get_config_flash(led, temp, ®ulator_probe);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index 0840e30..b479857 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -23,8 +23,16 @@
struct msm_isp_buffer *buf;
uint32_t pingpong_bit = 0;
uint32_t bufq_handle = stream_info->bufq_handle;
- uint32_t stats_pingpong_offset =
- STATS_IDX(stream_info->stream_handle) +
+ uint32_t stats_pingpong_offset;
+
+ if (STATS_IDX(stream_info->stream_handle) >=
+ vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__,
+ STATS_IDX(stream_info->stream_handle));
+ return -EINVAL;
+ }
+
+ stats_pingpong_offset = STATS_IDX(stream_info->stream_handle) +
vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset;
pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1);
@@ -151,10 +159,9 @@
stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops.
get_stats_idx(stream_req_cmd->stats_type);
- if ((stats_idx > MSM_ISP_STATS_MAX) ||
- (stats_idx == -EINVAL)) {
- pr_err("%s: Stats idx Error\n", __func__);
- return rc;
+ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, stats_idx);
+ return -EINVAL;
}
stream_info = &stats_data->stream_info[stats_idx];
@@ -209,9 +216,10 @@
}
stats_idx = STATS_IDX(stream_req_cmd->stream_handle);
- if (stats_idx > MSM_ISP_STATS_MAX) {
- pr_err("%s: Stats idx Error\n", __func__);
- return rc;
+
+ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, stats_idx);
+ return -EINVAL;
}
stream_info = &stats_data->stream_info[stats_idx];
@@ -242,9 +250,9 @@
int stats_idx = STATS_IDX(stream_release_cmd->stream_handle);
struct msm_vfe_stats_stream *stream_info = NULL;
- if (stats_idx > MSM_ISP_STATS_MAX) {
- pr_err("%s: Stats idx Error\n", __func__);
- return rc;
+ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, stats_idx);
+ return -EINVAL;
}
stream_info = &stats_data->stream_info[stats_idx];
@@ -379,6 +387,12 @@
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+
+ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, idx);
+ return -EINVAL;
+ }
+
stream_info = &stats_data->stream_info[idx];
if (stream_info->stream_handle !=
stream_cfg_cmd->stream_handle[i]) {
@@ -423,6 +437,12 @@
struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data;
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+
+ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, idx);
+ return -EINVAL;
+ }
+
stream_info = &stats_data->stream_info[idx];
if (stream_info->stream_handle !=
stream_cfg_cmd->stream_handle[i]) {
@@ -453,6 +473,12 @@
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]);
+
+ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) {
+ pr_err("%s Invalid stats index %d", __func__, idx);
+ return -EINVAL;
+ }
+
stream_info = &stats_data->stream_info[idx];
msm_isp_deinit_stats_ping_pong_reg(vfe_dev, stream_info);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index de5a16d..b024569 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -802,6 +802,8 @@
void msm_isp_process_error_info(struct vfe_device *vfe_dev)
{
int i;
+ uint8_t num_stats_type =
+ vfe_dev->hw_info->stats_hw_info->num_stats_type;
struct msm_vfe_error_info *error_info = &vfe_dev->error_info;
static DEFINE_RATELIMIT_STATE(rs,
DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
@@ -825,7 +827,7 @@
error_info->stream_framedrop_count[i] = 0;
}
}
- for (i = 0; i < MSM_ISP_STATS_MAX; i++) {
+ for (i = 0; i < num_stats_type; i++) {
if (error_info->stats_framedrop_count[i] != 0 &&
__ratelimit(&rs_stats)) {
pr_err("%s: Stats stream[%d]: dropped %d frames\n",
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 6b05840..2b963a4 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -40,7 +40,7 @@
#define ISPIF_INTF_CMD_DISABLE_IMMEDIATELY 0x02
#define ISPIF_TIMEOUT_SLEEP_US 1000
-#define ISPIF_TIMEOUT_ALL_US 500000
+#define ISPIF_TIMEOUT_ALL_US 1000000
#undef CDBG
#ifdef CONFIG_MSMB_CAMERA_DEBUG
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
index d302131..3aaff78 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
@@ -1323,6 +1323,11 @@
struct msm_vpe_buff_queue_info_t *buff_queue_info;
VPE_DBG("VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO\n");
+ if (ioctl_ptr->len != sizeof(uint32_t)) {
+ pr_err("%s:%d Invalid len\n", __func__, __LINE__);
+ mutex_unlock(&vpe_dev->mutex);
+ return -EINVAL;
+ }
rc = (copy_from_user(&identity,
(void __user *)ioctl_ptr->ioctl_ptr,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 7f4f231..17c5a14 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -41,6 +41,9 @@
/* Max bytes that can be read per CCI read transaction */
#define CCI_READ_MAX 12
+#define CCI_I2C_READ_MAX_RETRIES 3
+#define CCI_I2C_MAX_READ 8192
+#define CCI_I2C_MAX_WRITE 8192
static struct v4l2_subdev *g_cci_subdev;
@@ -87,36 +90,6 @@
return;
}
-static int32_t msm_cci_i2c_config_sync_timer(struct v4l2_subdev *sd,
- struct msm_camera_cci_ctrl *c_ctrl)
-{
- struct cci_device *cci_dev;
- cci_dev = v4l2_get_subdevdata(sd);
- msm_camera_io_w(c_ctrl->cci_info->cid, cci_dev->base +
- CCI_SET_CID_SYNC_TIMER_0_ADDR + (c_ctrl->cci_info->cid * 0x4));
- return 0;
-}
-
-static int32_t msm_cci_i2c_set_freq(struct v4l2_subdev *sd,
- struct msm_camera_cci_ctrl *c_ctrl)
-{
- struct cci_device *cci_dev;
- uint32_t val;
- cci_dev = v4l2_get_subdevdata(sd);
- val = c_ctrl->cci_info->freq;
- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SCL_CTL_ADDR +
- c_ctrl->cci_info->cci_i2c_master*0x100);
- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_0_ADDR +
- c_ctrl->cci_info->cci_i2c_master*0x100);
- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_1_ADDR +
- c_ctrl->cci_info->cci_i2c_master*0x100);
- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_SDA_CTL_2_ADDR +
- c_ctrl->cci_info->cci_i2c_master*0x100);
- msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_MISC_CTL_ADDR +
- c_ctrl->cci_info->cci_i2c_master*0x100);
- return 0;
-}
-
static void msm_cci_flush_queue(struct cci_device *cci_dev,
enum cci_i2c_master_t master)
{
@@ -213,8 +186,29 @@
uint16_t cmd_size = i2c_msg->size;
struct msm_camera_i2c_reg_conf *i2c_cmd = i2c_msg->reg_conf_tbl;
enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
+
+ if (i2c_cmd == NULL) {
+ pr_err("%s:%d Failed line\n", __func__,
+ __LINE__);
+ return -EINVAL;
+ }
+
+ if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) {
+ pr_err("%s:%d Failed line\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
CDBG("%s addr type %d data type %d\n", __func__,
i2c_msg->addr_type, i2c_msg->data_type);
+
+ if (i2c_msg->addr_type >= MSM_CAMERA_I2C_ADDR_TYPE_MAX) {
+ pr_err("%s failed line %d\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (i2c_msg->data_type >= MSM_CAMERA_I2C_DATA_TYPE_MAX) {
+ pr_err("%s failed line %d\n", __func__, __LINE__);
+ return -EINVAL;
+ }
/* assume total size within the max queue */
while (cmd_size) {
CDBG("%s cmd_size %d addr 0x%x data 0x%x", __func__,
@@ -321,6 +315,18 @@
goto ERROR;
}
+ if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
+ pr_err("%s:%d More than max retries\n", __func__,
+ __LINE__);
+ goto ERROR;
+ }
+
+ if (read_cfg->data == NULL) {
+ pr_err("%s:%d Data ptr is NULL\n", __func__,
+ __LINE__);
+ goto ERROR;
+ }
+
CDBG("%s master %d, queue %d\n", __func__, master, queue);
CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
@@ -341,6 +347,11 @@
goto ERROR;
}
+ if (read_cfg->addr_type >= MSM_CAMERA_I2C_ADDR_TYPE_MAX) {
+ CDBG("%s failed line %d\n", __func__, __LINE__);
+ goto ERROR;
+ }
+
if (read_cfg->addr_type == MSM_CAMERA_I2C_BYTE_ADDR)
val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4) |
((read_cfg->addr & 0xFF) << 8);
@@ -454,9 +465,14 @@
return -EINVAL;
}
+ if (c_ctrl->cci_info->cci_i2c_master > MASTER_MAX) {
+ pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
master = c_ctrl->cci_info->cci_i2c_master;
read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
- if (!read_cfg->num_byte) {
+ if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) {
pr_err("%s:%d read num bytes 0\n", __func__, __LINE__);
rc = -EINVAL;
goto ERROR;
@@ -494,6 +510,10 @@
enum cci_i2c_master_t master;
enum cci_i2c_queue_t queue = QUEUE_0;
cci_dev = v4l2_get_subdevdata(sd);
+ if (c_ctrl->cci_info->cci_i2c_master > MASTER_MAX) {
+ pr_err("%s:%d Invalid I2C master addr\n", __func__, __LINE__);
+ return -EINVAL;
+ }
master = c_ctrl->cci_info->cci_i2c_master;
CDBG("%s master %d, queue %d\n", __func__, master, queue);
CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
@@ -514,6 +534,11 @@
__LINE__, rc);
goto ERROR;
}
+ if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
+ pr_err("%s:%d More than max retries\n", __func__,
+ __LINE__);
+ goto ERROR;
+ }
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
@@ -533,7 +558,11 @@
goto ERROR;
}
- msm_cci_data_queue(cci_dev, c_ctrl, queue);
+ rc = msm_cci_data_queue(cci_dev, c_ctrl, queue);
+ if (rc < 0) {
+ CDBG("%s failed line %d\n", __func__, __LINE__);
+ goto ERROR;
+ }
val = CCI_I2C_UNLOCK_CMD;
CDBG("%s:%d CCI_I2C_UNLOCK_CMD\n", __func__, __LINE__);
rc = msm_cci_write_i2c_queue(cci_dev, val, master, queue);
@@ -622,7 +651,7 @@
if (rc < 0) {
cci_dev->ref_count--;
CDBG("%s: request gpio failed\n", __func__);
- goto clk_enable_failed;
+ goto request_gpio_failed;
}
rc = msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
@@ -647,7 +676,7 @@
__func__, __LINE__);
if (rc == 0)
rc = -ETIMEDOUT;
- return rc;
+ goto reset_complete_failed;
}
msm_cci_set_clk_param(cci_dev);
msm_camera_io_w(CCI_IRQ_MASK_0_RMSK,
@@ -658,7 +687,14 @@
cci_dev->cci_state = CCI_STATE_ENABLED;
return 0;
+reset_complete_failed:
+ disable_irq(cci_dev->irq->start);
+ msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
+ cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 0);
clk_enable_failed:
+ msm_camera_request_gpio_table(cci_dev->cci_gpio_tbl,
+ cci_dev->cci_gpio_tbl_size, 0);
+request_gpio_failed:
return rc;
}
@@ -703,14 +739,6 @@
case MSM_CCI_RELEASE:
rc = msm_cci_release(sd);
break;
- case MSM_CCI_SET_SID:
- break;
- case MSM_CCI_SET_FREQ:
- rc = msm_cci_i2c_set_freq(sd, cci_ctrl);
- break;
- case MSM_CCI_SET_SYNC_CID:
- rc = msm_cci_i2c_config_sync_timer(sd, cci_ctrl);
- break;
case MSM_CCI_I2C_READ:
rc = msm_cci_i2c_read_bytes(sd, cci_ctrl);
break;
@@ -809,7 +837,10 @@
rc = msm_cci_config(sd, arg);
break;
case MSM_SD_SHUTDOWN: {
- return rc;
+ struct msm_camera_cci_ctrl ctrl_cmd;
+ ctrl_cmd.cmd = MSM_CCI_RELEASE;
+ rc = msm_cci_config(sd, &ctrl_cmd);
+ break;
}
default:
rc = -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index 33bee58..1407f12 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -233,7 +233,7 @@
struct device_node *of)
{
int i, rc = 0;
- char property[12];
+ char property[14];
uint32_t count = 6;
struct msm_eeprom_board_info *eb = e_ctrl->eboard_info;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
index 50e5a0f..2de17c9 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_flash.c
@@ -42,6 +42,9 @@
return fctrl->func_tbl->flash_get_subdev_id(fctrl, argp);
case VIDIOC_MSM_FLASH_LED_DATA_CFG:
return fctrl->func_tbl->flash_led_config(fctrl, argp);
+ case MSM_SD_SHUTDOWN:
+ *(int *)argp = MSM_CAMERA_LED_RELEASE;
+ return fctrl->func_tbl->flash_led_config(fctrl, argp);
default:
pr_err("invalid cmd %d\n", cmd);
return -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/gc0339.c b/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
index 790dd28..8288ad0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/gc0339.c
@@ -254,9 +254,12 @@
0);
break;
case SENSOR_GPIO:
- gpio_set_value_cansleep(
- data->gpio_conf->gpio_num_info->gpio_num
- [power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+ if (data->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val])
+ gpio_set_value_cansleep(
+ data->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val],
+ GPIOF_OUT_INIT_LOW);
break;
case SENSOR_VREG:
msm_camera_config_single_vreg(s_ctrl->dev,
@@ -322,9 +325,12 @@
SENSOR_GPIO_MAX);
continue;
}
- gpio_set_value_cansleep(
- data->gpio_conf->gpio_num_info->gpio_num
- [power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+ if (data->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val])
+ gpio_set_value_cansleep(
+ data->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val],
+ GPIOF_OUT_INIT_LOW);
break;
case SENSOR_VREG:
if (power_setting->seq_val >= CAM_VREG_MAX) {
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/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 6764db6..1724db1 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -967,6 +967,7 @@
struct msm_sensor_power_setting_array *power_setting_array = NULL;
struct msm_sensor_power_setting *power_setting = NULL;
struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
+ s_ctrl->stop_setting_valid = 0;
CDBG("%s:%d\n", __func__, __LINE__);
power_setting_array = &s_ctrl->power_setting_array;
@@ -1271,9 +1272,8 @@
case VIDIOC_MSM_SENSOR_GET_AF_STATUS:
return msm_sensor_get_af_status(s_ctrl, argp);
case VIDIOC_MSM_SENSOR_RELEASE:
- msm_sensor_stop_stream(s_ctrl);
- return 0;
case MSM_SD_SHUTDOWN:
+ msm_sensor_stop_stream(s_ctrl);
return 0;
default:
return -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 36a2658..9194d46 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");
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/mmc/card/block.c b/drivers/mmc/card/block.c
index da07947..6ef389c 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1640,6 +1640,13 @@
ext_csd[EXT_CSD_CORRECTLY_PRG_SECTORS_NUM + 2] << 16 |
ext_csd[EXT_CSD_CORRECTLY_PRG_SECTORS_NUM + 3] << 24);
+ /*
+ * skip packed command header (1 sector) included by the counter but not
+ * actually written to the NAND
+ */
+ if (correctly_done >= card->ext_csd.data_sector_size)
+ correctly_done -= card->ext_csd.data_sector_size;
+
list_for_each_entry(prq, &mq_rq->packed_list, queuelist) {
if ((correctly_done - (int)blk_rq_bytes(prq)) < 0) {
/* prq is not successfull */
@@ -2993,11 +3000,6 @@
return ret;
}
-#define CID_MANFID_SANDISK 0x2
-#define CID_MANFID_TOSHIBA 0x11
-#define CID_MANFID_MICRON 0x13
-#define CID_MANFID_SAMSUNG 0x15
-
static const struct mmc_fixup blk_fixups[] =
{
MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 507cd5b..8986829 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -264,7 +264,7 @@
if ((host->caps2 & MMC_CAP2_STOP_REQUEST) &&
host->ops->stop_request &&
- mq->card->ext_csd.hpi)
+ mq->card->ext_csd.hpi_en)
blk_urgent_request(mq->queue, mmc_urgent_request);
memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
@@ -285,7 +285,9 @@
if (mmc_can_erase(card))
mmc_queue_setup_discard(mq->queue, card);
- if ((mmc_can_sanitize(card) && (host->caps2 & MMC_CAP2_SANITIZE)))
+ /* Don't enable Sanitize if HPI is not supported */
+ if ((mmc_can_sanitize(card) && (host->caps2 & MMC_CAP2_SANITIZE) &&
+ card->ext_csd.hpi_en))
mmc_queue_setup_sanitize(mq->queue);
#ifdef CONFIG_MMC_BLOCK_BOUNCE
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c5e8021..91efb12 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -607,7 +607,7 @@
int err = 0;
u32 status;
- if (!host->ops->stop_request || !card->ext_csd.hpi) {
+ if (!host->ops->stop_request || !card->ext_csd.hpi_en) {
pr_warn("%s: host ops stop_request() or HPI not supported\n",
mmc_hostname(host));
return -ENOTSUPP;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 4fb0675..e1609cf 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -58,6 +58,17 @@
__res & __mask; \
})
+static const struct mmc_fixup mmc_fixups[] = {
+ /*
+ * Certain Hynix eMMC 4.41 cards might get broken when HPI feature
+ * is used so disable the HPI feature for such buggy cards.
+ */
+ MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX,
+ 0x014a, add_quirk, MMC_QUIRK_BROKEN_HPI, 5),
+
+ END_FIXUP
+};
+
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
@@ -307,6 +318,9 @@
goto out;
}
+ /* fixup device after ext_csd revision field is updated */
+ mmc_fixup_device(card, mmc_fixups);
+
card->ext_csd.raw_sectors[0] = ext_csd[EXT_CSD_SEC_CNT + 0];
card->ext_csd.raw_sectors[1] = ext_csd[EXT_CSD_SEC_CNT + 1];
card->ext_csd.raw_sectors[2] = ext_csd[EXT_CSD_SEC_CNT + 2];
@@ -471,8 +485,28 @@
}
if (card->ext_csd.rev >= 5) {
- /* check whether the eMMC card supports BKOPS */
- if (ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) {
+ /* check whether the eMMC card supports HPI */
+ if ((ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) &&
+ !(card->quirks & MMC_QUIRK_BROKEN_HPI)) {
+ card->ext_csd.hpi = 1;
+ if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
+ card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
+ else
+ card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
+ /*
+ * Indicate the maximum timeout to close
+ * a command interrupted by HPI
+ */
+ card->ext_csd.out_of_int_time =
+ ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
+ }
+
+ /*
+ * check whether the eMMC card supports BKOPS.
+ * If HPI is not supported then BKOPs shouldn't be enabled.
+ */
+ if ((ext_csd[EXT_CSD_BKOPS_SUPPORT] & 0x1) &&
+ card->ext_csd.hpi) {
card->ext_csd.bkops = 1;
card->ext_csd.bkops_en = ext_csd[EXT_CSD_BKOPS_EN];
card->ext_csd.raw_bkops_status =
@@ -492,21 +526,6 @@
pr_info("%s: BKOPS_EN bit = %d\n",
mmc_hostname(card->host), card->ext_csd.bkops_en);
- /* check whether the eMMC card supports HPI */
- if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) {
- card->ext_csd.hpi = 1;
- if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
- card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
- else
- card->ext_csd.hpi_cmd = MMC_SEND_STATUS;
- /*
- * Indicate the maximum timeout to close
- * a command interrupted by HPI
- */
- card->ext_csd.out_of_int_time =
- ext_csd[EXT_CSD_OUT_OF_INTERRUPT_TIME] * 10;
- }
-
card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
@@ -1508,9 +1527,10 @@
/*
* If cache size is higher than 0, this indicates
* the existence of cache and it can be turned on.
+ * If HPI is not supported then cache shouldn't be enabled.
*/
if ((host->caps2 & MMC_CAP2_CACHE_CTRL) &&
- card->ext_csd.cache_size > 0) {
+ (card->ext_csd.cache_size > 0) && card->ext_csd.hpi_en) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, 1,
card->ext_csd.generic_cmd6_time);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 164c418..32e126b 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -598,7 +598,7 @@
unsigned int opcode;
int err;
- if (!card->ext_csd.hpi) {
+ if (!card->ext_csd.hpi_en) {
pr_warning("%s: Card didn't support HPI command\n",
mmc_hostname(card->host));
return -EINVAL;
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index 59f0340..4407d91 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -107,6 +107,8 @@
(f->name == CID_NAME_ANY ||
!strncmp(f->name, card->cid.prod_name,
sizeof(card->cid.prod_name))) &&
+ (f->ext_csd_rev == EXT_CSD_REV_ANY ||
+ f->ext_csd_rev == card->ext_csd.rev) &&
(f->cis_vendor == card->cis.vendor ||
f->cis_vendor == (u16) SDIO_ANY_ID) &&
(f->cis_device == card->cis.device ||
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index e318ecf..cc2049d 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -25,6 +25,7 @@
#include <asm/mach/time.h>
+#define ALARM_DELTA 120
#define ANDROID_ALARM_PRINT_ERROR (1U << 0)
#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
#define ANDROID_ALARM_PRINT_TSET (1U << 2)
@@ -512,6 +513,15 @@
rtc_tm_to_time(&rtc_time, &rtc_secs);
alarm_delta = wall_time.tv_sec - rtc_secs;
alarm_time = power_on_alarm - alarm_delta;
+
+ /*
+ * Substract ALARM_DELTA from actual alarm time
+ * to powerup the device before actual alarm
+ * expiration.
+ */
+ if ((alarm_time - ALARM_DELTA) > rtc_secs)
+ alarm_time -= ALARM_DELTA;
+
if (alarm_time <= rtc_secs)
goto disable_alarm;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index c862e78..6a1e7f7c 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -211,7 +211,8 @@
in_vreg[i].vreg_name, rc);
goto vreg_set_opt_mode_fail;
}
- msleep(in_vreg[i].pre_on_sleep);
+ if (in_vreg[i].pre_on_sleep)
+ msleep(in_vreg[i].pre_on_sleep);
rc = regulator_set_optimum_mode(in_vreg[i].vreg,
in_vreg[i].enable_load);
if (rc < 0) {
@@ -221,7 +222,8 @@
goto vreg_set_opt_mode_fail;
}
rc = regulator_enable(in_vreg[i].vreg);
- msleep(in_vreg[i].post_on_sleep);
+ if (in_vreg[i].post_on_sleep)
+ msleep(in_vreg[i].post_on_sleep);
if (rc < 0) {
DEV_ERR("%pS->%s: %s enable failed\n",
__builtin_return_address(0), __func__,
@@ -232,11 +234,13 @@
} else {
for (i = num_vreg-1; i >= 0; i--)
if (regulator_is_enabled(in_vreg[i].vreg)) {
- msleep(in_vreg[i].pre_off_sleep);
+ if (in_vreg[i].pre_off_sleep)
+ msleep(in_vreg[i].pre_off_sleep);
regulator_set_optimum_mode(in_vreg[i].vreg,
in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
- msleep(in_vreg[i].post_off_sleep);
+ if (in_vreg[i].post_off_sleep)
+ msleep(in_vreg[i].post_off_sleep);
}
}
return rc;
@@ -246,11 +250,13 @@
vreg_set_opt_mode_fail:
for (i--; i >= 0; i--) {
- msleep(in_vreg[i].pre_off_sleep);
+ if (in_vreg[i].pre_off_sleep)
+ msleep(in_vreg[i].pre_off_sleep);
regulator_set_optimum_mode(in_vreg[i].vreg,
in_vreg[i].disable_load);
regulator_disable(in_vreg[i].vreg);
- msleep(in_vreg[i].post_off_sleep);
+ if (in_vreg[i].post_off_sleep)
+ msleep(in_vreg[i].post_off_sleep);
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 91257f2..38b587d 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -363,7 +363,6 @@
};
struct mdss_overlay_private {
- int vsync_pending;
ktime_t vsync_time;
struct sysfs_dirent *vsync_event_sd;
int borderfill_enable;
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_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 938cb1f..32fea95 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1372,14 +1372,13 @@
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
{
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
int rc;
if (!ctl)
return -ENODEV;
if (!ctl->add_vsync_handler || !ctl->remove_vsync_handler)
- return -ENOTSUPP;
+ return -EOPNOTSUPP;
rc = mutex_lock_interruptible(&ctl->lock);
if (rc)
@@ -1388,9 +1387,8 @@
if (!ctl->power_on) {
pr_debug("fb%d vsync pending first update en=%d\n",
mfd->index, en);
- mdp5_data->vsync_pending = en;
mutex_unlock(&ctl->lock);
- return 0;
+ return -EPERM;
}
pr_debug("fb%d vsync en=%d\n", mfd->index, en);
@@ -2009,11 +2007,7 @@
if (IS_ERR_VALUE(rc)) {
pr_err("Failed to turn on fb%d\n", mfd->index);
mdss_mdp_overlay_off(mfd);
- } else if (mdp5_data->vsync_pending) {
- mdp5_data->vsync_pending = 0;
- mdss_mdp_overlay_vsync_ctrl(mfd, mdp5_data->vsync_pending);
}
-
return rc;
}
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/mmc/card.h b/include/linux/mmc/card.h
index 7852423..9d15908 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -349,6 +349,8 @@
#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */
/* byte mode */
#define MMC_QUIRK_INAND_DATA_TIMEOUT (1<<8) /* For incorrect data timeout */
+/* To avoid eMMC device getting broken permanently due to HPI feature */
+#define MMC_QUIRK_BROKEN_HPI (1 << 11)
unsigned int erase_size; /* erase size in sectors */
unsigned int erase_shift; /* if erase unit is power 2 */
@@ -428,6 +430,8 @@
/* SDIO-specfic fields. You can use SDIO_ANY_ID here of course */
u16 cis_vendor, cis_device;
+ /* for MMC cards */
+ unsigned int ext_csd_rev;
void (*vendor_fixup)(struct mmc_card *card, int data);
int data;
@@ -437,11 +441,19 @@
#define CID_OEMID_ANY ((unsigned short) -1)
#define CID_NAME_ANY (NULL)
+#define EXT_CSD_REV_ANY (-1u)
+
+#define CID_MANFID_SANDISK 0x2
+#define CID_MANFID_TOSHIBA 0x11
+#define CID_MANFID_MICRON 0x13
+#define CID_MANFID_SAMSUNG 0x15
+#define CID_MANFID_HYNIX 0x90
+
#define END_FIXUP { 0 }
#define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \
_cis_vendor, _cis_device, \
- _fixup, _data) \
+ _fixup, _data, _ext_csd_rev) \
{ \
.name = (_name), \
.manfid = (_manfid), \
@@ -452,23 +464,30 @@
.cis_device = (_cis_device), \
.vendor_fixup = (_fixup), \
.data = (_data), \
+ .ext_csd_rev = (_ext_csd_rev), \
}
#define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \
- _fixup, _data) \
+ _fixup, _data, _ext_csd_rev) \
_FIXUP_EXT(_name, _manfid, \
_oemid, _rev_start, _rev_end, \
SDIO_ANY_ID, SDIO_ANY_ID, \
- _fixup, _data) \
+ _fixup, _data, _ext_csd_rev) \
-#define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \
- MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data)
+#define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \
+ MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
+ EXT_CSD_REV_ANY)
+
+#define MMC_FIXUP_EXT_CSD_REV(_name, _manfid, _oemid, _fixup, _data, \
+ _ext_csd_rev) \
+ MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
+ _ext_csd_rev)
#define SDIO_FIXUP(_vendor, _device, _fixup, _data) \
_FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \
CID_OEMID_ANY, 0, -1ull, \
_vendor, _device, \
- _fixup, _data) \
+ _fixup, _data, EXT_CSD_REV_ANY) \
#define cid_rev(hwrev, fwrev, year, month) \
(((u64) hwrev) << 40 | \
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/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 15391d8..540fd2c 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -52,6 +52,7 @@
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
MSM_CAMERA_I2C_3B_ADDR,
+ MSM_CAMERA_I2C_ADDR_TYPE_MAX,
};
enum msm_camera_i2c_data_type {
@@ -62,6 +63,7 @@
MSM_CAMERA_I2C_SET_WORD_MASK,
MSM_CAMERA_I2C_UNSET_WORD_MASK,
MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
+ MSM_CAMERA_I2C_DATA_TYPE_MAX,
};
enum msm_sensor_power_seq_type_t {
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/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 90430b7..1604bf2 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -494,8 +494,10 @@
}
if (ops->fill_info) {
data = nla_nest_start(skb, IFLA_INFO_DATA);
- if (data == NULL)
+ if (data == NULL) {
+ err = -EMSGSIZE;
goto err_cancel_link;
+ }
err = ops->fill_info(skb, dev);
if (err < 0)
goto err_cancel_data;
@@ -1059,7 +1061,7 @@
rcu_read_lock();
cb->seq = net->dev_base_seq;
- if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+ if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
ifla_policy) >= 0) {
if (tb[IFLA_EXT_MASK])
@@ -1902,7 +1904,7 @@
u32 ext_filter_mask = 0;
u16 min_ifinfo_dump_size = 0;
- if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+ if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
ifla_policy) >= 0) {
if (tb[IFLA_EXT_MASK])
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
diff --git a/net/core/sock.c b/net/core/sock.c
index b2e14c0..0f8402e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1600,6 +1600,11 @@
gfp_t gfp_mask;
long timeo;
int err;
+ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+ err = -EMSGSIZE;
+ if (npages > MAX_SKB_FRAGS)
+ goto failure;
gfp_mask = sk->sk_allocation;
if (gfp_mask & __GFP_WAIT)
@@ -1618,14 +1623,12 @@
if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
skb = alloc_skb(header_len, gfp_mask);
if (skb) {
- int npages;
int i;
/* No pages, we're done... */
if (!data_len)
break;
- npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
skb->truesize += data_len;
skb_shinfo(skb)->nr_frags = npages;
for (i = 0; i < npages; i++) {
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index fcc264c..c0448f2 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -42,6 +42,13 @@
#define TAPAN_HPH_PA_SETTLE_COMP_ON 3000
#define TAPAN_HPH_PA_SETTLE_COMP_OFF 13000
+#define TAPAN_VDD_CX_OPTIMAL_UA 10000
+#define TAPAN_VDD_CX_SLEEP_UA 2000
+
+static struct regulator *tapan_codec_find_regulator(
+ struct snd_soc_codec *codec,
+ const char *name);
+
static atomic_t kp_tapan_priv;
static int spkr_drv_wrnd_param_set(const char *val,
const struct kernel_param *kp);
@@ -59,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
@@ -966,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),
@@ -988,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),
@@ -1017,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),
@@ -1034,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),
@@ -1082,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),
@@ -1089,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[] = {
@@ -1106,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"
};
@@ -1212,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);
@@ -1301,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);
@@ -2515,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"},
@@ -2630,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"},
@@ -2640,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"},
@@ -2678,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"},
@@ -2756,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"},
@@ -2783,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"},
@@ -2793,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"},
@@ -2832,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"},
@@ -2847,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)
@@ -2988,6 +3045,28 @@
}
}
+static void tapan_set_vdd_cx_current(struct snd_soc_codec *codec,
+ int current_uA)
+{
+ struct regulator *cx_regulator;
+ int ret;
+
+ cx_regulator = tapan_codec_find_regulator(codec,
+ "cdc-vdd-cx");
+
+ if (!cx_regulator) {
+ dev_err(codec->dev, "%s: Regulator %s not defined\n",
+ __func__, "cdc-vdd-cx-supply");
+ return;
+ }
+
+ ret = regulator_set_optimum_mode(cx_regulator, current_uA);
+ if (ret < 0)
+ dev_err(codec->dev,
+ "%s: Failed to set vdd_cx current to %d\n",
+ __func__, current_uA);
+}
+
int tapan_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
{
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
@@ -2997,6 +3076,7 @@
WCD9XXX_BG_CLK_LOCK(&tapan->resmgr);
if (mclk_enable) {
+ tapan_set_vdd_cx_current(codec, TAPAN_VDD_CX_OPTIMAL_UA);
wcd9xxx_resmgr_get_bandgap(&tapan->resmgr,
WCD9XXX_BANDGAP_AUDIO_MODE);
wcd9xxx_resmgr_get_clk_block(&tapan->resmgr, WCD9XXX_CLK_MCLK);
@@ -3005,6 +3085,8 @@
wcd9xxx_resmgr_put_clk_block(&tapan->resmgr, WCD9XXX_CLK_MCLK);
wcd9xxx_resmgr_put_bandgap(&tapan->resmgr,
WCD9XXX_BANDGAP_AUDIO_MODE);
+ /* Set the vdd cx power rail sleep mode current */
+ tapan_set_vdd_cx_current(codec, TAPAN_VDD_CX_SLEEP_UA);
}
WCD9XXX_BG_CLK_UNLOCK(&tapan->resmgr);
@@ -3439,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",
@@ -3844,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,
@@ -3901,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),
@@ -3921,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 |
@@ -3941,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),
@@ -4004,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),
@@ -4066,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 |
@@ -4117,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 |
@@ -4153,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,
@@ -4184,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),
@@ -4807,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;
@@ -4924,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));
@@ -5000,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),
};
@@ -5034,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);