Merge "msm: wfd: protect queued buffers list with lock"
diff --git a/Documentation/devicetree/bindings/arm/msm/smdtty.txt b/Documentation/devicetree/bindings/arm/msm/smdtty.txt
new file mode 100644
index 0000000..f661b84
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/smdtty.txt
@@ -0,0 +1,40 @@
+Qualcomm Shared Memory TTY Driver (smdtty)
+
+[Root level node]
+Required properties:
+-compatible : should be "qcom,smdtty"
+
+[Second level nodes]
+qcom,smdtty-port-names
+Required properties:
+-qcom,smdtty-remote: the remote subsystem name
+-qcom,smdtty-port-name : the smd channel name
+
+Optional properties:
+-qcom,smdtty-dev-name : the smdtty device name
+
+Required alias:
+- The index into TTY subsystem is specified via an alias with the following format
+ 'smd{n}' where n is the tty device index.
+
+Example:
+ aliases {
+ smd1 = &smdtty_apps_fm;
+ smd36 = &smdtty_loopback;
+ };
+
+ qcom,smdtty {
+ compatible = "qcom,smdtty";
+
+ smdtty_apps_fm: qcom,smdtty-apps-fm {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_FM";
+ };
+
+ smdtty_loopback: smdtty-loopback {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "LOOPBACK";
+ qcom,smdtty-dev-name = "LOOPBACK_TTY";
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 44134f8..49cd567 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -215,6 +215,10 @@
- qcom,mdss-dsi-off-command-state: String that specifies the ctrl state for sending OFF commands.
"dsi_lp_mode" = DSI low power mode (default)
"dsi_hs_mode" = DSI high speed mode
+- qcom,mdss-pan-physical-width-dimension: Specifies panel physical width in mm which corresponds
+ to the physical width in the framebuffer information.
+- qcom,mdss-pan-physical-height-dimension: Specifies panel physical height in mm which corresponds
+ to the physical height in the framebuffer information.
Note, if a given optional qcom,* binding is not present, then the driver will configure
@@ -303,5 +307,7 @@
qcom,mdss-dsi-bl-pmic-bank-select = <0>;
qcom,mdss-dsi-bl-pmic-pwm-frequency = <0>;
qcom,mdss-dsi-pwm-gpio = <&pm8941_mpps 5 0>;
+ qcom,mdss-pan-physical-width-dimension = <60>;
+ qcom,mdss-pan-physical-height-dimension = <140>;
};
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
index d77e96c..ce60d8d 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -23,6 +23,10 @@
- focaltech,display-coords : display coordinates in pixels. It is a four
tuple consisting of min x, min y, max x and
max y values
+ - focaltech,name : name of the controller
+ - focaltech,group-id : group id of this device
+ - focaltech,hard-reset-delay-ms : hard reset delay in ms
+ - focaltech,soft-reset-delay-ms : soft reset delay in ms
Optional properties:
@@ -33,21 +37,43 @@
- focaltech,no-force-update : to specify force update is allowed
- focaltech,button-map : button map of key codes. The number
of key codes depend on panel
-
+ - focaltech,fw-name : specify the firmware file name
+ - focaltech,fw-delay-aa-ms : specify the "aa" delay in ms for firmware upgrade
+ - focaltech,fw-delay-55-ms : specify the "55" delay in ms for firmware upgrade
+ - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
+ - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
+ - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
+ - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
+ - focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade
Example:
- i2c@f9924000 {
- ft5x06_ts@38 {
+ i2c@f9923000{
+ focaltech@38{
compatible = "focaltech,5x06";
reg = <0x38>;
interrupt-parent = <&msmgpio>;
- interrupts = <61 0x2>;
- vdd-supply = <&pm8941_l22>;
- vcc_i2c-supply = <&pm8941_s3>;
- focaltech,reset-gpio = <&msmgpio 60 0x00>;
- focaltech,irq-gpio = <&msmgpio 61 0x00>;
- focaltech,panel-coords = <0 0 480 800>;
+ interrupts = <1 0x2>;
+ vdd-supply = <&pm8110_l19>;
+ vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,name = "ft6x06";
+ focaltech,family-id = <0x06>;
+ focaltech,reset-gpio = <&msmgpio 0 0x00>;
+ focaltech,irq-gpio = <&msmgpio 1 0x00>;
focaltech,display-coords = <0 0 480 800>;
- focaltech,button-map= <158 102 139 217>;
- focaltech,family-id = <0x0a>;
+ focaltech,panel-coords = <0 0 480 800>;
+ focaltech,button-map= <139 102 158>;
+ focaltech,no-force-update;
+ focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay = <20>;
+ focaltech,soft-reset-delay = <150>;
+ focaltech,num-max-touches = <2>;
+ focaltech,fw-name = "ft_8610_qrd_fw.bin";
+ focaltech,fw-delay-aa-ms = <100>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
+ focaltech,fw-auto-cal;
};
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index 0f35e73..8fd813c 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -14,12 +14,14 @@
- vdd-supply : Analog power supply needed to power device
- vcc_i2c-supply : Power source required to pull up i2c bus
- synaptics,i2c-pull-up : specify to indicate pull up is needed
+ - synaptics,disable-gpios : specify to disable gpios in suspend (power saving)
- synaptics,button-map : virtual key code mappings to be used
- synaptics,x-flip : modify orientation of the x axis
- synaptics,y-flip : modify orientation of the y axis
- synaptics,panel-x : panel x dimension
- synaptics,panel-y : panel y dimension
- synaptics,fw-image-name : name of firmware .img file in /etc/firmware
+ - synaptics,power-down : fully power down regulators in suspend
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
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/mmc/sdhci-msm.txt b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
index 013d56e..d502f78 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
@@ -73,7 +73,8 @@
- qcom,pad-pull-off - Suspend pull configuration for sdc tlmm pins.
- qcom,pad-drv-on - Active drive strength configuration for sdc tlmm pins.
- qcom,pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
- Tlmm pins are specified as <clk cmd data>
+ Tlmm pins are specified as <clk cmd data> and starting with eMMC5.0 as
+ <clk cmd data rclk>
- qcom,bus-bw-vectors-bps: specifies array of throughput values in
Bytes/sec. The values in the array are determined according to
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/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index 9abf54e..489eb38 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -35,6 +35,12 @@
- qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
- qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
+ - cdc-vdd-buckhelper-supply: phandle of helper regulator supply's
+ device tree node. This supply is a helper regulator for
+ cdc-vdd-buck-supply regulator.
+ - cdc-vdd-buckhelper-voltage: helper supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buckhelper-current: helper supply's max current in mA.
+
- qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
hardware probe. Supplies in this list will be
stay enabled.
@@ -76,6 +82,10 @@
dynamically.
Supplies in this list are off by default.
+- qcom,cdc-cp-supplies: List of supplies required for codec chargepump enable
+ Supplies in this list can be enabled/disabled dynamically and
+ are off by default.
+
- qcom,cdc-micbias2-headset-only: Boolean. Allow micbias 2 only to headset mic.
Example:
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 2c5e57f..e4fc96c 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -826,43 +826,43 @@
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>;
+ };
+ };
};
};
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-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index fb24a25..64e4b6e 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -30,6 +30,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 +111,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 104cb4c..79476ea 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-cdp.dtsi
@@ -36,6 +36,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
};
@@ -111,6 +112,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-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 5f991fb..8852a8d 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -41,7 +41,7 @@
qcom,vbif-settings = <0x004 0x00000001>,
<0x0D8 0x00000707>,
<0x124 0x00000003>;
- qcom,mdp-settings = <0x02E0 0x000000A9>,
+ qcom,mdp-settings = <0x02E0 0x000000A5>,
<0x02E4 0x00000055>;
mdss_fb0: qcom,mdss_fb_primary {
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 977c772..8fc2c7b 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -36,6 +36,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
};
@@ -105,14 +106,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 7d7d949..6e5bc54 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -31,6 +31,7 @@
synaptics,button-map = <139 102 158>;
synaptics,i2c-pull-up;
synaptics,power-down;
+ synaptics,disable-gpios;
};
focaltech@38 {
compatible = "focaltech,5x06";
@@ -116,15 +117,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-pm.dtsi b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8226-pm.dtsi
rename to arch/arm/boot/dts/msm8226-v1-pm.dtsi
index ef0a55e..19b76de 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -179,7 +179,7 @@
<0xff 176>, /* o_wcss_apss_smsm_irq */
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
- <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 179>, /* o_wcss_apss_asic_intr */
<0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index d73fb93..1cbf00d 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -80,15 +80,15 @@
goodix,button-map= <158 102 139>;
goodix,family-id = <0x0>;
goodix,cfg-data = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
+ 41 D0 02 00 05 0A 35 01 01 0F
+ 2D 08 55 32 03 04 00 00 00 00
+ 00 00 05 0A 0C 0F 0A 8C 0E 0E
+ 30 2E B8 08 00 00 00 83 03 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 2D 62 94 C5 02 05 00 00 04
+ 96 30 00 80 39 00 71 42 00 63
+ 4D 00 56 5A 00 56 10 38 68 00
+ 56 50 35 AA AA 27 00 00 00 00
00 01 1B 14 0C 14 00 00 01 00
00 00 00 00 00 00 00 00 00 00
00 00 02 04 06 08 0A 0C 0E 10
@@ -97,8 +97,8 @@
FF FF 00 02 04 06 08 0A 0C 0F
10 12 13 14 16 18 1C 1D 1E 1F
20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF 06 01];
};
};
};
diff --git a/arch/arm/boot/dts/msm8226-v1.dtsi b/arch/arm/boot/dts/msm8226-v1.dtsi
index 2833673..8d127e8 100644
--- a/arch/arm/boot/dts/msm8226-v1.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-v1-pm.dtsi"
&tsens {
qcom,sensors = <4>;
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
similarity index 94%
copy from arch/arm/boot/dts/msm8226-pm.dtsi
copy to arch/arm/boot/dts/msm8226-v2-pm.dtsi
index ef0a55e..c46f847 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -96,6 +96,8 @@
qcom,phase-port = <0x1>;
qcom,pfm-port = <0x2>;
qcom,saw2-spm-cmd-ret = [00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 6b c0 e0 d0 42 07 50
+ 4e 02 02 d0 e0 c0 22 6b 02 32 50 0f];
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
@@ -130,7 +132,7 @@
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,l2 = "l2_cache_retention";
+ qcom,l2 = "l2_cache_gdhs";
qcom,latency-us = <20000>;
qcom,ss-power = <138>;
qcom,energy-overhead = <1208400>;
@@ -179,7 +181,7 @@
<0xff 176>, /* o_wcss_apss_smsm_irq */
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
- <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 179>, /* o_wcss_apss_asic_intr */
<0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 320cea1..fba41e5 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -81,15 +81,15 @@
goodix,button-map= <158 102 139>;
goodix,family-id = <0x0>;
goodix,cfg-data = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
+ 41 D0 02 00 05 0A 35 01 01 0F
+ 2D 08 55 32 03 04 00 00 00 00
+ 00 00 05 0A 0C 0F 0A 8C 0E 0E
+ 30 2E B8 08 00 00 00 83 03 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 2D 62 94 C5 02 05 00 00 04
+ 96 30 00 80 39 00 71 42 00 63
+ 4D 00 56 5A 00 56 10 38 68 00
+ 56 50 35 AA AA 27 00 00 00 00
00 01 1B 14 0C 14 00 00 01 00
00 00 00 00 00 00 00 00 00 00
00 00 02 04 06 08 0A 0C 0E 10
@@ -98,8 +98,8 @@
FF FF 00 02 04 06 08 0A 0C 0F
10 12 13 14 16 18 1C 1D 1E 1F
20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF 06 01];
};
};
};
@@ -161,6 +161,10 @@
};
};
+&pm8226_bms {
+ qcom,use-external-rsense;
+};
+
&pm8226_iadc {
qcom,rsense = <10000000>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 2b3b7c2..9681d2a 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8226.dtsi"
+/include/ "msm8226-v2-pm.dtsi"
&pm8226_l3 {
regulator-min-microvolt = <750000>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 8f153cd..0ae0fc6 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -51,7 +51,6 @@
/include/ "msm8226-camera.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8226-iommu.dtsi"
-/include/ "msm8226-pm.dtsi"
/include/ "msm8226-smp2p.dtsi"
/include/ "msm8226-gpu.dtsi"
/include/ "msm8226-bus.dtsi"
@@ -332,20 +331,21 @@
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>;
- qcom,cdc-static-supplies = "cdc-vdd-buck",
- "cdc-vdd-h",
+ cdc-vdd-buckhelper-supply = <&pm8226_l25>;
+ qcom,cdc-vdd-buckhelper-voltage = <1775000 2125000>;
+ qcom,cdc-vdd-buckhelper-current = <10000>;
+
+ qcom,cdc-static-supplies = "cdc-vdd-h",
"cdc-vdd-px",
- "cdc-vdd-a-1p2v",
"cdc-vdd-cx";
+ qcom,cdc-cp-supplies = "cdc-vdd-buck",
+ "cdc-vdd-buckhelper";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -377,6 +377,18 @@
qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
};
+ sound-9302 {
+ compatible = "qcom,msm8226-audio-tapan";
+ qcom,model = "msm8226-tapan9302-snd-card";
+ qcom,tapan-mclk-clk-freq = <9600000>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 63 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 64 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
+ qcom,tapan-codec-9302;
+ };
+
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
qcom,msm-pcm-dsp-id = <0>;
@@ -912,6 +924,8 @@
interrupts = <0 99 0>;
qcom,i2c-bus-freq = <384000>;
qcom,i2c-src-freq = <19200000>;
+ qcom,sda-gpio = <&msmgpio 18 0>;
+ qcom,scl-gpio = <&msmgpio 19 0>;
};
qcom,acpuclk@f9011050 {
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8610-cdp.dts
rename to arch/arm/boot/dts/msm8610-cdp.dtsi
index 519ca2f..bfccb78 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -10,19 +10,6 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8610.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
-/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
-
-/ {
- model = "Qualcomm MSM 8610 CDP";
- compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
- qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
- <163 1 0>, <164 1 0>, <166 1 0>;
-};
-
&soc {
serial@f991e000 {
status = "ok";
@@ -52,7 +39,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 02 00 0A 06 0D 00 00
+ 1D 03 00 1E 07 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -60,7 +47,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F D8 00 00 40 00
+ FC 01 04 2F F8 DC 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8610-mtp.dts
rename to arch/arm/boot/dts/msm8610-mtp.dtsi
index 9cc9e18..349c8f7 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -10,19 +10,6 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8610.dtsi"
-/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
-/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
-
-/ {
- model = "Qualcomm MSM 8610 MTP";
- compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
- qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
- <163 8 0>, <164 8 0>, <166 8 0>;
-};
-
&soc {
serial@f991e000 {
status = "ok";
@@ -52,7 +39,7 @@
/* Object 6, Instance = 0 */
00 00 00 00 00 00
/* Object 38, Instance = 0 */
- 1D 02 00 0A 06 0D 00 00
+ 1D 03 00 1E 07 0D 00 00
/* Object 7, Instance = 0 */
20 08 32
/* Object 8, Instance = 0 */
@@ -60,7 +47,7 @@
/* Object 9, Instance = 0 */
83 00 00 13 0B 00 20 32 01 03
00 32 05 30 0A 05 0A 00 70 03
- FC 01 00 36 2F D8 00 00 40 00
+ FC 01 04 2F F8 DC 00 00 40 00
00 0A 00 00 02
/* Object 18, Instance = 0 */
00 00
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index b1ec4fe..8d12017 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -24,7 +24,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -41,7 +41,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -58,7 +58,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 06 26 30 0f];
};
@@ -75,7 +75,7 @@
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
- qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 07 60 3b 76 76
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3b 76 76
0b 94 5b 80 10 26 30 0f];
};
@@ -179,9 +179,9 @@
<0xff 176>, /* o_wcss_apss_smsm_irq */
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
- <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 179>, /* o_wcss_apss_asic_intr */
<0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
- <0xff 161>, /* lpass_irq_out_spare[4] /
+ <0xff 161>, /* lpass_irq_out_spare[4] */
<0xff 162>, /* lpass_irq_out_spare[5]*/
<0xff 234>, /* lpass_irq_out_spare[6]*/
<0xff 235>, /* lpass_irq_out_spare[7]*/
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index d1bf471..49068b5 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -26,8 +26,6 @@
* };
*/
-/include/ "msm8610.dtsi"
-
&soc {
i2c@f9923000{
focaltech@38{
@@ -37,6 +35,7 @@
interrupts = <1 0x2>;
vdd-supply = <&pm8110_l19>;
vcc_i2c-supply = <&pm8110_l14>;
+ focaltech,name = "ft6x06";
focaltech,family-id = <0x06>;
focaltech,reset-gpio = <&msmgpio 0 0x00>;
focaltech,irq-gpio = <&msmgpio 1 0x00>;
@@ -45,6 +44,17 @@
focaltech,button-map= <139 102 158>;
focaltech,no-force-update;
focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay-ms = <20>;
+ focaltech,soft-reset-delay-ms = <150>;
+ focaltech,num-max-touches = <2>;
+ focaltech,fw-name = "ft_8610_qrd_fw.bin";
+ focaltech,fw-delay-aa-ms = <100>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x08>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
};
};
diff --git a/arch/arm/boot/dts/msm8610-v1-cdp.dts b/arch/arm/boot/dts/msm8610-v1-cdp.dts
new file mode 100644
index 0000000..ba0851f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v1.dtsi"
+/include/ "msm8610-cdp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
+ qcom,msm-id = <147 1 0>, <165 1 0>, <161 1 0>, <162 1 0>,
+ <163 1 0>, <164 1 0>, <166 1 0>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v1-mtp.dts b/arch/arm/boot/dts/msm8610-v1-mtp.dts
new file mode 100644
index 0000000..010903f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v1.dtsi"
+/include/ "msm8610-mtp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
+ qcom,msm-id = <147 8 0>, <165 8 0>, <161 8 0>, <162 8 0>,
+ <163 8 0>, <164 8 0>, <166 8 0>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
similarity index 97%
rename from arch/arm/boot/dts/msm8610-qrd-skuaa.dts
rename to arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
index e220e6f..5abe5c0 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuaa.dts
@@ -12,6 +12,7 @@
/dts-v1/;
+/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd.dtsi"
/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
/include/ "msm8610-qrd-camera-sensor.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
similarity index 98%
rename from arch/arm/boot/dts/msm8610-qrd-skuab.dts
rename to arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
index 2948dec..b4559ff 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab.dts
@@ -12,6 +12,7 @@
/dts-v1/;
+/include/ "msm8610-v1.dtsi"
/include/ "msm8610-qrd.dtsi"
/include/ "dsi-v2-panel-otm8018b-fwvga-video.dtsi"
/include/ "msm8612-qrd-camera-sensor.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-v1.dtsi b/arch/arm/boot/dts/msm8610-v1.dtsi
new file mode 100644
index 0000000..5052b96
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8610.dtsi file.
+ */
+
+/include/ "msm8610.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-v2-cdp.dts b/arch/arm/boot/dts/msm8610-v2-cdp.dts
new file mode 100644
index 0000000..51ef7a2
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-cdp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 CDP";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
+ qcom,msm-id = <147 1 0x10001>, <165 1 0x10001>, <161 1 0x10001>, <162 1 0x10001>,
+ <163 1 0x10001>, <164 1 0x10001>, <166 1 0x10001>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v2-mtp.dts b/arch/arm/boot/dts/msm8610-v2-mtp.dts
new file mode 100644
index 0000000..e1c9bb8
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-mtp.dtsi"
+/include/ "dsi-v2-panel-truly-wvga-video.dtsi"
+/include/ "msm8610-camera-sensor-cdp-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 MTP";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
+ qcom,msm-id = <147 8 0x10001>, <165 8 0x10001>, <161 8 0x10001>, <162 8 0x10001>,
+ <163 8 0x10001>, <164 8 0x10001>, <166 8 0x10001>;
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
new file mode 100644
index 0000000..6ad8cb5
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuaa.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-qrd.dtsi"
+/include/ "dsi-v2-panel-hx8379a-wvga-video.dtsi"
+/include/ "msm8610-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 1>, <11 0>;
+ qcom,msm-id = <147 0x10001>, <165 0x10001>, <161 0x10001>, <162 0x10001>,
+ <163 0x10001>, <164 0x10001>, <166 0x10001>;
+};
+
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
new file mode 100644
index 0000000..225be06
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "msm8610-v2.dtsi"
+/include/ "msm8610-qrd.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 QRD";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <11 3>;
+ qcom,msm-id = <147 0x10001>, <165 0x10001>, <161 0x10001>, <162 0x10001>,
+ <163 0x10001>, <164 0x10001>, <166 0x10001>;
+};
diff --git a/arch/arm/boot/dts/msm8610-v2.dtsi b/arch/arm/boot/dts/msm8610-v2.dtsi
new file mode 100644
index 0000000..5052b96
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2.dtsi
@@ -0,0 +1,19 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8610.dtsi file.
+ */
+
+/include/ "msm8610.dtsi"
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index c6104bf..efa68b9 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -472,6 +472,7 @@
qcom,i2c-src-freq = <19200000>;
qcom,sda-gpio = <&msmgpio 2 0>;
qcom,scl-gpio = <&msmgpio 3 0>;
+ qcom,master-id = <86>;
};
i2c_cdc: i2c@f9927000 { /* BLSP1 QUP5 */
@@ -484,6 +485,8 @@
interrupt-names = "qup_err_intr";
interrupts = <0 99 0>;
qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <19200000>;
+ qcom,master-id = <86>;
};
i2c: i2c@f9928000 { /* BLSP1 QUP6 */
@@ -499,6 +502,7 @@
qcom,i2c-src-freq = <19200000>;
qcom,sda-gpio = <&msmgpio 16 0>;
qcom,scl-gpio = <&msmgpio 17 0>;
+ qcom,master-id = <86>;
};
i2c@f9925000 { /* BLSP-1 QUP-3 */
@@ -511,6 +515,10 @@
interrupt-names = "qup_err_intr";
interrupts = <0 97 0>;
qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <19200000>;
+ qcom,sda-gpio = <&msmgpio 10 0>;
+ qcom,scl-gpio = <&msmgpio 11 0>;
+ qcom,master-id = <86>;
};
spi_4: spi@f9926000 { /* BLSP1 QUP4 */
@@ -929,10 +937,16 @@
};
&gdsc_vfe {
+ qcom,clock-names = "core_clk", "iface_clk", "bus_clk";
+ qcom,skip-logic-collapse;
+ qcom,retain-periph;
+ qcom,retain-mem;
status = "ok";
};
&gdsc_oxili_cx {
+ qcom,clock-names = "core_clk", "iface_clk", "mem_clk";
+ qcom,skip-logic-collapse;
status = "ok";
};
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/boot/dts/msm8974-ion.dtsi b/arch/arm/boot/dts/msm8974-ion.dtsi
index 63f6d59..455ed2d 100644
--- a/arch/arm/boot/dts/msm8974-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974-ion.dtsi
@@ -55,5 +55,12 @@
qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
qcom,memory-reservation-size = <0x614000>;
};
+
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x05d00000 0x1e00000>;
+ };
};
};
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 7362b64..dc41149 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -217,7 +217,7 @@
<0xff 176>, /* o_wcss_apss_smsm_irq */
<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
- <0xff 179>, /* o_wcss_apss_asic_intr
+ <0xff 179>, /* o_wcss_apss_asic_intr */
<0xff 188>, /* lpass_irq_out_apcs(0) */
<0xff 189>, /* lpass_irq_out_apcs(1) */
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 6fb68d1..1845e17 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -24,6 +24,19 @@
sdhc2 = &sdhc_2; /* SDC2 SD card slot */
sdhc3 = &sdhc_3; /* SDC3 SDIO slot */
sdhc4 = &sdhc_4; /* SDC4 SDIO slot */
+
+ /* smdtty devices */
+ smd1 = &smdtty_apps_fm;
+ smd2 = &smdtty_apps_riva_bt_acl;
+ smd3 = &smdtty_apps_riva_bt_cmd;
+ smd4 = &smdtty_mbalbridge;
+ smd5 = &smdtty_apps_riva_ant_cmd;
+ smd6 = &smdtty_apps_riva_ant_data;
+ smd7 = &smdtty_data1;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd27 = &smdtty_gps_nmea;
+ smd36 = &smdtty_loopback;
};
cpus {
@@ -1544,7 +1557,7 @@
memory_hole: qcom,msm-mem-hole {
compatible = "qcom,msm-mem-hole";
- qcom,memblock-remove = <0x7b00000 0x8400000>; /* Address and Size of Hole */
+ qcom,memblock-remove = <0x5d00000 0xa200000>; /* Address and Size of Hole */
};
uart7: uart@f995d000 { /*BLSP #2, UART #7 */
@@ -1672,6 +1685,66 @@
compatible = "qcom,l2-pmu";
interrupts = <0 1 0>;
};
+
+ qcom,smdtty {
+ compatible = "qcom,smdtty";
+
+ smdtty_apps_fm: qcom,smdtty-apps-fm {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_FM";
+ };
+
+ smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_ACL";
+ };
+
+ smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_CMD";
+ };
+
+ smdtty_mbalbridge: qcom,smdtty-mbalbridge {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "MBALBRIDGE";
+ };
+
+ smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD";
+ };
+
+ smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA";
+ };
+
+ smdtty_data1: qcom,smdtty-data1 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA1";
+ };
+
+ smdtty_data11: qcom,smdtty-data11 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA11";
+ };
+
+ smdtty_data21: qcom,smdtty-data21 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA21";
+ };
+
+ smdtty_gps_nmea: smdtty-gpsnmea {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "GPSNMEA";
+ };
+
+ smdtty_loopback: smdtty-loopback {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "LOOPBACK";
+ qcom,smdtty-dev-name = "LOOPBACK_TTY";
+ };
+ };
};
&gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
index 862dbee..237c9f9 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
@@ -123,3 +123,12 @@
qcom,thermal-node;
};
};
+
+&sdhc_1 {
+ reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000 400000000>;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,pad-pull-on = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
+ qcom,pad-pull-off = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
index 250afd2..debf7fb 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
@@ -62,10 +62,6 @@
vbus_dwc3-supply = <&pm8941_mvs1>;
};
- qcom,mdss_dsi_toshiba_720p_video {
- qcom,rst-gpio = <&pma8084_gpios 20 0>;
- };
-
gpio_keys {
camera_snapshot {
gpios = <&pma8084_gpios 3 0x1>;
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-ac.dtsi
index 3ecde60..4c55169 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac.dtsi
@@ -52,6 +52,7 @@
vdd-supply = <&pma8084_l22>;
vddio-supply = <&pma8084_l12>;
vdda-supply = <&pma8084_l2>;
+ qcom,platform-reset-gpio = <&pma8084_gpios 20 0>;
};
qcom,mdss_dsi@fd922e00 {
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
new file mode 100644
index 0000000..31bff88
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -0,0 +1,340 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+ qcom,spm@f9089000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9089000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f9099000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9099000 0x1000>;
+ qcom,core-id = <1>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f90a9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90a9000 0x1000>;
+ qcom,core-id = <2>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f90b9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf90b9000 0x1000>;
+ qcom,core-id = <3>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x01>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-ret = [42 1b 00 d8 5B 03 d8 5b 0b 00 42 1b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ qcom,saw2-spm-cmd-pc = [00 20 80 10 E8 5B 03 3B E8 5B 82 10 0B
+ 30 06 26 30 0F];
+ };
+
+ qcom,spm@f9012000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xf9012000 0x1000>;
+ qcom,core-id = <0xffff>; /* L2/APCS SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-avs-ctl = <0>;
+ qcom,saw2-avs-hysteresis = <0>;
+ qcom,saw2-avs-limit = <0>;
+ qcom,saw2-avs-dly= <0>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-pmic-data0 = <0x02030080>;
+ qcom,saw2-pmic-data1 = <0x00030000>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,pfm-port = <0x2>;
+ qcom,saw2-spm-cmd-ret = [1f 00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 32 42 07 44 50 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+ 50 02 32 50 0f];
+ };
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_retention";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,lpm-level@0 {
+ reg = <0x0>;
+ qcom,mode = "wfi";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <1>;
+ qcom,ss-power = <715>;
+ qcom,energy-overhead = <17700>;
+ qcom,time-overhead = <2>;
+ };
+
+ qcom,lpm-level@1 {
+ reg = <0x1>;
+ qcom,mode = "retention";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <35>;
+ qcom,ss-power = <542>;
+ qcom,energy-overhead = <34920>;
+ qcom,time-overhead = <40>;
+ };
+
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = "standalone_pc";
+ qcom,l2 = "l2_cache_retention";
+ qcom,latency-us = <300>;
+ qcom,ss-power = <476>;
+ qcom,energy-overhead = <225300>;
+ qcom,time-overhead = <350>;
+ };
+
+ qcom,lpm-level@3 {
+ reg = <0x3>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_gdhs";
+ qcom,gpio-detectable;
+ qcom,latency-us = <20000>;
+ qcom,ss-power = <163>;
+ qcom,energy-overhead = <1577736>;
+ qcom,time-overhead = <5067>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = "pc";
+ qcom,l2 = "l2_cache_pc";
+ qcom,latency-us = <30000>;
+ qcom,ss-power = <83>;
+ qcom,energy-overhead = <2274420>;
+ qcom,time-overhead = <6605>;
+ };
+ };
+
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = "tz";
+ };
+
+ qcom,mpm@fc4281d0 {
+ compatible = "qcom,mpm-v2";
+ reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xf9011008 0x4>; /* MSM_APCS_GCC_BASE 4K */
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+ <47 165>, /* usb30_hs_phy_irq */
+ <50 172>, /* usb1_hs_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 56>, /* modem_watchdog */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
+ <0xff 70>, /* iommu_pmon_nonsecure_irq */
+ <0xff 97>, /* iommu_nonsecure_irq */
+ <0xff 105>, /* iommu_pmon_nonsecure_irq */
+ <0xff 173>, /* o_wcss_apss_smd_hi */
+ <0xff 174>, /* o_wcss_apss_smd_med */
+ <0xff 175>, /* o_wcss_apss_smd_low */
+ <0xff 176>, /* o_wcss_apss_smsm_irq */
+ <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+ <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+ <0xff 179>, /* o_wcss_apss_asic_intr */
+
+ <0xff 181>, /* wcnss watchdog */
+ <0xff 188>, /* lpass_irq_out_apcs(0) */
+ <0xff 189>, /* lpass_irq_out_apcs(1) */
+ <0xff 190>, /* lpass_irq_out_apcs(2) */
+ <0xff 191>, /* lpass_irq_out_apcs(3) */
+ <0xff 192>, /* lpass_irq_out_apcs(4) */
+ <0xff 193>, /* lpass_irq_out_apcs(5) */
+ <0xff 194>, /* lpass_irq_out_apcs(6) */
+ <0xff 195>, /* lpass_irq_out_apcs(7) */
+ <0xff 196>, /* lpass_irq_out_apcs(8) */
+ <0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 211>, /* usb_dwc3_otg */
+ <0xff 240>; /* summary_irq_kpss */
+
+ qcom,gpio-parent = <&msmgpio>;
+ qcom,gpio-map = <3 102>,
+ <4 1 >,
+ <5 5 >,
+ <6 9 >,
+ <7 18>,
+ <8 20>,
+ <9 24>,
+ <10 27>,
+ <11 28>,
+ <12 34>,
+ <13 35>,
+ <14 37>,
+ <15 42>,
+ <16 44>,
+ <17 46>,
+ <18 50>,
+ <19 54>,
+ <20 59>,
+ <21 61>,
+ <22 62>,
+ <23 64>,
+ <24 65>,
+ <25 66>,
+ <26 67>,
+ <27 68>,
+ <28 71>,
+ <29 72>,
+ <30 73>,
+ <31 74>,
+ <32 75>,
+ <33 77>,
+ <34 79>,
+ <35 80>,
+ <36 82>,
+ <37 86>,
+ <38 92>,
+ <39 93>,
+ <40 95>,
+ <41 144>;
+ };
+
+ qcom,pm-8x60@fe805664 {
+ compatible = "qcom,pm-8x60";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg = <0xfe805664 0x40>;
+ qcom,pc-mode = "tz_l2_int";
+ qcom,use-sync-timer;
+ qcom,cpus-as-clocks;
+
+ qcom,pm-snoc-client {
+ compatible = "qcom,pm-snoc-client";
+ qcom,msm-bus,name = "ocimem_snoc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,vectors-KBps =
+ <54 585 0 0>,
+ <54 585 0 800000>;
+ };
+ };
+
+ qcom,cpu-sleep-status@f9088008{
+ compatible = "qcom,cpu-sleep-status";
+ reg = <0xf9088008 0x100>;
+ qcom,cpu-alias-addr = <0x10000>;
+ qcom,sleep-status-mask= <0x80000>;
+ };
+
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
+ qcom,rpm-stats@fc19dba0 {
+ compatible = "qcom,rpm-stats";
+ reg = <0xfc19dba0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+
+ qcom,rpm-rbcpr-stats@fc000000 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0xfc000000 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index e7c6a48..7914a6a 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -19,7 +19,7 @@
/include/ "msm8974.dtsi"
/include/ "msm8974-v2-iommu.dtsi"
/include/ "msm8974-v2-iommu-domains.dtsi"
-/include/ "msm8974-v2-pm.dtsi"
+/include/ "msm8974pro-pm.dtsi"
/include/ "msm8974pro-ion.dtsi"
&soc {
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/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index b8dc0d7b..8591812 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -233,6 +233,7 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
+# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index dd4274a..20938d5 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -232,6 +232,7 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
+# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 6078901..12ffa66 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -75,7 +75,7 @@
$(obj)/smd_rpc_sym.c: $(src)/smd_rpc_sym $(src)/mkrpcsym.pl
$(call if_changed,mkrpcsym)
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o smem.o
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o smem.o smd_init_dt.o smd_init_plat.o
obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_gpio.o
obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_gpio_test.o smp2p_spinlock_test.o
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 01c7a2a..910264e 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -134,12 +134,16 @@
# MSM8610
zreladdr-$(CONFIG_ARCH_MSM8610) := 0x00008000
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-cdp.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-mtp.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-rumi.dtb
dtb-$(CONFIG_ARCH_MSM8610) += msm8610-sim.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuaa.dtb
- dtb-$(CONFIG_ARCH_MSM8610) += msm8610-qrd-skuab.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-qrd-skuaa.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v1-qrd-skuab.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-qrd-skuaa.dtb
+ dtb-$(CONFIG_ARCH_MSM8610) += msm8610-v2-qrd-skuab.dtb
# MSMSAMARIUM
zreladdr-$(CONFIG_ARCH_MSMSAMARIUM) := 0x00008000
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 4ea5654..ebb90af 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -57,7 +57,7 @@
static struct gpiomux_setting synaptics_reset_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_6MA,
+ .drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
};
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/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 39916ef..f8c206b 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -240,6 +240,7 @@
#define GFX3D_CMD_RCGR 0x4000
#define OXILI_GFX3D_CBCR 0x4028
#define OXILI_GFX3D_BCR 0x4030
+#define GMEM_GFX3D_BCR 0x4040
#define OXILI_AHB_BCR 0x4044
#define OXILI_AHB_CBCR 0x403C
#define AHB_CMD_RCGR 0x5000
@@ -2147,6 +2148,7 @@
static struct branch_clk csi_vfe_clk = {
.cbcr_reg = CSI_VFE_CBCR,
+ .bcr_reg = CSI_VFE_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2217,6 +2219,7 @@
static struct branch_clk gmem_gfx3d_clk = {
.cbcr_reg = GMEM_GFX3D_CBCR,
+ .bcr_reg = GMEM_GFX3D_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2358,6 +2361,7 @@
static struct branch_clk oxili_ahb_clk = {
.cbcr_reg = OXILI_AHB_CBCR,
+ .bcr_reg = OXILI_AHB_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2369,6 +2373,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
+ .bcr_reg = OXILI_GFX3D_BCR,
.has_sibling = 0,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2381,6 +2386,7 @@
static struct branch_clk vfe_clk = {
.cbcr_reg = VFE_CBCR,
+ .bcr_reg = VFE_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2393,6 +2399,7 @@
static struct branch_clk vfe_ahb_clk = {
.cbcr_reg = VFE_AHB_CBCR,
+ .bcr_reg = VFE_AHB_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2404,6 +2411,7 @@
static struct branch_clk vfe_axi_clk = {
.cbcr_reg = VFE_AXI_CBCR,
+ .bcr_reg = VFE_AXI_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
/* FIXME: Remove this once simulation is fixed. */
@@ -3133,6 +3141,14 @@
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "fd404000.qcom,qcrypto"),
+
+ /* GDSC clocks */
+ CLK_LOOKUP("core_clk", vfe_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("iface_clk", vfe_ahb_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("bus_clk", vfe_axi_clk.c, "fd8c36a4.qcom,gdsc"),
+ CLK_LOOKUP("core_clk", oxili_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
+ CLK_LOOKUP("iface_clk", oxili_ahb_clk.c, "fd8c4034.qcom,gdsc"),
+ CLK_LOOKUP("mem_clk", gmem_gfx3d_clk.c, "fd8c4034.qcom,gdsc"),
};
static struct clk_lookup msm_clocks_8610_rumi[] = {
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index b7852fe..4488869 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -549,19 +549,21 @@
u32 cbcr_val;
unsigned long irq_flags;
struct branch_clk *branch = to_branch_clk(c);
- int ret = 0;
+ int delay_us = 0, ret = 0;
spin_lock_irqsave(&local_clock_reg_lock, irq_flags);
cbcr_val = readl_relaxed(CBCR_REG(branch));
switch (flags) {
case CLKFLAG_RETAIN_PERIPH:
cbcr_val |= BIT(13);
+ delay_us = 1;
break;
case CLKFLAG_NORETAIN_PERIPH:
cbcr_val &= ~BIT(13);
break;
case CLKFLAG_RETAIN_MEM:
cbcr_val |= BIT(14);
+ delay_us = 1;
break;
case CLKFLAG_NORETAIN_MEM:
cbcr_val &= ~BIT(14);
@@ -570,17 +572,11 @@
ret = -EINVAL;
}
writel_relaxed(cbcr_val, CBCR_REG(branch));
- /*
- * 8974v2.2 has a requirement that writes to set bits 13 and 14 are
- * separated by at least 2 bus cycles. Cover one of these cycles by
- * performing an extra write here. The other cycle is covered by the
- * read-modify-write design of this function.
- */
- writel_relaxed(cbcr_val, CBCR_REG(branch));
- spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
-
- /* Make sure write is issued before returning. */
+ /* Make sure power is enabled before returning. */
mb();
+ udelay(delay_us);
+
+ spin_unlock_irqrestore(&local_clock_reg_lock, irq_flags);
return ret;
}
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 774548c..ea4865d 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -111,6 +111,13 @@
uint32_t regval;
int i, ret = 0;
+ for (i = sc->clock_count-1; i >= 0; i--) {
+ if (sc->toggle_mem)
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+ if (sc->toggle_periph)
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+ }
+
if (sc->toggle_logic) {
regval = readl_relaxed(sc->gdscr);
regval |= SW_COLLAPSE_MASK;
@@ -123,18 +130,11 @@
dev_err(&rdev->dev, "%s disable timed out\n",
sc->rdesc.name);
} else {
- for (i = 0; i < sc->clock_count; i++)
+ for (i = sc->clock_count-1; i >= 0; i--)
clk_reset(sc->clocks[i], CLK_RESET_ASSERT);
sc->resets_asserted = true;
}
- for (i = 0; i < sc->clock_count; i++) {
- if (sc->toggle_mem)
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
- if (sc->toggle_periph)
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
- }
-
return ret;
}
@@ -225,20 +225,9 @@
retain_mem = of_property_read_bool(pdev->dev.of_node,
"qcom,retain-mem");
+ sc->toggle_mem = !retain_mem;
retain_periph = of_property_read_bool(pdev->dev.of_node,
"qcom,retain-periph");
- for (i = 0; i < sc->clock_count; i++) {
- if (retain_mem || (regval & PWR_ON_MASK))
- clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
- else
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
-
- if (retain_periph || (regval & PWR_ON_MASK))
- clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
- else
- clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
- }
- sc->toggle_mem = !retain_mem;
sc->toggle_periph = !retain_periph;
sc->toggle_logic = !of_property_read_bool(pdev->dev.of_node,
"qcom,skip-logic-collapse");
@@ -255,6 +244,18 @@
}
}
+ for (i = 0; i < sc->clock_count; i++) {
+ if (retain_mem || (regval & PWR_ON_MASK))
+ clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_MEM);
+
+ if (retain_periph || (regval & PWR_ON_MASK))
+ clk_set_flags(sc->clocks[i], CLKFLAG_RETAIN_PERIPH);
+ else
+ clk_set_flags(sc->clocks[i], CLKFLAG_NORETAIN_PERIPH);
+ }
+
sc->rdev = regulator_register(&sc->rdesc, &pdev->dev, init_data, sc,
pdev->dev.of_node);
if (IS_ERR(sc->rdev)) {
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index bfcce73..45be31f 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -188,6 +188,7 @@
TLMM_PULL_SDC1_CLK,
TLMM_PULL_SDC1_CMD,
TLMM_PULL_SDC1_DATA,
+ TLMM_PULL_SDC1_RCLK,
};
#if defined(CONFIG_GPIO_MSM_V2) || defined(CONFIG_GPIO_MSM_V3)
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 2653ae4..cd07662 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -316,6 +316,15 @@
*/
int __init msm_smd_init(void);
+/**
+ * smd_remote_ss_to_edge() - return edge type from remote ss type
+ * @name: remote subsystem name
+ *
+ * Returns the edge type connected between the local subsystem(APPS)
+ * and remote subsystem @name.
+ */
+int smd_remote_ss_to_edge(const char *name);
+
#else
static inline int smd_open(const char *name, smd_channel_t **ch, void *priv,
@@ -447,6 +456,11 @@
{
return 0;
}
+
+static inline int smd_remote_ss_to_edge(const char *name)
+{
+ return -EINVAL;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_smem.h b/arch/arm/mach-msm/include/mach/msm_smem.h
index a121791..5556db9 100644
--- a/arch/arm/mach-msm/include/mach/msm_smem.h
+++ b/arch/arm/mach-msm/include/mach/msm_smem.h
@@ -27,7 +27,6 @@
};
#define SMEM_NUM_SMD_STREAM_CHANNELS 64
-#define SMEM_NUM_SMD_BLOCK_CHANNELS 64
enum {
/* fixed items */
@@ -87,13 +86,13 @@
SMEM_ID_VENDOR1,
SMEM_ID_VENDOR2,
SMEM_HW_SW_BUILD_ID,
- SMEM_SMD_BLOCK_PORT_BASE_ID,
- SMEM_SMD_BLOCK_PORT_PROC0_HEAP = SMEM_SMD_BLOCK_PORT_BASE_ID +
- SMEM_NUM_SMD_BLOCK_CHANNELS,
- SMEM_SMD_BLOCK_PORT_PROC1_HEAP = SMEM_SMD_BLOCK_PORT_PROC0_HEAP +
- SMEM_NUM_SMD_BLOCK_CHANNELS,
- SMEM_I2C_MUTEX = SMEM_SMD_BLOCK_PORT_PROC1_HEAP +
- SMEM_NUM_SMD_BLOCK_CHANNELS,
+ SMEM_SMD_BASE_ID_2,
+ SMEM_SMD_FIFO_BASE_ID_2 = SMEM_SMD_BASE_ID_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_CHANNEL_ALLOC_TBL_2 = SMEM_SMD_FIFO_BASE_ID_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_I2C_MUTEX = SMEM_CHANNEL_ALLOC_TBL_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
SMEM_SCLK_CONVERSION,
SMEM_SMD_SMSM_INTR_MUX,
SMEM_SMSM_CPU_INTR_MASK,
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 863a2d7..6fe945c 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1350,7 +1350,7 @@
struct msm_ipc_router_xprt_info *xprt_info)
{
int i;
- struct msm_ipc_routing_table_entry *rt_entry;
+ struct msm_ipc_routing_table_entry *rt_entry, *tmp_rt_entry;
if (!xprt_info) {
pr_err("%s: Invalid xprt_info\n", __func__);
@@ -1360,7 +1360,8 @@
down_write(&server_list_lock_lha2);
down_write(&routing_table_lock_lha3);
for (i = 0; i < RT_HASH_SIZE; i++) {
- list_for_each_entry(rt_entry, &routing_table[i], list) {
+ list_for_each_entry_safe(rt_entry, tmp_rt_entry,
+ &routing_table[i], list) {
down_write(&rt_entry->lock_lha4);
if (rt_entry->xprt_info != xprt_info) {
up_write(&rt_entry->lock_lha4);
@@ -1369,6 +1370,8 @@
cleanup_rmt_ports(xprt_info, rt_entry);
rt_entry->xprt_info = NULL;
up_write(&rt_entry->lock_lha4);
+ list_del(&rt_entry->list);
+ kfree(rt_entry);
}
}
up_write(&routing_table_lock_lha3);
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
index 86e8963..a5593bf 100644
--- a/arch/arm/mach-msm/msm_cache_dump.c
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -23,15 +23,16 @@
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
#include <mach/scm.h>
#include <mach/msm_cache_dump.h>
-#include <mach/memory.h>
#include <mach/msm_iomap.h>
#include <mach/msm_memory_dump.h>
#define L2_DUMP_OFFSET 0x14
-static unsigned long msm_cache_dump_addr;
+static dma_addr_t msm_cache_dump_addr;
+static void *msm_cache_dump_vaddr;
/*
* These should not actually be dereferenced. There's no
@@ -76,7 +77,6 @@
unsigned long buf;
unsigned long size;
} l1_cache_data;
- void *temp;
u32 l1_size, l2_size;
unsigned long total_size;
@@ -102,19 +102,20 @@
};
total_size = l1_size + l2_size;
- msm_cache_dump_addr = allocate_contiguous_ebi_nomap(total_size, SZ_4K);
+ msm_cache_dump_vaddr = (void *) dma_alloc_coherent(&pdev->dev,
+ total_size, &msm_cache_dump_addr,
+ GFP_KERNEL);
- if (!msm_cache_dump_addr) {
+ if (!msm_cache_dump_vaddr) {
pr_err("%s: Could not get memory for cache dumping\n",
__func__);
return -ENOMEM;
}
- temp = ioremap(msm_cache_dump_addr, total_size);
- memset(temp, 0xFF, total_size);
+ memset(msm_cache_dump_vaddr, 0xFF, total_size);
/* Clean caches before sending buffer to TZ */
- clean_caches((unsigned long) temp, total_size, msm_cache_dump_addr);
- iounmap(temp);
+ clean_caches((unsigned long) msm_cache_dump_vaddr, total_size,
+ msm_cache_dump_addr);
l1_cache_data.buf = msm_cache_dump_addr;
l1_cache_data.size = l1_size;
@@ -126,8 +127,9 @@
pr_err("%s: could not register L1 buffer ret = %d.\n",
__func__, ret);
- l1_dump = (struct l1_cache_dump *)msm_cache_dump_addr;
- l2_dump = (struct l2_cache_dump *)(msm_cache_dump_addr + l1_size);
+ l1_dump = (struct l1_cache_dump *)(uint32_t)msm_cache_dump_addr;
+ l2_dump = (struct l2_cache_dump *)(uint32_t)(msm_cache_dump_addr
+ + l1_size);
#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
l1_cache_data.buf = msm_cache_dump_addr + l1_size;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index e148868..deb1cc7 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -55,24 +55,6 @@
#include "modem_notifier.h"
#include "smem_private.h"
-#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
- || defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
- || defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_APQ8064)
-#define CONFIG_QDSP6 1
-#endif
-
-#if defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) \
- || defined(CONFIG_ARCH_APQ8064)
-#define CONFIG_DSPS 1
-#endif
-
-#if defined(CONFIG_ARCH_MSM8960) \
- || defined(CONFIG_ARCH_APQ8064)
-#define CONFIG_WCNSS 1
-#define CONFIG_DSPS_SMSM 1
-#endif
-
-#define MODULE_NAME "msm_smd"
#define SMD_VERSION 0x00020000
#define SMSM_SNAPSHOT_CNT 64
#define SMSM_SNAPSHOT_SIZE ((SMSM_NUM_ENTRIES + 1) * 4)
@@ -86,14 +68,6 @@
#define LEGACY_MODEM_SMSM_MASK (SMSM_RESET | SMSM_INIT | SMSM_SMDINIT \
| SMSM_RUN | SMSM_SYSTEM_DOWNLOAD)
-enum {
- MSM_SMD_DEBUG = 1U << 0,
- MSM_SMSM_DEBUG = 1U << 1,
- MSM_SMD_INFO = 1U << 2,
- MSM_SMSM_INFO = 1U << 3,
- MSM_SMx_POWER_INFO = 1U << 4,
-};
-
struct smsm_shared_info {
uint32_t *state;
uint32_t *intr_mask;
@@ -127,32 +101,14 @@
uint32_t intr_mask_clear;
};
-struct interrupt_config_item {
- /* must be initialized */
- irqreturn_t (*irq_handler)(int req, void *data);
- /* outgoing interrupt config (set from platform data) */
- uint32_t out_bit_pos;
- void __iomem *out_base;
- uint32_t out_offset;
- int irq_id;
-};
-
-struct interrupt_config {
- struct interrupt_config_item smd;
- struct interrupt_config_item smsm;
-};
-
-static irqreturn_t smd_modem_irq_handler(int irq, void *data);
-static irqreturn_t smsm_modem_irq_handler(int irq, void *data);
-static irqreturn_t smd_dsp_irq_handler(int irq, void *data);
-static irqreturn_t smsm_dsp_irq_handler(int irq, void *data);
-static irqreturn_t smd_dsps_irq_handler(int irq, void *data);
-static irqreturn_t smsm_dsps_irq_handler(int irq, void *data);
-static irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
-static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data);
-static irqreturn_t smd_rpm_irq_handler(int irq, void *data);
static irqreturn_t smsm_irq_handler(int irq, void *data);
+/*
+ * Interrupt configuration consists of static configuration for the supported
+ * processors that is done here along with interrupt configuration that is
+ * added by the separate initialization modules (device tree, platform data, or
+ * hard coded).
+ */
static struct interrupt_config private_intr_config[NUM_SMD_SUBSYSTEMS] = {
[SMD_MODEM] = {
.smd.irq_handler = smd_modem_irq_handler,
@@ -188,10 +144,10 @@
SMSM_APPS_DEM_I = 3,
};
-static int msm_smd_debug_mask = MSM_SMx_POWER_INFO;
+int msm_smd_debug_mask = MSM_SMx_POWER_INFO;
module_param_named(debug_mask, msm_smd_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
-static void *smd_log_ctx;
+void *smd_log_ctx;
#define NUM_LOG_PAGES 4
#define IPC_LOG(level, x...) do { \
@@ -248,124 +204,9 @@
static inline void smd_write_intr(unsigned int val,
const void __iomem *addr);
-
-#if defined(CONFIG_ARCH_MSM7X30)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1 << 0, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1 << 8, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1 << 5, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1 << 8, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM8X60)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1 << 3, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1 << 15, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1 << 4, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1 << 14, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT \
- (smd_write_intr(1, MSM_SIC_NON_SECURE_BASE + 0x4080))
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM9615)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1 << 3, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1 << 15, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1 << 4, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1 << 14, MSM_APCS_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_FSM9XXX)
-#define MSM_TRIG_A2Q6_SMD_INT \
- (smd_write_intr(1 << 10, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2Q6_SMSM_INT \
- (smd_write_intr(1 << 10, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1 << 0, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1 << 5, MSM_GCC_BASE + 0x8))
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7x25)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
-#define MSM_TRIG_A2Q6_SMD_INT
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
-#define MSM_TRIG_A2Q6_SMSM_INT
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#elif defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM7X27A)
-#define MSM_TRIG_A2M_SMD_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (0) * 4))
-#define MSM_TRIG_A2Q6_SMD_INT
-#define MSM_TRIG_A2M_SMSM_INT \
- (smd_write_intr(1, MSM_CSR_BASE + 0x400 + (5) * 4))
-#define MSM_TRIG_A2Q6_SMSM_INT
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#else /* use platform device / device tree configuration */
-#define MSM_TRIG_A2M_SMD_INT
-#define MSM_TRIG_A2Q6_SMD_INT
-#define MSM_TRIG_A2M_SMSM_INT
-#define MSM_TRIG_A2Q6_SMSM_INT
-#define MSM_TRIG_A2DSPS_SMD_INT
-#define MSM_TRIG_A2DSPS_SMSM_INT
-#define MSM_TRIG_A2WCNSS_SMD_INT
-#define MSM_TRIG_A2WCNSS_SMSM_INT
-#endif
-
-/*
- * stub out legacy macros if they are not being used so that the legacy
- * code compiles even though it is not used
- *
- * these definitions should not be used in active code and will cause
- * an early failure
- */
-#ifndef INT_A9_M2A_0
-#define INT_A9_M2A_0 -1
-#endif
-#ifndef INT_A9_M2A_5
-#define INT_A9_M2A_5 -1
-#endif
-#ifndef INT_ADSP_A11
-#define INT_ADSP_A11 -1
-#endif
#ifndef INT_ADSP_A11_SMSM
#define INT_ADSP_A11_SMSM -1
#endif
-#ifndef INT_DSPS_A11
-#define INT_DSPS_A11 -1
-#endif
-#ifndef INT_DSPS_A11_SMSM
-#define INT_DSPS_A11_SMSM -1
-#endif
-#ifndef INT_WCNSS_A11
-#define INT_WCNSS_A11 -1
-#endif
-#ifndef INT_WCNSS_A11_SMSM
-#define INT_WCNSS_A11_SMSM -1
-#endif
#define SMD_LOOPBACK_CID 100
@@ -421,9 +262,6 @@
++interrupt_stats[SMD_MODEM].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_MODEM].smd_out_hardcode_count;
- MSM_TRIG_A2M_SMD_INT;
}
}
@@ -437,9 +275,6 @@
++interrupt_stats[SMD_Q6].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_Q6].smd_out_hardcode_count;
- MSM_TRIG_A2Q6_SMD_INT;
}
}
@@ -453,9 +288,6 @@
++interrupt_stats[SMD_DSPS].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_DSPS].smd_out_hardcode_count;
- MSM_TRIG_A2DSPS_SMD_INT;
}
}
@@ -469,9 +301,6 @@
++interrupt_stats[SMD_WCNSS].smd_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_WCNSS].smd_out_hardcode_count;
- MSM_TRIG_A2WCNSS_SMD_INT;
}
}
@@ -492,13 +321,13 @@
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_MODEM].smsm;
+
+ SMx_POWER_INFO("SMSM Apps->%s", "MODEM");
+
if (intr->out_base) {
++interrupt_stats[SMD_MODEM].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_MODEM].smsm_out_hardcode_count;
- MSM_TRIG_A2M_SMSM_INT;
}
}
@@ -506,13 +335,13 @@
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_Q6].smsm;
+
+ SMx_POWER_INFO("SMSM Apps->%s", "ADSP");
+
if (intr->out_base) {
++interrupt_stats[SMD_Q6].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_Q6].smsm_out_hardcode_count;
- MSM_TRIG_A2Q6_SMSM_INT;
}
}
@@ -520,13 +349,13 @@
{
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_DSPS].smsm;
+
+ SMx_POWER_INFO("SMSM Apps->%s", "DSPS");
+
if (intr->out_base) {
++interrupt_stats[SMD_DSPS].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_DSPS].smsm_out_hardcode_count;
- MSM_TRIG_A2DSPS_SMSM_INT;
}
}
@@ -535,13 +364,12 @@
static const struct interrupt_config_item *intr
= &private_intr_config[SMD_WCNSS].smsm;
+ SMx_POWER_INFO("SMSM Apps->%s", "WCNSS");
+
if (intr->out_base) {
++interrupt_stats[SMD_WCNSS].smsm_out_config_count;
smd_write_intr(intr->out_bit_pos,
intr->out_base + intr->out_offset);
- } else {
- ++interrupt_stats[SMD_WCNSS].smsm_out_hardcode_count;
- MSM_TRIG_A2WCNSS_SMSM_INT;
}
}
@@ -694,13 +522,6 @@
struct smd_half_channel_word_access ch1;
};
-struct edge_to_pid {
- uint32_t local_pid;
- uint32_t remote_pid;
- char subsys_name[SMD_MAX_CH_NAME_LEN];
- bool initialized;
-};
-
/**
* Maps edge type to local and remote processor ID's.
*/
@@ -733,7 +554,7 @@
struct notifier_block nb;
};
-static int disable_smsm_reset_handshake;
+int disable_smsm_reset_handshake;
static struct platform_device loopback_tty_pdev = {.name = "LOOPBACK_TTY"};
static LIST_HEAD(smd_ch_closed_list);
@@ -745,14 +566,17 @@
static LIST_HEAD(smd_ch_list_wcnss);
static LIST_HEAD(smd_ch_list_rpm);
-static unsigned char smd_ch_allocated[64];
+/* 2 total supported tables of channels */
+static unsigned char smd_ch_allocated[SMEM_NUM_SMD_STREAM_CHANNELS * 2];
static struct work_struct probe_work;
static void finalize_channel_close_fn(struct work_struct *work);
static DECLARE_WORK(finalize_channel_close_work, finalize_channel_close_fn);
static struct workqueue_struct *channel_close_wq;
-static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm);
+#define PRI_ALLOC_TBL 1
+#define SEC_ALLOC_TBL 2
+static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm, int table_id);
static bool smd_edge_inited(int edge)
{
@@ -763,26 +587,33 @@
hence use a lock */
static DEFINE_MUTEX(smd_probe_lock);
-static void smd_channel_probe_worker(struct work_struct *work)
+/**
+ * scan_alloc_table - Scans a specified SMD channel allocation table in SMEM for
+ * newly created channels that need to be made locally
+ * visable
+ *
+ * @shared: pointer to the table array in SMEM
+ * @smd_ch_allocated: pointer to an array indicating already allocated channels
+ * table_id: identifier for this channel allocation table
+ *
+ * The smd_probe_lock must be locked by the calling function. Shared and
+ * smd_ch_allocated are assumed to be valid pointers.
+ */
+static void scan_alloc_table(struct smd_alloc_elm *shared,
+ char *smd_ch_allocated,
+ int table_id)
{
- struct smd_alloc_elm *shared;
unsigned n;
uint32_t type;
- shared = smem_find(ID_CH_ALLOC_TBL, sizeof(*shared) * 64);
-
- if (!shared) {
- pr_err("%s: allocation table not initialized\n", __func__);
- return;
- }
-
- mutex_lock(&smd_probe_lock);
- for (n = 0; n < 64; n++) {
+ for (n = 0; n < SMEM_NUM_SMD_STREAM_CHANNELS; n++) {
if (smd_ch_allocated[n])
continue;
- /* channel should be allocated only if APPS
- processor is involved */
+ /*
+ * channel should be allocated only if APPS processor is
+ * involved
+ */
type = SMD_CHANNEL_TYPE(shared[n].type);
if (type >= ARRAY_SIZE(edge_to_pids) ||
edge_to_pids[type].local_pid != SMD_APPS)
@@ -793,15 +624,52 @@
continue;
if (!smd_initialized && !smd_edge_inited(type)) {
- SMD_INFO("Probe skipping ch %d, edge not inited\n", n);
+ SMD_INFO(
+ "Probe skipping tbl %d, ch %d, edge not inited\n",
+ table_id, n);
continue;
}
- if (!smd_alloc_channel(&shared[n]))
+ if (!smd_alloc_channel(&shared[n], table_id))
smd_ch_allocated[n] = 1;
else
- SMD_INFO("Probe skipping ch %d, not allocated\n", n);
+ SMD_INFO(
+ "Probe skipping tbl %d, ch %d, not allocated\n",
+ table_id, n);
}
+}
+
+/**
+ * smd_channel_probe_worker() - Scan for newly created SMD channels and init
+ * local structures so the channels are visable to
+ * local clients
+ *
+ * @work: work_struct corresponding to an instance of this function running on
+ * a workqueue.
+ */
+static void smd_channel_probe_worker(struct work_struct *work)
+{
+ struct smd_alloc_elm *shared;
+
+ shared = smem_find(ID_CH_ALLOC_TBL,
+ sizeof(*shared) * SMEM_NUM_SMD_STREAM_CHANNELS);
+
+ if (!shared) {
+ pr_err("%s: allocation table not initialized\n", __func__);
+ return;
+ }
+
+ mutex_lock(&smd_probe_lock);
+
+ scan_alloc_table(shared, smd_ch_allocated, PRI_ALLOC_TBL);
+
+ shared = smem_find(SMEM_CHANNEL_ALLOC_TBL_2,
+ sizeof(*shared) * SMEM_NUM_SMD_STREAM_CHANNELS);
+ if (shared)
+ scan_alloc_table(shared,
+ &(smd_ch_allocated[SMEM_NUM_SMD_STREAM_CHANNELS]),
+ SEC_ALLOC_TBL);
+
mutex_unlock(&smd_probe_lock);
}
@@ -860,6 +728,29 @@
return ret;
}
+/**
+ * smd_remote_ss_to_edge() - return edge type from remote ss type
+ * @name: remote subsystem name
+ *
+ * Returns the edge type connected between the local subsystem(APPS)
+ * and remote subsystem @name.
+ */
+int smd_remote_ss_to_edge(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(edge_to_pids); ++i) {
+ if (edge_to_pids[i].subsys_name[0] != 0x0) {
+ if (!strncmp(edge_to_pids[i].subsys_name, name,
+ strlen(name)))
+ return i;
+ }
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(smd_remote_ss_to_edge);
+
/*
* Returns a pointer to the subsystem name or NULL if no
* subsystem name is available.
@@ -1384,7 +1275,7 @@
SMx_POWER_INFO("SMD Int %s->Apps\n", subsys);
}
-static irqreturn_t smd_modem_irq_handler(int irq, void *data)
+irqreturn_t smd_modem_irq_handler(int irq, void *data)
{
log_irq(SMD_APPS_MODEM);
++interrupt_stats[SMD_MODEM].smd_in_count;
@@ -1393,7 +1284,7 @@
return IRQ_HANDLED;
}
-static irqreturn_t smd_dsp_irq_handler(int irq, void *data)
+irqreturn_t smd_dsp_irq_handler(int irq, void *data)
{
log_irq(SMD_APPS_QDSP);
++interrupt_stats[SMD_Q6].smd_in_count;
@@ -1402,7 +1293,7 @@
return IRQ_HANDLED;
}
-static irqreturn_t smd_dsps_irq_handler(int irq, void *data)
+irqreturn_t smd_dsps_irq_handler(int irq, void *data)
{
log_irq(SMD_APPS_DSPS);
++interrupt_stats[SMD_DSPS].smd_in_count;
@@ -1411,7 +1302,7 @@
return IRQ_HANDLED;
}
-static irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
+irqreturn_t smd_wcnss_irq_handler(int irq, void *data)
{
log_irq(SMD_APPS_WCNSS);
++interrupt_stats[SMD_WCNSS].smd_in_count;
@@ -1420,7 +1311,7 @@
return IRQ_HANDLED;
}
-static irqreturn_t smd_rpm_irq_handler(int irq, void *data)
+irqreturn_t smd_rpm_irq_handler(int irq, void *data)
{
log_irq(SMD_APPS_RPM);
++interrupt_stats[SMD_RPM].smd_in_count;
@@ -1661,15 +1552,41 @@
}
#if (defined(CONFIG_MSM_SMD_PKG4) || defined(CONFIG_MSM_SMD_PKG3))
-static int smd_alloc_v2(struct smd_channel *ch)
+/**
+ * smd_alloc_v2() - Init local channel structure with information stored in SMEM
+ *
+ * @ch: pointer to the local structure for this channel
+ * @table_id: the id of the table this channel resides in. 1 = first table, 2 =
+ * second table, etc
+ * @returns: -EINVAL for failure; 0 for success
+ *
+ * ch must point to an allocated instance of struct smd_channel that is zeroed
+ * out, and has the n and type members already initialized to the correct values
+ */
+static int smd_alloc_v2(struct smd_channel *ch, int table_id)
{
void *buffer;
unsigned buffer_sz;
+ unsigned base_id;
+ unsigned fifo_id;
+
+ switch (table_id) {
+ case PRI_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID;
+ fifo_id = SMEM_SMD_FIFO_BASE_ID;
+ break;
+ case SEC_ALLOC_TBL:
+ base_id = SMEM_SMD_BASE_ID_2;
+ fifo_id = SMEM_SMD_FIFO_BASE_ID_2;
+ break;
+ default:
+ SMD_INFO("Invalid table_id:%d passed to smd_alloc\n", table_id);
+ return -EINVAL;
+ }
if (is_word_access_ch(ch->type)) {
struct smd_shared_v2_word_access *shared2;
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n,
- sizeof(*shared2));
+ shared2 = smem_alloc(base_id + ch->n, sizeof(*shared2));
if (!shared2) {
SMD_INFO("smem_alloc failed ch=%d\n", ch->n);
return -EINVAL;
@@ -1678,8 +1595,7 @@
ch->recv = &shared2->ch1;
} else {
struct smd_shared_v2 *shared2;
- shared2 = smem_alloc(SMEM_SMD_BASE_ID + ch->n,
- sizeof(*shared2));
+ shared2 = smem_alloc(base_id + ch->n, sizeof(*shared2));
if (!shared2) {
SMD_INFO("smem_alloc failed ch=%d\n", ch->n);
return -EINVAL;
@@ -1689,7 +1605,7 @@
}
ch->half_ch = get_half_ch_funcs(ch->type);
- buffer = smem_get_entry(SMEM_SMD_FIFO_BASE_ID + ch->n, &buffer_sz);
+ buffer = smem_get_entry(fifo_id + ch->n, &buffer_sz);
if (!buffer) {
SMD_INFO("smem_get_entry failed\n");
return -EINVAL;
@@ -1714,7 +1630,7 @@
}
#else /* define v1 for older targets */
-static int smd_alloc_v2(struct smd_channel *ch)
+static int smd_alloc_v2(struct smd_channel *ch, int table_id)
{
return -EINVAL;
}
@@ -1738,7 +1654,16 @@
#endif
-static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm)
+/**
+ * smd_alloc_channel() - Create and init local structures for a newly allocated
+ * SMD channel
+ *
+ * @alloc_elm: the allocation element stored in SMEM for this channel
+ * @table_id: the id of the table this channel resides in. 1 = first table, 2 =
+ * seconds table, etc
+ * @returns: -1 for failure; 0 for success
+ */
+static int smd_alloc_channel(struct smd_alloc_elm *alloc_elm, int table_id)
{
struct smd_channel *ch;
@@ -1750,7 +1675,7 @@
ch->n = alloc_elm->cid;
ch->type = SMD_CHANNEL_TYPE(alloc_elm->type);
- if (smd_alloc_v2(ch) && smd_alloc_v1(ch)) {
+ if (smd_alloc_v2(ch, table_id) && smd_alloc_v1(ch)) {
kfree(ch);
return -1;
}
@@ -2712,28 +2637,28 @@
return IRQ_HANDLED;
}
-static irqreturn_t smsm_modem_irq_handler(int irq, void *data)
+irqreturn_t smsm_modem_irq_handler(int irq, void *data)
{
SMx_POWER_INFO("SMSM Int Modem->Apps\n");
++interrupt_stats[SMD_MODEM].smsm_in_count;
return smsm_irq_handler(irq, data);
}
-static irqreturn_t smsm_dsp_irq_handler(int irq, void *data)
+irqreturn_t smsm_dsp_irq_handler(int irq, void *data)
{
SMx_POWER_INFO("SMSM Int LPASS->Apps\n");
++interrupt_stats[SMD_Q6].smsm_in_count;
return smsm_irq_handler(irq, data);
}
-static irqreturn_t smsm_dsps_irq_handler(int irq, void *data)
+irqreturn_t smsm_dsps_irq_handler(int irq, void *data)
{
SMx_POWER_INFO("SMSM Int DSPS->Apps\n");
++interrupt_stats[SMD_DSPS].smsm_in_count;
return smsm_irq_handler(irq, data);
}
-static irqreturn_t smsm_wcnss_irq_handler(int irq, void *data)
+irqreturn_t smsm_wcnss_irq_handler(int irq, void *data)
{
SMx_POWER_INFO("SMSM Int WCNSS->Apps\n");
++interrupt_stats[SMD_WCNSS].smsm_in_count;
@@ -2825,7 +2750,8 @@
old_state = __raw_readl(SMSM_STATE_ADDR(smsm_entry));
new_state = (old_state & ~clear_mask) | set_mask;
__raw_writel(new_state, SMSM_STATE_ADDR(smsm_entry));
- SMSM_DBG("smsm_change_state %x\n", new_state);
+ SMx_POWER_INFO("%s %d:%08x->%08x", __func__, smsm_entry,
+ old_state, new_state);
notify_other_smsm(SMSM_APPS_STATE, (old_state ^ new_state));
spin_unlock_irqrestore(&smem_lock, flags);
@@ -3090,523 +3016,6 @@
}
EXPORT_SYMBOL(smsm_state_cb_deregister);
-int smd_core_init(void)
-{
- int r;
- unsigned long flags = IRQF_TRIGGER_RISING;
- SMD_INFO("smd_core_init()\n");
-
- r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
- flags, "smd_dev", 0);
- if (r < 0)
- return r;
- interrupt_stats[SMD_MODEM].smd_interrupt_id = INT_A9_M2A_0;
- r = enable_irq_wake(INT_A9_M2A_0);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_A9_M2A_0\n");
-
- r = request_irq(INT_A9_M2A_5, smsm_modem_irq_handler,
- flags, "smsm_dev", 0);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- return r;
- }
- interrupt_stats[SMD_MODEM].smsm_interrupt_id = INT_A9_M2A_5;
- r = enable_irq_wake(INT_A9_M2A_5);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_A9_M2A_5\n");
-
-#if defined(CONFIG_QDSP6)
-#if (INT_ADSP_A11 == INT_ADSP_A11_SMSM)
- flags |= IRQF_SHARED;
-#endif
- r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
- flags, "smd_dev", smd_dsp_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- return r;
- }
-
- interrupt_stats[SMD_Q6].smd_interrupt_id = INT_ADSP_A11;
- r = request_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler,
- flags, "smsm_dev", smsm_dsp_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- return r;
- }
-
- interrupt_stats[SMD_Q6].smsm_interrupt_id = INT_ADSP_A11_SMSM;
- r = enable_irq_wake(INT_ADSP_A11);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_ADSP_A11\n");
-
-#if (INT_ADSP_A11 != INT_ADSP_A11_SMSM)
- r = enable_irq_wake(INT_ADSP_A11_SMSM);
- if (r < 0)
- pr_err("smd_core_init: enable_irq_wake "
- "failed for INT_ADSP_A11_SMSM\n");
-#endif
- flags &= ~IRQF_SHARED;
-#endif
-
-#if defined(CONFIG_DSPS)
- r = request_irq(INT_DSPS_A11, smd_dsps_irq_handler,
- flags, "smd_dev", smd_dsps_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
- return r;
- }
-
- interrupt_stats[SMD_DSPS].smd_interrupt_id = INT_DSPS_A11;
- r = enable_irq_wake(INT_DSPS_A11);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_ADSP_A11\n");
-#endif
-
-#if defined(CONFIG_WCNSS)
- r = request_irq(INT_WCNSS_A11, smd_wcnss_irq_handler,
- flags, "smd_dev", smd_wcnss_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
- free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
- return r;
- }
-
- interrupt_stats[SMD_WCNSS].smd_interrupt_id = INT_WCNSS_A11;
- r = enable_irq_wake(INT_WCNSS_A11);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_WCNSS_A11\n");
-
- r = request_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler,
- flags, "smsm_dev", smsm_wcnss_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
- free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
- free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
- return r;
- }
-
- interrupt_stats[SMD_WCNSS].smsm_interrupt_id = INT_WCNSS_A11_SMSM;
- r = enable_irq_wake(INT_WCNSS_A11_SMSM);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_WCNSS_A11_SMSM\n");
-#endif
-
-#if defined(CONFIG_DSPS_SMSM)
- r = request_irq(INT_DSPS_A11_SMSM, smsm_dsps_irq_handler,
- flags, "smsm_dev", smsm_dsps_irq_handler);
- if (r < 0) {
- free_irq(INT_A9_M2A_0, 0);
- free_irq(INT_A9_M2A_5, 0);
- free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
- free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
- free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
- free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
- free_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler);
- return r;
- }
-
- interrupt_stats[SMD_DSPS].smsm_interrupt_id = INT_DSPS_A11_SMSM;
- r = enable_irq_wake(INT_DSPS_A11_SMSM);
- if (r < 0)
- pr_err("smd_core_init: "
- "enable_irq_wake failed for INT_DSPS_A11_SMSM\n");
-#endif
- SMD_INFO("smd_core_init() done\n");
-
- return 0;
-}
-
-static int intr_init(struct interrupt_config_item *private_irq,
- struct smd_irq_config *platform_irq,
- struct platform_device *pdev
- )
-{
- int irq_id;
- int ret;
- int ret_wake;
-
- private_irq->out_bit_pos = platform_irq->out_bit_pos;
- private_irq->out_offset = platform_irq->out_offset;
- private_irq->out_base = platform_irq->out_base;
-
- irq_id = platform_get_irq_byname(
- pdev,
- platform_irq->irq_name
- );
- SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
- platform_irq->irq_name, irq_id);
- ret = request_irq(irq_id,
- private_irq->irq_handler,
- platform_irq->flags,
- platform_irq->device_name,
- (void *)platform_irq->dev_id
- );
- if (ret < 0) {
- platform_irq->irq_id = ret;
- private_irq->irq_id = ret;
- } else {
- platform_irq->irq_id = irq_id;
- private_irq->irq_id = irq_id;
- ret_wake = enable_irq_wake(irq_id);
- if (ret_wake < 0) {
- pr_err("smd: enable_irq_wake failed on %s",
- platform_irq->irq_name);
- }
- }
-
- return ret;
-}
-
-int smd_core_platform_init(struct platform_device *pdev)
-{
- int i;
- int ret;
- uint32_t num_ss;
- struct smd_platform *smd_platform_data;
- struct smd_subsystem_config *smd_ss_config_list;
- struct smd_subsystem_config *cfg;
- int err_ret = 0;
-
- smd_platform_data = pdev->dev.platform_data;
- num_ss = smd_platform_data->num_ss_configs;
- smd_ss_config_list = smd_platform_data->smd_ss_configs;
-
- if (smd_platform_data->smd_ssr_config)
- disable_smsm_reset_handshake = smd_platform_data->
- smd_ssr_config->disable_smsm_reset_handshake;
-
- for (i = 0; i < num_ss; i++) {
- cfg = &smd_ss_config_list[i];
-
- ret = intr_init(
- &private_intr_config[cfg->irq_config_id].smd,
- &cfg->smd_int,
- pdev
- );
-
- if (ret < 0) {
- err_ret = ret;
- pr_err("smd: register irq failed on %s\n",
- cfg->smd_int.irq_name);
- goto intr_failed;
- }
-
- interrupt_stats[cfg->irq_config_id].smd_interrupt_id
- = cfg->smd_int.irq_id;
- /* only init smsm structs if this edge supports smsm */
- if (cfg->smsm_int.irq_id)
- ret = intr_init(
- &private_intr_config[cfg->irq_config_id].smsm,
- &cfg->smsm_int,
- pdev
- );
-
- if (ret < 0) {
- err_ret = ret;
- pr_err("smd: register irq failed on %s\n",
- cfg->smsm_int.irq_name);
- goto intr_failed;
- }
-
- if (cfg->smsm_int.irq_id)
- interrupt_stats[cfg->irq_config_id].smsm_interrupt_id
- = cfg->smsm_int.irq_id;
- if (cfg->subsys_name)
- strlcpy(edge_to_pids[cfg->edge].subsys_name,
- cfg->subsys_name, SMD_MAX_CH_NAME_LEN);
- }
-
- SMD_INFO("smd_core_platform_init() done\n");
-
- return 0;
-
-intr_failed:
- pr_err("smd: deregistering IRQs\n");
- for (i = 0; i < num_ss; ++i) {
- cfg = &smd_ss_config_list[i];
-
- if (cfg->smd_int.irq_id >= 0)
- free_irq(cfg->smd_int.irq_id,
- (void *)cfg->smd_int.dev_id
- );
- if (cfg->smsm_int.irq_id >= 0)
- free_irq(cfg->smsm_int.irq_id,
- (void *)cfg->smsm_int.dev_id
- );
- }
- return err_ret;
-}
-
-static int msm_smsm_probe(struct platform_device *pdev)
-{
- uint32_t edge;
- char *key;
- int ret;
- uint32_t irq_offset;
- uint32_t irq_bitmask;
- uint32_t irq_line;
- struct interrupt_config_item *private_irq;
- struct device_node *node;
- void *irq_out_base;
- resource_size_t irq_out_size;
- struct platform_device *parent_pdev;
- struct resource *r;
-
- disable_smsm_reset_handshake = 1;
-
- node = pdev->dev.of_node;
-
- if (!pdev->dev.parent) {
- pr_err("%s: missing link to parent device\n", __func__);
- return -ENODEV;
- }
-
- parent_pdev = to_platform_device(pdev->dev.parent);
-
- key = "irq-reg-base";
- r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
- if (!r)
- goto missing_key;
- irq_out_size = resource_size(r);
- irq_out_base = ioremap_nocache(r->start, irq_out_size);
- if (!irq_out_base) {
- pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
- __func__, &r->start, &irq_out_size);
- return -ENOMEM;
- }
- SMSM_DBG("%s: %s = %p", __func__, key, irq_out_base);
-
- key = "qcom,smsm-edge";
- ret = of_property_read_u32(node, key, &edge);
- if (ret)
- goto missing_key;
- SMSM_DBG("%s: %s = %d", __func__, key, edge);
-
- key = "qcom,smsm-irq-offset";
- ret = of_property_read_u32(node, key, &irq_offset);
- if (ret)
- goto missing_key;
- SMSM_DBG("%s: %s = %x", __func__, key, irq_offset);
-
- key = "qcom,smsm-irq-bitmask";
- ret = of_property_read_u32(node, key, &irq_bitmask);
- if (ret)
- goto missing_key;
- SMSM_DBG("%s: %s = %x", __func__, key, irq_bitmask);
-
- key = "interrupts";
- irq_line = irq_of_parse_and_map(node, 0);
- if (!irq_line)
- goto missing_key;
- SMSM_DBG("%s: %s = %d", __func__, key, irq_line);
-
- private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smsm;
- private_irq->out_bit_pos = irq_bitmask;
- private_irq->out_offset = irq_offset;
- private_irq->out_base = irq_out_base;
- private_irq->irq_id = irq_line;
-
- ret = request_irq(irq_line,
- private_irq->irq_handler,
- IRQF_TRIGGER_RISING,
- "smsm_dev",
- NULL);
- if (ret < 0) {
- pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
- return ret;
- } else {
- ret = enable_irq_wake(irq_line);
- if (ret < 0)
- pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
- irq_line);
- }
-
- if (smsm_init())
- pr_err("smsm_init() failed\n");
-
- smsm_irq_handler(0, 0);
-
- return 0;
-
-missing_key:
- pr_err("%s: missing key: %s", __func__, key);
- return -ENODEV;
-}
-
-static int msm_smd_probe(struct platform_device *pdev)
-{
- uint32_t edge;
- char *key;
- int ret;
- uint32_t irq_offset;
- uint32_t irq_bitmask;
- uint32_t irq_line;
- unsigned long irq_flags = IRQF_TRIGGER_RISING;
- const char *pilstr;
- struct interrupt_config_item *private_irq;
- struct device_node *node;
- void *irq_out_base;
- resource_size_t irq_out_size;
- struct platform_device *parent_pdev;
- struct resource *r;
-
- node = pdev->dev.of_node;
-
- if (!pdev->dev.parent) {
- pr_err("%s: missing link to parent device\n", __func__);
- return -ENODEV;
- }
-
- parent_pdev = to_platform_device(pdev->dev.parent);
-
- key = "irq-reg-base";
- r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
- if (!r)
- goto missing_key;
- irq_out_size = resource_size(r);
- irq_out_base = ioremap_nocache(r->start, irq_out_size);
- if (!irq_out_base) {
- pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
- __func__, &r->start, &irq_out_size);
- return -ENOMEM;
- }
- SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
-
- key = "qcom,smd-edge";
- ret = of_property_read_u32(node, key, &edge);
- if (ret)
- goto missing_key;
- SMD_DBG("%s: %s = %d", __func__, key, edge);
-
- key = "qcom,smd-irq-offset";
- ret = of_property_read_u32(node, key, &irq_offset);
- if (ret)
- goto missing_key;
- SMD_DBG("%s: %s = %x", __func__, key, irq_offset);
-
- key = "qcom,smd-irq-bitmask";
- ret = of_property_read_u32(node, key, &irq_bitmask);
- if (ret)
- goto missing_key;
- SMD_DBG("%s: %s = %x", __func__, key, irq_bitmask);
-
- key = "interrupts";
- irq_line = irq_of_parse_and_map(node, 0);
- if (!irq_line)
- goto missing_key;
- SMD_DBG("%s: %s = %d", __func__, key, irq_line);
-
- key = "qcom,pil-string";
- pilstr = of_get_property(node, key, NULL);
- if (pilstr)
- SMD_DBG("%s: %s = %s", __func__, key, pilstr);
-
- key = "qcom,irq-no-suspend";
- ret = of_property_read_bool(node, key);
- if (ret)
- irq_flags |= IRQF_NO_SUSPEND;
-
- private_irq = &private_intr_config[edge_to_pids[edge].remote_pid].smd;
- private_irq->out_bit_pos = irq_bitmask;
- private_irq->out_offset = irq_offset;
- private_irq->out_base = irq_out_base;
- private_irq->irq_id = irq_line;
-
- ret = request_irq(irq_line,
- private_irq->irq_handler,
- irq_flags,
- "smd_dev",
- NULL);
- if (ret < 0) {
- pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
- return ret;
- } else {
- ret = enable_irq_wake(irq_line);
- if (ret < 0)
- pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
- irq_line);
- }
-
- if (pilstr)
- strlcpy(edge_to_pids[edge].subsys_name, pilstr,
- SMD_MAX_CH_NAME_LEN);
-
- edge_to_pids[edge].initialized = true;
-
- schedule_work(&probe_work);
-
- return 0;
-
-missing_key:
- pr_err("%s: missing key: %s", __func__, key);
- return -ENODEV;
-}
-
-static int msm_smd_probe_legacy(struct platform_device *pdev)
-{
- int ret;
-
- if (!smem_initialized_check())
- return -ENODEV;
-
- SMD_INFO("smd probe\n");
-
- if (smsm_init()) {
- pr_err("smsm_init() failed\n");
- return -1;
- }
-
- if (pdev) {
- if (pdev->dev.of_node) {
- pr_err("%s: invalid device tree init\n", __func__);
- return -ENODEV;
- } else if (pdev->dev.platform_data) {
- ret = smd_core_platform_init(pdev);
- if (ret) {
- pr_err(
- "SMD: smd_core_platform_init() failed\n");
- return -ENODEV;
- }
- } else {
- ret = smd_core_init();
- if (ret) {
- pr_err("smd_core_init() failed\n");
- return -ENODEV;
- }
- }
- } else {
- pr_err("SMD: PDEV not found\n");
- return -ENODEV;
- }
-
- smd_initialized = 1;
-
- smd_alloc_loopback_channel();
- smsm_irq_handler(0, 0);
- tasklet_schedule(&smd_fake_irq_tasklet);
-
- return 0;
-}
-
static int restart_notifier_cb(struct notifier_block *this,
unsigned long code,
void *data);
@@ -3650,6 +3059,137 @@
return NOTIFY_DONE;
}
+/**
+ * smd_post_init() - SMD post initialization
+ * @is_leagcy: 1 for Leagcy/platform device init sequence
+ * 0 for device tree init sequence
+ *
+ * This function is used by the legacy and device tree initialization
+ * to complete the SMD init sequence.
+ */
+void smd_post_init(bool is_legacy)
+{
+ if (is_legacy) {
+ smd_initialized = 1;
+ smd_alloc_loopback_channel();
+ tasklet_schedule(&smd_fake_irq_tasklet);
+ } else {
+ schedule_work(&probe_work);
+ }
+}
+
+/**
+ * smsm_post_init() - SMSM post initialization
+ * @returns: 0 for success, standard Linux error code otherwise
+ *
+ * This function is used by the legacy and device tree initialization
+ * to complete the SMSM init sequence.
+ */
+int smsm_post_init(void)
+{
+ int ret;
+
+ ret = smsm_init();
+ if (ret) {
+ pr_err("smsm_init() failed ret = %d\n", ret);
+ return ret;
+ }
+ smsm_irq_handler(0, 0);
+
+ return ret;
+}
+
+/**
+ * smd_get_intr_config() - Get interrupt configuration structure
+ * @edge: edge type identifes local and remote processor
+ * @returns: pointer to interrupt configuration
+ *
+ * This function returns the interrupt configuration of remote processor
+ * based on the edge type.
+ */
+struct interrupt_config *smd_get_intr_config(uint32_t edge)
+{
+ if (edge >= ARRAY_SIZE(edge_to_pids))
+ return NULL;
+ return &private_intr_config[edge_to_pids[edge].remote_pid];
+}
+
+/**
+ * smd_get_edge_remote_pid() - Get the remote processor ID
+ * @edge: edge type identifes local and remote processor
+ * @returns: remote processor ID
+ *
+ * This function returns remote processor ID based on edge type.
+ */
+int smd_edge_to_remote_pid(uint32_t edge)
+{
+ if (edge >= ARRAY_SIZE(edge_to_pids))
+ return -EINVAL;
+ return edge_to_pids[edge].remote_pid;
+}
+
+/**
+ * smd_set_edge_subsys_name() - Set the subsystem name
+ * @edge: edge type identifies local and remote processor
+ * @sussys_name: pointer to subsystem name
+ *
+ * This function is used to set the subsystem name for given edge type.
+ */
+void smd_set_edge_subsys_name(uint32_t edge, const char *subsys_name)
+{
+ if (edge <= ARRAY_SIZE(edge_to_pids))
+ strlcpy(edge_to_pids[edge].subsys_name,
+ subsys_name, SMD_MAX_CH_NAME_LEN);
+ else
+ pr_err("%s: Invalid edge type[%d]\n", __func__, edge);
+}
+
+/**
+ * smd_set_edge_initialized() - Set the edge initialized status
+ * @edge: edge type identifies local and remote processor
+ *
+ * This function set the initialized varibale based on edge type.
+ */
+void smd_set_edge_initialized(uint32_t edge)
+{
+ if (edge <= ARRAY_SIZE(edge_to_pids))
+ edge_to_pids[edge].initialized = true;
+ else
+ pr_err("%s: Invalid edge type[%d]\n", __func__, edge);
+}
+
+/**
+ * smd_cfg_smd_intr() - Set the SMD interrupt configuration
+ * @proc: remote processor ID
+ * @mask: bit position in IRQ register
+ * @ptr: IRQ register
+ *
+ * This function is called in Legacy init sequence and used to set
+ * the SMD interrupt configurations for particular processor.
+ */
+void smd_cfg_smd_intr(uint32_t proc, uint32_t mask, void *ptr)
+{
+ private_intr_config[proc].smd.out_bit_pos = mask;
+ private_intr_config[proc].smd.out_base = ptr;
+ private_intr_config[proc].smd.out_offset = 0;
+}
+
+/*
+ * smd_cfg_smsm_intr() - Set the SMSM interrupt configuration
+ * @proc: remote processor ID
+ * @mask: bit position in IRQ register
+ * @ptr: IRQ register
+ *
+ * This function is called in Legacy init sequence and used to set
+ * the SMSM interrupt configurations for particular processor.
+ */
+void smd_cfg_smsm_intr(uint32_t proc, uint32_t mask, void *ptr)
+{
+ private_intr_config[proc].smsm.out_bit_pos = mask;
+ private_intr_config[proc].smsm.out_base = ptr;
+ private_intr_config[proc].smsm.out_offset = 0;
+}
+
static __init int modem_restart_late_init(void)
{
int i;
@@ -3667,42 +3207,6 @@
}
late_initcall(modem_restart_late_init);
-static struct of_device_id msm_smd_match_table[] = {
- { .compatible = "qcom,smd" },
- {},
-};
-
-static struct platform_driver msm_smd_driver = {
- .probe = msm_smd_probe,
- .driver = {
- .name = "msm_smd_dt",
- .owner = THIS_MODULE,
- .of_match_table = msm_smd_match_table,
- },
-};
-
-static struct of_device_id msm_smsm_match_table[] = {
- { .compatible = "qcom,smsm" },
- {},
-};
-
-static struct platform_driver msm_smsm_driver = {
- .probe = msm_smsm_probe,
- .driver = {
- .name = "msm_smsm",
- .owner = THIS_MODULE,
- .of_match_table = msm_smsm_match_table,
- },
-};
-
-static struct platform_driver msm_smd_driver_legacy = {
- .probe = msm_smd_probe_legacy,
- .driver = {
- .name = MODULE_NAME,
- .owner = THIS_MODULE,
- },
-};
-
int __init msm_smd_init(void)
{
static bool registered;
@@ -3727,27 +3231,12 @@
return -ENOMEM;
}
- rc = platform_driver_register(&msm_smd_driver_legacy);
- if (rc) {
- pr_err("%s: msm_smd_driver_legacy register failed %d\n",
- __func__, rc);
- return rc;
- }
-
- rc = platform_driver_register(&msm_smd_driver);
+ rc = msm_smd_driver_register();
if (rc) {
pr_err("%s: msm_smd_driver register failed %d\n",
__func__, rc);
return rc;
}
-
- rc = platform_driver_register(&msm_smsm_driver);
- if (rc) {
- pr_err("%s: msm_smsm_driver register failed %d\n",
- __func__, rc);
- return rc;
- }
-
return 0;
}
diff --git a/arch/arm/mach-msm/smd_init_dt.c b/arch/arm/mach-msm/smd_init_dt.c
new file mode 100644
index 0000000..d888a72
--- /dev/null
+++ b/arch/arm/mach-msm/smd_init_dt.c
@@ -0,0 +1,322 @@
+/* arch/arm/mach-msm/smd_init_dt.c
+ *
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifdef CONFIG_OF
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include <mach/msm_ipc_logging.h>
+#include <smd_private.h>
+
+#define MODULE_NAME "msm_smd"
+#define IPC_LOG(level, x...) do { \
+ if (smd_log_ctx) \
+ ipc_log_string(smd_log_ctx, x); \
+ else \
+ printk(level x); \
+ } while (0)
+
+#if defined(CONFIG_MSM_SMD_DEBUG)
+#define SMD_DBG(x...) do { \
+ if (msm_smd_debug_mask & MSM_SMD_DEBUG) \
+ IPC_LOG(KERN_DEBUG, x); \
+ } while (0)
+
+#define SMSM_DBG(x...) do { \
+ if (msm_smd_debug_mask & MSM_SMSM_DEBUG) \
+ IPC_LOG(KERN_DEBUG, x); \
+ } while (0)
+#else
+#define SMD_DBG(x...) do { } while (0)
+#define SMSM_DBG(x...) do { } while (0)
+#endif
+
+static int msm_smsm_probe(struct platform_device *pdev)
+{
+ uint32_t edge;
+ char *key;
+ int ret;
+ uint32_t irq_offset;
+ uint32_t irq_bitmask;
+ uint32_t irq_line;
+ struct interrupt_config_item *private_irq;
+ struct device_node *node;
+ void *irq_out_base;
+ resource_size_t irq_out_size;
+ struct platform_device *parent_pdev;
+ struct resource *r;
+ struct interrupt_config *private_intr_config;
+ uint32_t remote_pid;
+
+ disable_smsm_reset_handshake = 1;
+
+ node = pdev->dev.of_node;
+
+ if (!pdev->dev.parent) {
+ pr_err("%s: missing link to parent device\n", __func__);
+ return -ENODEV;
+ }
+
+ parent_pdev = to_platform_device(pdev->dev.parent);
+
+ key = "irq-reg-base";
+ r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+ if (!r)
+ goto missing_key;
+ irq_out_size = resource_size(r);
+ irq_out_base = ioremap_nocache(r->start, irq_out_size);
+ if (!irq_out_base) {
+ pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+ __func__, &r->start, &irq_out_size);
+ return -ENOMEM;
+ }
+ SMSM_DBG("%s: %s = %p", __func__, key, irq_out_base);
+
+ key = "qcom,smsm-edge";
+ ret = of_property_read_u32(node, key, &edge);
+ if (ret)
+ goto missing_key;
+ SMSM_DBG("%s: %s = %d", __func__, key, edge);
+
+ key = "qcom,smsm-irq-offset";
+ ret = of_property_read_u32(node, key, &irq_offset);
+ if (ret)
+ goto missing_key;
+ SMSM_DBG("%s: %s = %x", __func__, key, irq_offset);
+
+ key = "qcom,smsm-irq-bitmask";
+ ret = of_property_read_u32(node, key, &irq_bitmask);
+ if (ret)
+ goto missing_key;
+ SMSM_DBG("%s: %s = %x", __func__, key, irq_bitmask);
+
+ key = "interrupts";
+ irq_line = irq_of_parse_and_map(node, 0);
+ if (!irq_line)
+ goto missing_key;
+ SMSM_DBG("%s: %s = %d", __func__, key, irq_line);
+
+ private_intr_config = smd_get_intr_config(edge);
+ if (!private_intr_config) {
+ pr_err("%s: invalid edge\n", __func__);
+ return -ENODEV;
+ }
+ private_irq = &private_intr_config->smsm;
+ private_irq->out_bit_pos = irq_bitmask;
+ private_irq->out_offset = irq_offset;
+ private_irq->out_base = irq_out_base;
+ private_irq->irq_id = irq_line;
+ remote_pid = smd_edge_to_remote_pid(edge);
+ interrupt_stats[remote_pid].smsm_interrupt_id = irq_line;
+
+ ret = request_irq(irq_line,
+ private_irq->irq_handler,
+ IRQF_TRIGGER_RISING,
+ "smsm_dev",
+ NULL);
+ if (ret < 0) {
+ pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
+ return ret;
+ } else {
+ ret = enable_irq_wake(irq_line);
+ if (ret < 0)
+ pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
+ irq_line);
+ }
+
+ ret = smsm_post_init();
+ if (ret) {
+ pr_err("smd_post_init() failed ret=%d\n", ret);
+ return ret;
+ }
+
+ return 0;
+
+missing_key:
+ pr_err("%s: missing key: %s", __func__, key);
+ return -ENODEV;
+}
+
+static int msm_smd_probe(struct platform_device *pdev)
+{
+ uint32_t edge;
+ char *key;
+ int ret;
+ uint32_t irq_offset;
+ uint32_t irq_bitmask;
+ uint32_t irq_line;
+ unsigned long irq_flags = IRQF_TRIGGER_RISING;
+ const char *pilstr;
+ struct interrupt_config_item *private_irq;
+ struct device_node *node;
+ void *irq_out_base;
+ resource_size_t irq_out_size;
+ struct platform_device *parent_pdev;
+ struct resource *r;
+ struct interrupt_config *private_intr_config;
+ uint32_t remote_pid;
+
+ node = pdev->dev.of_node;
+
+ if (!pdev->dev.parent) {
+ pr_err("%s: missing link to parent device\n", __func__);
+ return -ENODEV;
+ }
+
+ parent_pdev = to_platform_device(pdev->dev.parent);
+
+ key = "irq-reg-base";
+ r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key);
+ if (!r)
+ goto missing_key;
+ irq_out_size = resource_size(r);
+ irq_out_base = ioremap_nocache(r->start, irq_out_size);
+ if (!irq_out_base) {
+ pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n",
+ __func__, &r->start, &irq_out_size);
+ return -ENOMEM;
+ }
+ SMD_DBG("%s: %s = %p", __func__, key, irq_out_base);
+
+ key = "qcom,smd-edge";
+ ret = of_property_read_u32(node, key, &edge);
+ if (ret)
+ goto missing_key;
+ SMD_DBG("%s: %s = %d", __func__, key, edge);
+
+ key = "qcom,smd-irq-offset";
+ ret = of_property_read_u32(node, key, &irq_offset);
+ if (ret)
+ goto missing_key;
+ SMD_DBG("%s: %s = %x", __func__, key, irq_offset);
+
+ key = "qcom,smd-irq-bitmask";
+ ret = of_property_read_u32(node, key, &irq_bitmask);
+ if (ret)
+ goto missing_key;
+ SMD_DBG("%s: %s = %x", __func__, key, irq_bitmask);
+
+ key = "interrupts";
+ irq_line = irq_of_parse_and_map(node, 0);
+ if (!irq_line)
+ goto missing_key;
+ SMD_DBG("%s: %s = %d", __func__, key, irq_line);
+
+ key = "qcom,pil-string";
+ pilstr = of_get_property(node, key, NULL);
+ if (pilstr)
+ SMD_DBG("%s: %s = %s", __func__, key, pilstr);
+
+ key = "qcom,irq-no-suspend";
+ ret = of_property_read_bool(node, key);
+ if (ret)
+ irq_flags |= IRQF_NO_SUSPEND;
+
+ private_intr_config = smd_get_intr_config(edge);
+ if (!private_intr_config) {
+ pr_err("%s: invalid edge\n", __func__);
+ return -ENODEV;
+ }
+ private_irq = &private_intr_config->smd;
+ private_irq->out_bit_pos = irq_bitmask;
+ private_irq->out_offset = irq_offset;
+ private_irq->out_base = irq_out_base;
+ private_irq->irq_id = irq_line;
+ remote_pid = smd_edge_to_remote_pid(edge);
+ interrupt_stats[remote_pid].smd_interrupt_id = irq_line;
+
+ ret = request_irq(irq_line,
+ private_irq->irq_handler,
+ irq_flags,
+ "smd_dev",
+ NULL);
+ if (ret < 0) {
+ pr_err("%s: request_irq() failed on %d\n", __func__, irq_line);
+ return ret;
+ } else {
+ ret = enable_irq_wake(irq_line);
+ if (ret < 0)
+ pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
+ irq_line);
+ }
+
+ if (pilstr)
+ smd_set_edge_subsys_name(edge, pilstr);
+
+ smd_set_edge_initialized(edge);
+ smd_post_init(0);
+ return 0;
+
+missing_key:
+ pr_err("%s: missing key: %s", __func__, key);
+ return -ENODEV;
+}
+
+static struct of_device_id msm_smd_match_table[] = {
+ { .compatible = "qcom,smd" },
+ {},
+};
+
+static struct platform_driver msm_smd_driver = {
+ .probe = msm_smd_probe,
+ .driver = {
+ .name = MODULE_NAME ,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_smd_match_table,
+ },
+};
+
+static struct of_device_id msm_smsm_match_table[] = {
+ { .compatible = "qcom,smsm" },
+ {},
+};
+
+static struct platform_driver msm_smsm_driver = {
+ .probe = msm_smsm_probe,
+ .driver = {
+ .name = "msm_smsm",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_smsm_match_table,
+ },
+};
+
+int msm_smd_driver_register(void)
+{
+ int rc;
+
+ rc = platform_driver_register(&msm_smd_driver);
+ if (rc) {
+ pr_err("%s: smd_driver register failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = platform_driver_register(&msm_smsm_driver);
+ if (rc) {
+ pr_err("%s: msm_smsm_driver register failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(msm_smd_driver_register);
+
+MODULE_DESCRIPTION("MSM SMD Device Tree Init");
+MODULE_LICENSE("GPL v2");
+#endif
diff --git a/arch/arm/mach-msm/smd_init_plat.c b/arch/arm/mach-msm/smd_init_plat.c
new file mode 100644
index 0000000..c6f6cd9
--- /dev/null
+++ b/arch/arm/mach-msm/smd_init_plat.c
@@ -0,0 +1,535 @@
+/* arch/arm/mach-msm/smd_init_plat.c
+ *
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef CONFIG_OF
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/msm_ipc_logging.h>
+#include <smd_private.h>
+
+#define MODULE_NAME "msm_smd"
+#define IPC_LOG(level, x...) do { \
+ if (smd_log_ctx) \
+ ipc_log_string(smd_log_ctx, x); \
+ else \
+ printk(level x); \
+ } while (0)
+
+#if defined(CONFIG_MSM_SMD_DEBUG)
+#define SMD_DBG(x...) do { \
+ if (msm_smd_debug_mask & MSM_SMD_DEBUG) \
+ IPC_LOG(KERN_DEBUG, x); \
+ } while (0)
+
+#define SMD_INFO(x...) do { \
+ if (msm_smd_debug_mask & MSM_SMD_INFO) \
+ IPC_LOG(KERN_INFO, x); \
+ } while (0)
+#else
+#define SMD_DBG(x...) do { } while (0)
+#define SMD_INFO(x...) do { } while (0)
+#endif
+
+#if defined(CONFIG_ARCH_QSD8X50) || defined(CONFIG_ARCH_MSM8X60) \
+ || defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_FSM9XXX) \
+ || defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_APQ8064)
+#define CONFIG_QDSP6 1
+#endif
+
+#if defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960) \
+ || defined(CONFIG_ARCH_APQ8064)
+#define CONFIG_DSPS 1
+#endif
+
+#if defined(CONFIG_ARCH_MSM8960) \
+ || defined(CONFIG_ARCH_APQ8064)
+#define CONFIG_WCNSS 1
+#define CONFIG_DSPS_SMSM 1
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X30)
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1 << 0, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMD_INT \
+ (smd_cfg_smd_intr(SMD_Q6, 1 << 8, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1 << 5, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_Q6, 1 << 8, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM8X60)
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1 << 3, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMD_INT \
+ (smd_cfg_smd_intr(SMD_Q6, 1 << 15, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1 << 4, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_Q6, 1 << 14, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2DSPS_SMD_INT \
+ (smd_cfg_smd_intr(SMD_DSPS, 1, \
+ MSM_SIC_NON_SECURE_BASE + 0x4080))
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM9615)
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1 << 3, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMD_INT \
+ (smd_cfg_smd_intr(SMD_Q6, 1 << 15, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1 << 4, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_Q6, 1 << 14, MSM_APCS_GCC_BASE + 0x8))
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_FSM9XXX)
+#define MSM_CFG_A2Q6_SMD_INT \
+ (smd_cfg_smd_intr(SMD_Q6, 1 << 10, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2Q6_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_Q6, 1 << 10, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1 << 0, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1 << 5, MSM_GCC_BASE + 0x8))
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM7X01A) || defined(CONFIG_ARCH_MSM7x25)
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1, MSM_CSR_BASE + 0x400 + (0) * 4))
+#define MSM_CFG_A2Q6_SMD_INT
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1, \
+ MSM_CSR_BASE + 0x400 + (5) * 4))
+#define MSM_CFG_A2Q6_SMSM_INT
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#elif defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM7X27A)
+#define MSM_CFG_A2M_SMD_INT \
+ (smd_cfg_smd_intr(SMD_MODEM, 1, MSM_CSR_BASE + 0x400 + (0) * 4))
+#define MSM_CFG_A2Q6_SMD_INT
+#define MSM_CFG_A2M_SMSM_INT \
+ (smd_cfg_smsm_intr(SMD_MODEM, 1, \
+ MSM_CSR_BASE + 0x400 + (5) * 4))
+#define MSM_CFG_A2Q6_SMSM_INT
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#else /* use platform device / device tree configuration */
+#define MSM_CFG_A2M_SMD_INT
+#define MSM_CFG_A2Q6_SMD_INT
+#define MSM_CFG_A2M_SMSM_INT
+#define MSM_CFG_A2Q6_SMSM_INT
+#define MSM_CFG_A2DSPS_SMD_INT
+#define MSM_CFG_A2DSPS_SMSM_INT
+#define MSM_CFG_A2WCNSS_SMD_INT
+#define MSM_CFG_A2WCNSS_SMSM_INT
+#endif
+
+/*
+ * stub out legacy macros if they are not being used so that the legacy
+ * code compiles even though it is not used
+ *
+ * these definitions should not be used in active code and will cause
+ * an early failure
+ */
+#ifndef INT_A9_M2A_0
+#define INT_A9_M2A_0 -1
+#endif
+#ifndef INT_A9_M2A_5
+#define INT_A9_M2A_5 -1
+#endif
+#ifndef INT_ADSP_A11
+#define INT_ADSP_A11 -1
+#endif
+#ifndef INT_ADSP_A11_SMSM
+#define INT_ADSP_A11_SMSM -1
+#endif
+#ifndef INT_DSPS_A11
+#define INT_DSPS_A11 -1
+#endif
+#ifndef INT_DSPS_A11_SMSM
+#define INT_DSPS_A11_SMSM -1
+#endif
+#ifndef INT_WCNSS_A11
+#define INT_WCNSS_A11 -1
+#endif
+#ifndef INT_WCNSS_A11_SMSM
+#define INT_WCNSS_A11_SMSM -1
+#endif
+
+static int intr_init(struct interrupt_config_item *private_irq,
+ struct smd_irq_config *platform_irq,
+ struct platform_device *pdev
+ )
+{
+ int irq_id;
+ int ret;
+ int ret_wake;
+
+ private_irq->out_bit_pos = platform_irq->out_bit_pos;
+ private_irq->out_offset = platform_irq->out_offset;
+ private_irq->out_base = platform_irq->out_base;
+
+ irq_id = platform_get_irq_byname(
+ pdev,
+ platform_irq->irq_name
+ );
+ SMD_DBG("smd: %s: register irq: %s id: %d\n", __func__,
+ platform_irq->irq_name, irq_id);
+ ret = request_irq(irq_id,
+ private_irq->irq_handler,
+ platform_irq->flags,
+ platform_irq->device_name,
+ (void *)platform_irq->dev_id
+ );
+ if (ret < 0) {
+ platform_irq->irq_id = ret;
+ private_irq->irq_id = ret;
+ } else {
+ platform_irq->irq_id = irq_id;
+ private_irq->irq_id = irq_id;
+ ret_wake = enable_irq_wake(irq_id);
+ if (ret_wake < 0) {
+ pr_err("smd: enable_irq_wake failed on %s",
+ platform_irq->irq_name);
+ }
+ }
+
+ return ret;
+}
+
+int smd_core_init(void)
+{
+ int r;
+ unsigned long flags = IRQF_TRIGGER_RISING;
+ SMD_INFO("smd_core_init()\n");
+
+ MSM_CFG_A2M_SMD_INT;
+ MSM_CFG_A2Q6_SMD_INT;
+ MSM_CFG_A2M_SMSM_INT;
+ MSM_CFG_A2Q6_SMSM_INT;
+ MSM_CFG_A2DSPS_SMD_INT;
+ MSM_CFG_A2DSPS_SMSM_INT;
+ MSM_CFG_A2WCNSS_SMD_INT;
+ MSM_CFG_A2WCNSS_SMSM_INT;
+
+ r = request_irq(INT_A9_M2A_0, smd_modem_irq_handler,
+ flags, "smd_dev", 0);
+ if (r < 0)
+ return r;
+ interrupt_stats[SMD_MODEM].smd_interrupt_id = INT_A9_M2A_0;
+ r = enable_irq_wake(INT_A9_M2A_0);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_A9_M2A_0\n",
+ __func__);
+
+ r = request_irq(INT_A9_M2A_5, smsm_modem_irq_handler,
+ flags, "smsm_dev", 0);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ return r;
+ }
+ interrupt_stats[SMD_MODEM].smsm_interrupt_id = INT_A9_M2A_5;
+ r = enable_irq_wake(INT_A9_M2A_5);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_A9_M2A_5\n",
+ __func__);
+
+#if defined(CONFIG_QDSP6)
+#if (INT_ADSP_A11 == INT_ADSP_A11_SMSM)
+ flags |= IRQF_SHARED;
+#endif
+ r = request_irq(INT_ADSP_A11, smd_dsp_irq_handler,
+ flags, "smd_dev", smd_dsp_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ return r;
+ }
+
+ interrupt_stats[SMD_Q6].smd_interrupt_id = INT_ADSP_A11;
+ r = request_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler,
+ flags, "smsm_dev", smsm_dsp_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
+ return r;
+ }
+
+ interrupt_stats[SMD_Q6].smsm_interrupt_id = INT_ADSP_A11_SMSM;
+ r = enable_irq_wake(INT_ADSP_A11);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_ADSP_A11\n",
+ __func__);
+
+#if (INT_ADSP_A11 != INT_ADSP_A11_SMSM)
+ r = enable_irq_wake(INT_ADSP_A11_SMSM);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_ADSP_A11_SMSM\n",
+ __func__);
+#endif
+ flags &= ~IRQF_SHARED;
+#endif
+
+#if defined(CONFIG_DSPS)
+ r = request_irq(INT_DSPS_A11, smd_dsps_irq_handler,
+ flags, "smd_dev", smd_dsps_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
+ return r;
+ }
+
+ interrupt_stats[SMD_DSPS].smd_interrupt_id = INT_DSPS_A11;
+ r = enable_irq_wake(INT_DSPS_A11);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_ADSP_A11\n",
+ __func__);
+#endif
+
+#if defined(CONFIG_WCNSS)
+ r = request_irq(INT_WCNSS_A11, smd_wcnss_irq_handler,
+ flags, "smd_dev", smd_wcnss_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
+ free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
+ return r;
+ }
+
+ interrupt_stats[SMD_WCNSS].smd_interrupt_id = INT_WCNSS_A11;
+ r = enable_irq_wake(INT_WCNSS_A11);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_WCNSS_A11\n",
+ __func__);
+
+ r = request_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler,
+ flags, "smsm_dev", smsm_wcnss_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
+ free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
+ free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
+ return r;
+ }
+
+ interrupt_stats[SMD_WCNSS].smsm_interrupt_id = INT_WCNSS_A11_SMSM;
+ r = enable_irq_wake(INT_WCNSS_A11_SMSM);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_WCNSS_A11_SMSM\n",
+ __func__);
+#endif
+
+#if defined(CONFIG_DSPS_SMSM)
+ r = request_irq(INT_DSPS_A11_SMSM, smsm_dsps_irq_handler,
+ flags, "smsm_dev", smsm_dsps_irq_handler);
+ if (r < 0) {
+ free_irq(INT_A9_M2A_0, 0);
+ free_irq(INT_A9_M2A_5, 0);
+ free_irq(INT_ADSP_A11, smd_dsp_irq_handler);
+ free_irq(INT_ADSP_A11_SMSM, smsm_dsp_irq_handler);
+ free_irq(INT_DSPS_A11, smd_dsps_irq_handler);
+ free_irq(INT_WCNSS_A11, smd_wcnss_irq_handler);
+ free_irq(INT_WCNSS_A11_SMSM, smsm_wcnss_irq_handler);
+ return r;
+ }
+
+ interrupt_stats[SMD_DSPS].smsm_interrupt_id = INT_DSPS_A11_SMSM;
+ r = enable_irq_wake(INT_DSPS_A11_SMSM);
+ if (r < 0)
+ pr_err("%s: enable_irq_wake failed for INT_DSPS_A11_SMSM\n",
+ __func__);
+#endif
+ SMD_INFO("smd_core_init() done\n");
+
+ return 0;
+}
+
+int smd_core_platform_init(struct platform_device *pdev)
+{
+ int i;
+ int ret;
+ uint32_t num_ss;
+ struct smd_platform *smd_platform_data;
+ struct smd_subsystem_config *smd_ss_config_list;
+ struct smd_subsystem_config *cfg;
+ struct interrupt_config *private_intr_config;
+ int err_ret = 0;
+
+ smd_platform_data = pdev->dev.platform_data;
+ num_ss = smd_platform_data->num_ss_configs;
+ smd_ss_config_list = smd_platform_data->smd_ss_configs;
+
+ if (smd_platform_data->smd_ssr_config)
+ disable_smsm_reset_handshake = smd_platform_data->
+ smd_ssr_config->disable_smsm_reset_handshake;
+
+ for (i = 0; i < num_ss; i++) {
+ cfg = &smd_ss_config_list[i];
+ private_intr_config = smd_get_intr_config(cfg->edge);
+ if (!private_intr_config) {
+ pr_err("%s: invalid edge\n", __func__);
+ goto intr_failed;
+ }
+
+ ret = intr_init(
+ &private_intr_config->smd,
+ &cfg->smd_int,
+ pdev
+ );
+
+ if (ret < 0) {
+ err_ret = ret;
+ pr_err("smd: register irq failed on %s\n",
+ cfg->smd_int.irq_name);
+ goto intr_failed;
+ }
+
+ interrupt_stats[cfg->irq_config_id].smd_interrupt_id
+ = cfg->smd_int.irq_id;
+ /* only init smsm structs if this edge supports smsm */
+ if (cfg->smsm_int.irq_id)
+ ret = intr_init(
+ &private_intr_config->smsm,
+ &cfg->smsm_int,
+ pdev
+ );
+
+ if (ret < 0) {
+ err_ret = ret;
+ pr_err("smd: register irq failed on %s\n",
+ cfg->smsm_int.irq_name);
+ goto intr_failed;
+ }
+
+ if (cfg->smsm_int.irq_id)
+ interrupt_stats[cfg->irq_config_id].smsm_interrupt_id
+ = cfg->smsm_int.irq_id;
+ if (cfg->subsys_name)
+ smd_set_edge_subsys_name(cfg->edge, cfg->subsys_name);
+
+ smd_set_edge_initialized(cfg->edge);
+ }
+
+ SMD_INFO("smd_core_platform_init() done\n");
+
+ return 0;
+
+intr_failed:
+ pr_err("smd: deregistering IRQs\n");
+ for (i = 0; i < num_ss; ++i) {
+ cfg = &smd_ss_config_list[i];
+
+ if (cfg->smd_int.irq_id >= 0)
+ free_irq(cfg->smd_int.irq_id,
+ (void *)cfg->smd_int.dev_id
+ );
+ if (cfg->smsm_int.irq_id >= 0)
+ free_irq(cfg->smsm_int.irq_id,
+ (void *)cfg->smsm_int.dev_id
+ );
+ }
+ return err_ret;
+}
+
+static int msm_smd_probe_legacy(struct platform_device *pdev)
+{
+ int ret;
+
+ if (!smem_initialized_check())
+ return -ENODEV;
+
+ SMD_INFO("smd probe\n");
+ if (pdev) {
+ if (pdev->dev.of_node) {
+ pr_err("%s: invalid device tree init\n", __func__);
+ return -ENODEV;
+ } else if (pdev->dev.platform_data) {
+ ret = smd_core_platform_init(pdev);
+ if (ret) {
+ pr_err(
+ "SMD: smd_core_platform_init() failed\n");
+ return -ENODEV;
+ }
+ } else {
+ ret = smd_core_init();
+ if (ret) {
+ pr_err("smd_core_init() failed\n");
+ return -ENODEV;
+ }
+ }
+ } else {
+ pr_err("SMD: PDEV not found\n");
+ return -ENODEV;
+ }
+
+ ret = smsm_post_init();
+ if (ret) {
+ pr_err("smd_post_init() failed ret = %d\n", ret);
+ return ret;
+ }
+ smd_post_init(1);
+
+ return 0;
+}
+
+static struct platform_driver msm_smd_driver_legacy = {
+ .probe = msm_smd_probe_legacy,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+int msm_smd_driver_register(void)
+{
+
+ int rc;
+
+ rc = platform_driver_register(&msm_smd_driver_legacy);
+ if (rc) {
+ pr_err("%s: smd_driver register failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(msm_smd_driver_register);
+
+MODULE_DESCRIPTION("MSM SMD Legacy/Platform Device Init");
+MODULE_LICENSE("GPL v2");
+#endif
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 2096063..4664197 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -21,6 +21,7 @@
#include <linux/errno.h>
#include <linux/remote_spinlock.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <mach/msm_smsm.h>
#include <mach/msm_smd.h>
@@ -213,4 +214,60 @@
uint32_t smsm_interrupt_id;
};
extern struct interrupt_stat interrupt_stats[NUM_SMD_SUBSYSTEMS];
+
+struct interrupt_config_item {
+ /* must be initialized */
+ irqreturn_t (*irq_handler)(int req, void *data);
+ /* outgoing interrupt config (set from platform data) */
+ uint32_t out_bit_pos;
+ void __iomem *out_base;
+ uint32_t out_offset;
+ int irq_id;
+};
+
+enum {
+ MSM_SMD_DEBUG = 1U << 0,
+ MSM_SMSM_DEBUG = 1U << 1,
+ MSM_SMD_INFO = 1U << 2,
+ MSM_SMSM_INFO = 1U << 3,
+ MSM_SMx_POWER_INFO = 1U << 4,
+};
+
+struct interrupt_config {
+ struct interrupt_config_item smd;
+ struct interrupt_config_item smsm;
+};
+
+struct edge_to_pid {
+ uint32_t local_pid;
+ uint32_t remote_pid;
+ char subsys_name[SMD_MAX_CH_NAME_LEN];
+ bool initialized;
+};
+
+extern void *smd_log_ctx;
+extern int msm_smd_debug_mask;
+extern int disable_smsm_reset_handshake;
+extern bool smem_initialized_check(void);
+
+extern irqreturn_t smd_modem_irq_handler(int irq, void *data);
+extern irqreturn_t smsm_modem_irq_handler(int irq, void *data);
+extern irqreturn_t smd_dsp_irq_handler(int irq, void *data);
+extern irqreturn_t smsm_dsp_irq_handler(int irq, void *data);
+extern irqreturn_t smd_dsps_irq_handler(int irq, void *data);
+extern irqreturn_t smsm_dsps_irq_handler(int irq, void *data);
+extern irqreturn_t smd_wcnss_irq_handler(int irq, void *data);
+extern irqreturn_t smsm_wcnss_irq_handler(int irq, void *data);
+extern irqreturn_t smd_rpm_irq_handler(int irq, void *data);
+
+extern int msm_smd_driver_register(void);
+extern void smd_post_init(bool is_legacy);
+extern int smsm_post_init(void);
+
+extern struct interrupt_config *smd_get_intr_config(uint32_t edge);
+extern int smd_edge_to_remote_pid(uint32_t edge);
+extern void smd_set_edge_subsys_name(uint32_t edge, const char *subsys_name);
+extern void smd_set_edge_initialized(uint32_t edge);
+extern void smd_cfg_smd_intr(uint32_t proc, uint32_t mask, void *ptr);
+extern void smd_cfg_smsm_intr(uint32_t proc, uint32_t mask, void *ptr);
#endif
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 3461e49..6df1da4 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -36,9 +36,11 @@
#include "smd_private.h"
+#define MODULE_NAME "msm_smdtty"
#define MAX_SMD_TTYS 37
#define MAX_TTY_BUF_SIZE 2048
#define MAX_RA_WAKE_LOCK_NAME_LEN 32
+#define SMD_TTY_PROBE_WAIT_TIMEOUT 3000
#define SMD_TTY_LOG_PAGES 2
#define SMD_TTY_INFO(buf...) \
@@ -58,6 +60,9 @@
static void *smd_tty_log_ctx;
static DEFINE_MUTEX(smd_tty_lock);
+static struct delayed_work smd_tty_probe_work;
+static int smd_tty_probe_done;
+
struct smd_tty_info {
smd_channel_t *ch;
struct tty_port port;
@@ -77,7 +82,10 @@
spinlock_t ra_lock; /* Read Available Lock*/
char ra_wake_lock_name[MAX_RA_WAKE_LOCK_NAME_LEN];
struct wake_lock ra_wake_lock; /* Read Available Wakelock */
- struct smd_config *smd;
+
+ uint32_t edge;
+ char ch_name[SMD_MAX_CH_NAME_LEN];
+ char dev_name[SMD_MAX_CH_NAME_LEN];
};
/**
@@ -95,6 +103,12 @@
uint32_t edge;
};
+/**
+ * struct smd_config smd_configs[]: Legacy configuration
+ *
+ * An array of all SMD tty channel supported in legacy targets.
+ * Future targets use either platform device or device tree configuration.
+ */
static struct smd_config smd_configs[] = {
{0, "DS", NULL, SMD_APPS_MODEM},
{1, "APPS_FM", NULL, SMD_APPS_WCNSS},
@@ -104,6 +118,7 @@
{5, "APPS_RIVA_ANT_CMD", NULL, SMD_APPS_WCNSS},
{6, "APPS_RIVA_ANT_DATA", NULL, SMD_APPS_WCNSS},
{7, "DATA1", NULL, SMD_APPS_MODEM},
+ {8, "DATA4", NULL, SMD_APPS_MODEM},
{11, "DATA11", NULL, SMD_APPS_MODEM},
{21, "DATA21", NULL, SMD_APPS_MODEM},
{27, "GPSNMEA", NULL, SMD_APPS_MODEM},
@@ -326,7 +341,7 @@
const char *peripheral = NULL;
- if (n >= MAX_SMD_TTYS || !smd_tty[n].smd)
+ if (n >= MAX_SMD_TTYS || !smd_tty[n].ch_name)
return -ENODEV;
info = smd_tty + n;
@@ -334,13 +349,13 @@
mutex_lock(&smd_tty_lock);
tty->driver_data = info;
- peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
+ peripheral = smd_edge_to_subsystem(smd_tty[n].edge);
if (peripheral) {
info->pil = subsystem_get(peripheral);
if (IS_ERR(info->pil)) {
SMD_TTY_INFO(
"%s failed on smd_tty device :%s subsystem_get failed for %s",
- __func__, smd_tty[n].smd->port_name,
+ __func__, info->ch_name,
peripheral);
/*
@@ -379,13 +394,13 @@
if (res == 0) {
SMD_TTY_INFO(
"Timed out waiting for SMD channel %s",
- smd_tty[n].smd->port_name);
+ info->ch_name);
res = -ETIMEDOUT;
goto release_pil;
} else if (res < 0) {
SMD_TTY_INFO(
"Error waiting for SMD channel %s : %d\n",
- smd_tty[n].smd->port_name, res);
+ info->ch_name, res);
goto release_pil;
}
}
@@ -393,18 +408,18 @@
tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
- smd_tty[n].smd->port_name);
+ info->ch_name);
scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
- "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
+ "SMD_TTY_%s_RA", info->ch_name);
wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
info->ra_wake_lock_name);
- res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
- smd_tty[n].smd->edge, &info->ch, info,
+ res = smd_named_open_on_edge(info->ch_name,
+ smd_tty[n].edge, &info->ch, info,
smd_tty_notify);
if (res < 0) {
SMD_TTY_INFO("%s: %s open failed %d\n",
- __func__, smd_tty[n].smd->port_name, res);
+ __func__, info->ch_name, res);
goto release_wl_tl;
}
@@ -414,11 +429,11 @@
res = -ETIMEDOUT;
if (res < 0) {
SMD_TTY_INFO("%s: wait for %s smd_open failed %d\n",
- __func__, smd_tty[n].smd->port_name, res);
+ __func__, info->ch_name, res);
goto close_ch;
}
SMD_TTY_INFO("%s with PID %u opened port %s",
- current->comm, current->pid, smd_tty[n].smd->port_name);
+ current->comm, current->pid, info->ch_name);
smd_disable_read_intr(info->ch);
mutex_unlock(&smd_tty_lock);
return 0;
@@ -464,7 +479,7 @@
SMD_TTY_INFO("%s with PID %u closed port %s",
current->comm, current->pid,
- info->smd->port_name);
+ info->ch_name);
tty->driver_data = NULL;
del_timer(&info->buf_req_timer);
@@ -513,7 +528,7 @@
if (len > avail)
len = avail;
SMD_TTY_INFO("[WRITE]: PID %u -> port %s %x bytes",
- current->pid, info->smd->port_name, len);
+ current->pid, info->ch_name, len);
return smd_write(info->ch, buf, len);
}
@@ -613,18 +628,15 @@
static int smd_tty_dummy_probe(struct platform_device *pdev)
{
int n;
- int idx;
- for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
- idx = smd_configs[n].tty_dev_index;
-
- if (!smd_configs[n].dev_name)
+ for (n = 0; n < MAX_SMD_TTYS; ++n) {
+ if (!smd_tty[n].dev_name)
continue;
- if (pdev->id == smd_configs[n].edge &&
- !strncmp(pdev->name, smd_configs[n].dev_name,
+ if (pdev->id == smd_tty[n].edge &&
+ !strncmp(pdev->name, smd_tty[n].dev_name,
SMD_MAX_CH_NAME_LEN)) {
- complete_all(&smd_tty[idx].ch_allocated);
+ complete_all(&smd_tty[n].ch_allocated);
return 0;
}
}
@@ -649,14 +661,10 @@
static struct tty_driver *smd_tty_driver;
-static int __init smd_tty_init(void)
+static int smd_tty_register_driver(void)
{
int ret;
- int n;
- int idx;
- struct tty_port *port;
- smd_tty_log_init();
smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
if (smd_tty_driver == 0) {
SMD_TTY_ERR("%s - Driver allocation failed", __func__);
@@ -683,14 +691,63 @@
if (ret) {
put_tty_driver(smd_tty_driver);
SMD_TTY_ERR("%s: driver registration failed %d", __func__, ret);
+ }
+
+ return ret;
+}
+
+static int smd_tty_device_init(int idx)
+{
+ int ret;
+ struct tty_port *port;
+
+ port = &smd_tty[idx].port;
+ tty_port_init(port);
+ port->ops = &smd_tty_port_ops;
+ /* TODO: For kernel >= 3.7 use tty_port_register_device */
+ smd_tty[idx].device_ptr = tty_register_device(smd_tty_driver, idx, 0);
+ init_completion(&smd_tty[idx].ch_allocated);
+
+ /* register platform device */
+ smd_tty[idx].driver.probe = smd_tty_dummy_probe;
+ smd_tty[idx].driver.driver.name = smd_tty[idx].dev_name;
+ smd_tty[idx].driver.driver.owner = THIS_MODULE;
+ spin_lock_init(&smd_tty[idx].reset_lock);
+ spin_lock_init(&smd_tty[idx].ra_lock);
+ smd_tty[idx].is_open = 0;
+ setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
+ (unsigned long)&smd_tty[idx]);
+ init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
+ ret = platform_driver_register(&smd_tty[idx].driver);
+
+ return ret;
+}
+
+static int __init smd_tty_core_init(void)
+{
+ int ret;
+ int n;
+ int idx;
+
+ ret = smd_tty_register_driver();
+ if (ret) {
+ pr_err("%s: driver registration failed %d\n", __func__, ret);
return ret;
}
for (n = 0; n < ARRAY_SIZE(smd_configs); ++n) {
idx = smd_configs[n].tty_dev_index;
+ smd_tty[idx].edge = smd_configs[n].edge;
- if (smd_configs[n].dev_name == NULL)
- smd_configs[n].dev_name = smd_configs[n].port_name;
+ strlcpy(smd_tty[idx].ch_name, smd_configs[n].port_name,
+ SMD_MAX_CH_NAME_LEN);
+ if (smd_configs[n].dev_name == NULL) {
+ strlcpy(smd_tty[idx].dev_name, smd_tty[idx].ch_name,
+ SMD_MAX_CH_NAME_LEN);
+ } else {
+ strlcpy(smd_tty[idx].dev_name, smd_configs[n].dev_name,
+ SMD_MAX_CH_NAME_LEN);
+ }
if (idx == DS_IDX) {
/*
@@ -713,39 +770,19 @@
continue;
}
- port = &smd_tty[idx].port;
- tty_port_init(port);
- port->ops = &smd_tty_port_ops;
- /* TODO: For kernel >= 3.7 use tty_port_register_device */
- smd_tty[idx].device_ptr =
- tty_register_device(smd_tty_driver, idx, 0);
+ ret = smd_tty_device_init(idx);
if (device_create_file(smd_tty[idx].device_ptr,
&dev_attr_open_timeout))
SMD_TTY_ERR(
"%s: Unable to create device attributes for %s",
__func__, smd_configs[n].port_name);
- init_completion(&smd_tty[idx].ch_allocated);
-
- /* register platform device */
- smd_tty[idx].driver.probe = smd_tty_dummy_probe;
- smd_tty[idx].driver.driver.name = smd_configs[n].dev_name;
- smd_tty[idx].driver.driver.owner = THIS_MODULE;
- spin_lock_init(&smd_tty[idx].reset_lock);
- spin_lock_init(&smd_tty[idx].ra_lock);
- smd_tty[idx].is_open = 0;
- setup_timer(&smd_tty[idx].buf_req_timer, buf_req_retry,
- (unsigned long)&smd_tty[idx]);
- init_waitqueue_head(&smd_tty[idx].ch_opened_wait_queue);
- ret = platform_driver_register(&smd_tty[idx].driver);
-
if (ret) {
SMD_TTY_ERR(
"%s: init failed %d (%d)", __func__, idx, ret);
smd_tty[idx].driver.probe = NULL;
goto out;
}
- smd_tty[idx].smd = &smd_configs[n];
}
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
return 0;
@@ -766,4 +803,155 @@
return ret;
}
+static int __init smd_tty_devicetree_init(struct platform_device *pdev)
+{
+ int ret;
+ int idx;
+ int edge;
+ char *key;
+ const char *ch_name;
+ const char *dev_name;
+ const char *remote_ss;
+ struct device_node *node;
+
+ ret = smd_tty_register_driver();
+ if (ret) {
+ SMD_TTY_ERR("%s: driver registration failed %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ for_each_child_of_node(pdev->dev.of_node, node) {
+
+ ret = of_alias_get_id(node, "smd");
+ SMD_TTY_INFO("%s:adding smd%d\n", __func__, ret);
+
+ if (ret < 0 || ret >= MAX_SMD_TTYS)
+ goto error;
+ idx = ret;
+
+ key = "qcom,smdtty-remote";
+ remote_ss = of_get_property(node, key, NULL);
+ if (!remote_ss)
+ goto error;
+
+ edge = smd_remote_ss_to_edge(remote_ss);
+ if (edge < 0)
+ goto error;
+ smd_tty[idx].edge = edge;
+
+ key = "qcom,smdtty-port-name";
+ ch_name = of_get_property(node, key, NULL);
+ if (!ch_name)
+ goto error;
+ strlcpy(smd_tty[idx].ch_name, ch_name,
+ SMD_MAX_CH_NAME_LEN);
+
+ key = "qcom,smdtty-dev-name";
+ dev_name = of_get_property(node, key, NULL);
+ if (!dev_name) {
+ strlcpy(smd_tty[idx].dev_name, smd_tty[idx].ch_name,
+ SMD_MAX_CH_NAME_LEN);
+ } else {
+ strlcpy(smd_tty[idx].dev_name, dev_name,
+ SMD_MAX_CH_NAME_LEN);
+ }
+
+ ret = smd_tty_device_init(idx);
+ if (ret) {
+ SMD_TTY_ERR("%s: init failed %d (%d)\n", __func__,
+ idx, ret);
+ smd_tty[idx].driver.probe = NULL;
+ goto error;
+ }
+ }
+ INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
+
+ return 0;
+
+error:
+ SMD_TTY_ERR("%s: unregister platform device\n", __func__);
+ /*Unregister platform devices*/
+ for_each_child_of_node(pdev->dev.of_node, node) {
+
+ key = "qcom,smdtty-dev-idx";
+ ret = of_property_read_u32(node, key, &idx);
+ if (ret || idx >= MAX_SMD_TTYS)
+ goto out;
+
+ if (smd_tty[idx].driver.probe) {
+ platform_driver_unregister(&smd_tty[idx].driver);
+ tty_unregister_device(smd_tty_driver, idx);
+ }
+ }
+out:
+ tty_unregister_driver(smd_tty_driver);
+ put_tty_driver(smd_tty_driver);
+ return ret;
+}
+
+static int __devinit msm_smd_tty_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (pdev) {
+ if (pdev->dev.of_node) {
+ ret = smd_tty_devicetree_init(pdev);
+ if (ret) {
+ SMD_TTY_ERR("%s: device tree init failed\n",
+ __func__);
+ return ret;
+ }
+ }
+ }
+
+ smd_tty_probe_done = 1;
+ return 0;
+}
+
+static void smd_tty_probe_worker(struct work_struct *work)
+{
+ int ret;
+ if (!smd_tty_probe_done) {
+ ret = smd_tty_core_init();
+ if (ret < 0)
+ SMD_TTY_ERR("smd_tty_core_init failed ret = %d\n", ret);
+ }
+
+}
+
+static struct of_device_id msm_smd_tty_match_table[] = {
+ { .compatible = "qcom,smdtty" },
+ {},
+};
+
+static struct platform_driver msm_smd_tty_driver = {
+ .probe = msm_smd_tty_probe,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_smd_tty_match_table,
+ },
+};
+
+
+static int __init smd_tty_init(void)
+{
+ int rc;
+
+ smd_tty_log_init();
+ rc = platform_driver_register(&msm_smd_tty_driver);
+ if (rc) {
+ SMD_TTY_ERR("%s: msm_smd_tty_driver register failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ INIT_DELAYED_WORK(&smd_tty_probe_work, smd_tty_probe_worker);
+ schedule_delayed_work(&smd_tty_probe_work,
+ msecs_to_jiffies(SMD_TTY_PROBE_WAIT_TIMEOUT));
+
+ return 0;
+}
+
module_init(smd_tty_init);
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index a24fc54..aa88b37 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -350,19 +350,21 @@
bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
"i: %3d, cmd_code: %4x, subsys_id: %4x, "
"client: %2d, cmd_code_lo: %4x, "
- "cmd_code_hi: %4x, process_id: %5d\n",
+ "cmd_code_hi: %4x, process_id: %5d %s\n",
i,
driver->table[i].cmd_code,
driver->table[i].subsys_id,
driver->table[i].client_id,
driver->table[i].cmd_code_lo,
driver->table[i].cmd_code_hi,
- driver->table[i].process_id);
+ driver->table[i].process_id,
+ (diag_find_polling_reg(i) ? "<- Polling cmd reg" : ""));
bytes_in_buffer += bytes_written;
/* Check if there is room to add another table entry */
bytes_remaining = buf_size - bytes_in_buffer;
+
if (bytes_remaining < bytes_written)
break;
}
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c91095e..9c27180 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -19,12 +19,15 @@
#include "diagfwd_cntl.h"
#include "diag_masks.h"
-int diag_event_config;
int diag_event_num_bytes;
+#define DIAG_CTRL_MASK_INVALID 0
+#define DIAG_CTRL_MASK_ALL_DISABLED 1
+#define DIAG_CTRL_MASK_ALL_ENABLED 2
+#define DIAG_CTRL_MASK_VALID 3
+
#define ALL_EQUIP_ID 100
#define ALL_SSID -1
-#define MAX_SSID_PER_RANGE 100
#define FEATURE_MASK_LEN_BYTES 2
@@ -106,6 +109,8 @@
uint8_t *parse_ptr, *ptr = driver->msg_masks;
mutex_lock(&driver->diagchar_mutex);
+ driver->msg_status = rt_mask ? DIAG_CTRL_MASK_ALL_ENABLED :
+ DIAG_CTRL_MASK_ALL_DISABLED;
while (*(uint32_t *)(ptr + 4)) {
first_ssid = *(uint32_t *)ptr;
ptr += 8; /* increment by 8 to skip 'last' */
@@ -129,9 +134,9 @@
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 */
while (*(uint32_t *)(ptr + 4)) {
first = *(uint32_t *)ptr;
@@ -148,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;
@@ -177,6 +190,7 @@
} else
pr_alert("diag: Not enough buffer space for MSG_MASK\n");
}
+ driver->msg_status = DIAG_CTRL_MASK_VALID;
mutex_unlock(&driver->diagchar_mutex);
diag_print_mask_table();
}
@@ -186,28 +200,29 @@
uint8_t *ptr = driver->event_masks;
mutex_lock(&driver->diagchar_mutex);
- if (toggle)
+ if (toggle) {
+ driver->event_status = DIAG_CTRL_MASK_ALL_ENABLED;
memset(ptr, 0xFF, EVENT_MASK_SIZE);
- else
+ } else {
+ driver->event_status = DIAG_CTRL_MASK_ALL_DISABLED;
memset(ptr, 0, EVENT_MASK_SIZE);
+ }
mutex_unlock(&driver->diagchar_mutex);
}
-static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
+static void diag_update_event_mask(uint8_t *buf, int num_bytes)
{
uint8_t *ptr = driver->event_masks;
uint8_t *temp = buf + 2;
mutex_lock(&driver->diagchar_mutex);
- if (!toggle)
- memset(ptr, 0 , EVENT_MASK_SIZE);
- else
- if (CHK_OVERFLOW(ptr, ptr,
- ptr+EVENT_MASK_SIZE, num_bytes))
- memcpy(ptr, temp , num_bytes);
- else
- printk(KERN_CRIT "Not enough buffer space for EVENT_MASK\n");
+ if (CHK_OVERFLOW(ptr, ptr, ptr+EVENT_MASK_SIZE, num_bytes)) {
+ memcpy(ptr, temp, num_bytes);
+ driver->event_status = DIAG_CTRL_MASK_VALID;
+ } else {
+ pr_err("diag: In %s, not enough buffer space\n", __func__);
+ }
mutex_unlock(&driver->diagchar_mutex);
}
@@ -226,6 +241,7 @@
(parse_ptr->num_items + 7)/8);
parse_ptr++;
}
+ driver->log_status = DIAG_CTRL_MASK_ALL_DISABLED;
mutex_unlock(&driver->diagchar_mutex);
}
@@ -282,10 +298,13 @@
}
ptr_data = driver->log_masks + offset;
if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
- + LOG_MASK_SIZE, (num_items+7)/8))
- memcpy(ptr_data, temp , (num_items+7)/8);
- else
+ + LOG_MASK_SIZE, (num_items+7)/8)) {
+ memcpy(ptr_data, temp, (num_items+7)/8);
+ driver->log_status = DIAG_CTRL_MASK_VALID;
+ } else {
pr_err("diag: Not enough buffer space for LOG_MASK\n");
+ driver->log_status = DIAG_CTRL_MASK_INVALID;
+ }
mutex_unlock(&driver->diagchar_mutex);
}
@@ -300,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,
@@ -330,15 +349,36 @@
driver->log_mask->num_items = ptr->num_items;
driver->log_mask->data_len = 11 + size;
driver->log_mask->stream_id = 1; /* 2, if dual stream */
- driver->log_mask->status = 3; /* status for valid mask */
driver->log_mask->equip_id = ptr->equip_id;
- driver->log_mask->log_mask_size = size;
+ driver->log_mask->status = driver->log_status;
+ switch (driver->log_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->log_mask->log_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->log_mask->log_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_VALID:
+ driver->log_mask->log_mask_size = size;
+ break;
+ default:
+ /* Log status is not set or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->log_status);
+ driver->log_mask->status = DIAG_CTRL_MASK_INVALID;
+ }
+
+ if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
/* send only desired update, NOT ALL */
if (equip_id == ALL_EQUIP_ID || equip_id ==
driver->log_mask->equip_id) {
memcpy(buf, driver->log_mask, header_size);
- memcpy(buf+header_size, driver->log_masks+ptr->index,
- size);
+ if (driver->log_status == DIAG_CTRL_MASK_VALID)
+ memcpy(buf + header_size,
+ driver->log_masks+ptr->index, size);
if (ch) {
while (retry_count < 3) {
wr_size = smd_write(ch, buf,
@@ -380,11 +420,34 @@
driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
driver->event_mask->data_len = 7 + num_bytes;
driver->event_mask->stream_id = 1; /* 2, if dual stream */
- driver->event_mask->status = 3; /* status for valid mask */
- driver->event_mask->event_config = diag_event_config; /* event config */
- driver->event_mask->event_mask_size = num_bytes;
+ driver->event_mask->status = driver->event_status;
+
+ switch (driver->event_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->event_mask->event_config = 0;
+ driver->event_mask->event_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->event_mask->event_config = 1;
+ driver->event_mask->event_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_VALID:
+ driver->event_mask->event_config = 1;
+ driver->event_mask->event_mask_size = num_bytes;
+ memcpy(buf + header_size, driver->event_masks, num_bytes);
+ break;
+ default:
+ /* Event status is not set yet or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->event_status);
+ driver->event_mask->status = DIAG_CTRL_MASK_INVALID;
+ }
+
+ if (driver->event_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
memcpy(buf, driver->event_mask, header_size);
- memcpy(buf+header_size, driver->event_masks, num_bytes);
if (ch) {
while (retry_count < 3) {
wr_size = smd_write(ch, buf, header_size + num_bytes);
@@ -418,44 +481,78 @@
ptr += 4;
actual_last = *(uint32_t *)ptr;
ptr += 4;
- if ((updated_ssid_first >= first && updated_ssid_last <=
- actual_last) || (updated_ssid_first == ALL_SSID)) {
- /* send f3 mask update */
- driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
- driver->msg_mask->msg_mask_size = actual_last -
- first + 1;
- driver->msg_mask->data_len = 11 +
- 4 * (driver->msg_mask->msg_mask_size);
- driver->msg_mask->stream_id = 1; /* 2, if dual stream */
- driver->msg_mask->status = 3; /* status valid mask */
- driver->msg_mask->msg_mode = 0; /* Legcay mode */
- driver->msg_mask->ssid_first = first;
- driver->msg_mask->ssid_last = actual_last;
- memcpy(buf, driver->msg_mask, header_size);
+ if (!((updated_ssid_first >= first && updated_ssid_last <=
+ actual_last) || (updated_ssid_first == ALL_SSID))) {
+ ptr += MAX_SSID_PER_RANGE*4;
+ continue;
+ }
+ /* send f3 mask update */
+ driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
+ driver->msg_mask->status = driver->msg_status;
+ switch (driver->msg_status) {
+ case DIAG_CTRL_MASK_ALL_DISABLED:
+ driver->msg_mask->msg_mask_size = 0;
+ break;
+ case DIAG_CTRL_MASK_ALL_ENABLED:
+ driver->msg_mask->msg_mask_size = 1;
memcpy(buf+header_size, ptr,
4 * (driver->msg_mask->msg_mask_size));
- if (ch) {
- while (retry_count < 3) {
- size = smd_write(ch, buf, header_size +
- 4*(driver->msg_mask->msg_mask_size));
- if (size == -ENOMEM) {
- retry_count++;
- usleep_range(10000, 10100);
- } else
- break;
- }
- if (size != header_size +
- 4*(driver->msg_mask->msg_mask_size))
- pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
- proc, size, (header_size +
- 4*(driver->msg_mask->msg_mask_size)));
- else
- pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
- first, actual_last, proc);
- } else
- pr_err("diag: proc %d, ch invalid msg mask update\n",
- proc);
+ break;
+ 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;
+ default:
+ /* Msg status is not set or the buffer is corrupted */
+ pr_err("diag: In %s, invalid status %d", __func__,
+ driver->msg_status);
+ driver->msg_mask->status = DIAG_CTRL_MASK_INVALID;
}
+
+ if (driver->msg_mask->status == DIAG_CTRL_MASK_INVALID) {
+ mutex_unlock(&driver->diag_cntl_mutex);
+ return;
+ }
+ driver->msg_mask->data_len = 11 +
+ 4 * (driver->msg_mask->msg_mask_size);
+ driver->msg_mask->stream_id = 1; /* 2, if dual stream */
+ driver->msg_mask->msg_mode = 0; /* Legcay mode */
+ driver->msg_mask->ssid_first = first;
+ driver->msg_mask->ssid_last = actual_last;
+ memcpy(buf, driver->msg_mask, header_size);
+ if (ch) {
+ while (retry_count < 3) {
+ size = smd_write(ch, buf, header_size +
+ 4*(driver->msg_mask->msg_mask_size));
+ if (size == -ENOMEM) {
+ retry_count++;
+ usleep_range(10000, 10100);
+ } else
+ break;
+ }
+ if (size != header_size +
+ 4*(driver->msg_mask->msg_mask_size))
+ pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
+ proc, size, (header_size +
+ 4*(driver->msg_mask->msg_mask_size)));
+ else
+ pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
+ first, actual_last, proc);
+ } else
+ pr_err("diag: proc %d, ch invalid msg mask update\n",
+ proc);
ptr += MAX_SSID_PER_RANGE*4;
}
mutex_unlock(&driver->diag_cntl_mutex);
@@ -706,8 +803,8 @@
#endif
} else if (*buf == 0x82) { /* event mask change */
buf += 4;
- diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
- diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
+ diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
+ diag_update_event_mask(buf, diag_event_num_bytes);
diag_update_userspace_clients(EVENT_MASKS_TYPE);
#if defined(CONFIG_DIAG_OVER_USB)
if (chk_apps_only()) {
@@ -729,7 +826,6 @@
}
#endif
} else if (*buf == 0x60) {
- diag_event_config = *(buf+1);
diag_toggle_event_mask(*(buf+1));
diag_update_userspace_clients(EVENT_MASKS_TYPE);
#if defined(CONFIG_DIAG_OVER_USB)
@@ -764,6 +860,10 @@
void diag_masks_init(void)
{
+ driver->event_status = DIAG_CTRL_MASK_INVALID;
+ driver->msg_status = DIAG_CTRL_MASK_INVALID;
+ driver->log_status = DIAG_CTRL_MASK_INVALID;
+
if (driver->event_mask == NULL) {
driver->event_mask = kzalloc(sizeof(
struct diag_ctrl_event_mask), GFP_KERNEL);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 7ef1d80..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
@@ -362,9 +370,12 @@
struct work_struct diag_drain_work;
struct workqueue_struct *diag_cntl_wq;
uint8_t *msg_masks;
+ uint8_t msg_status;
uint8_t *log_masks;
+ uint8_t log_status;
int log_masks_length;
uint8_t *event_masks;
+ uint8_t event_status;
uint8_t log_on_demand_support;
struct diag_master_table *table;
uint8_t *pkt_buf;
@@ -412,5 +423,6 @@
extern uint16_t wrap_count;
void diag_get_timestamp(char *time_str);
+int diag_find_polling_reg(int i);
#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 24d7fac..6cc18da 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -327,17 +327,19 @@
subsys_id = driver->table[i].subsys_id;
cmd_code_lo = driver->table[i].cmd_code_lo;
cmd_code_hi = driver->table[i].cmd_code_hi;
- if (driver->table[i].cmd_code == 0x0C)
- return 1;
- else if (driver->table[i].cmd_code == 0xFF) {
- if (subsys_id == 0x04 && cmd_code_hi == 0x0E &&
- cmd_code_lo == 0x0E)
+
+ if (driver->table[i].cmd_code == 0xFF) {
+ if (subsys_id == 0xFF && cmd_code_hi >= 0x0C &&
+ cmd_code_lo <= 0x0C)
return 1;
- else if (subsys_id == 0x08 && cmd_code_hi == 0x02 &&
- cmd_code_lo == 0x02)
+ if (subsys_id == 0x04 && cmd_code_hi >= 0x0E &&
+ cmd_code_lo <= 0x0E)
return 1;
- else if (subsys_id == 0x32 && cmd_code_hi == 0x03 &&
- cmd_code_lo == 0x03)
+ else if (subsys_id == 0x08 && cmd_code_hi >= 0x02 &&
+ cmd_code_lo <= 0x02)
+ return 1;
+ else if (subsys_id == 0x32 && cmd_code_hi >= 0x03 &&
+ cmd_code_lo <= 0x03)
return 1;
}
return 0;
@@ -356,7 +358,8 @@
}
/* re-scan the registration table */
for (i = 0; i < diag_max_reg; i++) {
- if (diag_find_polling_reg(i) == 1) {
+ if (driver->table[i].process_id != 0 &&
+ diag_find_polling_reg(i) == 1) {
driver->polling_reg_flag = 1;
break;
}
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/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 3115628..3d18809 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -84,6 +84,7 @@
{SDC1_HDRV_PULL_CTL, 13}, /* TLMM_PULL_SDC1_CLK */
{SDC1_HDRV_PULL_CTL, 11}, /* TLMM_PULL_SDC1_CMD */
{SDC1_HDRV_PULL_CTL, 9}, /* TLMM_PULL_SDC1_DATA */
+ {SDC1_HDRV_PULL_CTL, 15}, /* TLMM_PULL_SDC1_RCLK */
};
/*
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/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 83b2aa1..6044512 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -41,22 +41,23 @@
#define FT_SUSPEND_LEVEL 1
#endif
-#define CFG_MAX_TOUCH_POINTS 5
+#define FT_DRIVER_VERSION 0x01
-#define FT_STARTUP_DLY 150
-#define FT_RESET_DLY 20
+#define FT_META_REGS 3
+#define FT_ONE_TCH_LEN 6
+#define FT_TCH_LEN(x) (FT_META_REGS + FT_ONE_TCH_LEN * x)
#define FT_PRESS 0x7F
#define FT_MAX_ID 0x0F
-#define FT_TOUCH_STEP 6
#define FT_TOUCH_X_H_POS 3
#define FT_TOUCH_X_L_POS 4
#define FT_TOUCH_Y_H_POS 5
#define FT_TOUCH_Y_L_POS 6
+#define FT_TD_STATUS 2
#define FT_TOUCH_EVENT_POS 3
#define FT_TOUCH_ID_POS 5
-
-#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
+#define FT_TOUCH_DOWN 0
+#define FT_TOUCH_CONTACT 2
/*register address*/
#define FT_REG_DEV_MODE 0x00
@@ -104,55 +105,6 @@
#define FT_UPGRADE_AA 0xAA
#define FT_UPGRADE_55 0x55
-/*upgrade config of FT5606*/
-#define FT5606_UPGRADE_AA_DELAY 50
-#define FT5606_UPGRADE_55_DELAY 10
-#define FT5606_UPGRADE_ID_1 0x79
-#define FT5606_UPGRADE_ID_2 0x06
-#define FT5606_UPGRADE_READID_DELAY 100
-#define FT5606_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT5316*/
-#define FT5316_UPGRADE_AA_DELAY 50
-#define FT5316_UPGRADE_55_DELAY 30
-#define FT5316_UPGRADE_ID_1 0x79
-#define FT5316_UPGRADE_ID_2 0x07
-#define FT5316_UPGRADE_READID_DELAY 1
-#define FT5316_UPGRADE_EARSE_DELAY 1500
-
-/*upgrade config of FT5x06(x=2,3,4)*/
-#define FT5X06_UPGRADE_AA_DELAY 50
-#define FT5X06_UPGRADE_55_DELAY 30
-#define FT5X06_UPGRADE_ID_1 0x79
-#define FT5X06_UPGRADE_ID_2 0x03
-#define FT5X06_UPGRADE_READID_DELAY 1
-#define FT5X06_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT6208*/
-#define FT6208_UPGRADE_AA_DELAY 60
-#define FT6208_UPGRADE_55_DELAY 10
-#define FT6208_UPGRADE_ID_1 0x79
-#define FT6208_UPGRADE_ID_2 0x05
-#define FT6208_UPGRADE_READID_DELAY 10
-#define FT6208_UPGRADE_EARSE_DELAY 2000
-
-/*upgrade config of FT6x06*/
-#define FT6X06_UPGRADE_AA_DELAY 100
-#define FT6X06_UPGRADE_55_DELAY 30
-#define FT6X06_UPGRADE_ID_1 0x79
-#define FT6X06_UPGRADE_ID_2 0x08
-#define FT6X06_UPGRADE_READID_DELAY 10
-#define FT6X06_UPGRADE_EARSE_DELAY 2000
-
-#define FT_UPGRADE_INFO(x, y) do { \
- x->delay_55 = y##_UPGRADE_55_DELAY; \
- x->delay_aa = y##_UPGRADE_AA_DELAY; \
- x->upgrade_id_1 = y##_UPGRADE_ID_1; \
- x->upgrade_id_2 = y##_UPGRADE_ID_2; \
- x->delay_readid = y##_UPGRADE_READID_DELAY; \
- x->delay_earse_flash = y##_UPGRADE_EARSE_DELAY; \
- } while (0)
-
#define FT_FW_MIN_SIZE 8
#define FT_FW_MAX_SIZE 32768
#define FT_FW_FILE_VER(x) ((x)->data[(x)->size - 2])
@@ -180,39 +132,26 @@
#define FT_REG_CAL 0x00
#define FT_CAL_MASK 0x70
-#define FT_INFO_MAX_LEN 200
+#define FT_INFO_MAX_LEN 512
-#define FT_STORE_TS_INFO(buf, id, fw_ver) \
+#define FT_STORE_TS_INFO(buf, id, name, max_tch, group_id, fw_name, fw_ver) \
snprintf(buf, FT_INFO_MAX_LEN, \
"controller\t= focaltech\n" \
"model\t\t= 0x%x\n" \
- "fw_ver\t\t= 0x%x\n", id, fw_ver)
+ "name\t\t= %s\n" \
+ "max_touches\t= %d\n" \
+ "drv_ver\t\t= 0x%x\n" \
+ "group_id\t= 0x%x\n" \
+ "fw_name\t\t= %s\n" \
+ "fw_ver\t\t= 0x%x\n", id, name, \
+ max_tch, FT_DRIVER_VERSION, group_id, \
+ fw_name, fw_ver)
#define FT_DEBUG_DIR_NAME "ts_debug"
-struct ts_event {
- u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
- u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
- /* touch event: 0 -- down; 1-- contact; 2 -- contact */
- u8 touch_event[CFG_MAX_TOUCH_POINTS];
- u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
- u16 pressure;
- u8 touch_point;
-};
-
-struct upgrade_info {
- u16 delay_aa; /*delay of write FT_UPGRADE_AA */
- u16 delay_55; /*delay of write FT_UPGRADE_55 */
- u8 upgrade_id_1; /*upgrade id 1 */
- u8 upgrade_id_2; /*upgrade id 2 */
- u16 delay_readid; /*delay of read id */
- u16 delay_earse_flash; /*delay of earse flash*/
-};
-
struct ft5x06_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
- struct ts_event event;
const struct ft5x06_ts_platform_data *pdata;
struct regulator *vdd;
struct regulator *vcc_i2c;
@@ -223,6 +162,8 @@
u16 addr;
bool suspended;
char *ts_info;
+ u8 *tch_data;
+ u32 tch_data_len;
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -305,88 +246,65 @@
return ft5x06_i2c_read(client, &addr, 1, val, 1);
}
-static void ft5x06_report_value(struct ft5x06_ts_data *data)
-{
- struct ts_event *event = &data->event;
- int i;
- int fingerdown = 0;
-
- for (i = 0; i < event->touch_point; i++) {
- if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
- event->pressure = FT_PRESS;
- fingerdown++;
- } else {
- event->pressure = 0;
- }
-
- input_mt_slot(data->input_dev, event->finger_id[i]);
- input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER,
- !!event->pressure);
-
- if (event->pressure == FT_PRESS) {
- input_report_abs(data->input_dev, ABS_MT_POSITION_X,
- event->x[i]);
- input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
- event->y[i]);
- input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
- event->pressure);
- }
- }
-
- input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
- input_sync(data->input_dev);
-}
-
-static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
-{
- struct ts_event *event = &data->event;
- int num_points;
- int ret, i;
- u8 buf[POINT_READ_BUF] = { 0 };
- u8 pointid = FT_MAX_ID;
-
- ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
- if (ret < 0) {
- dev_err(&data->client->dev, "%s read touchdata failed.\n",
- __func__);
- return ret;
- }
- memset(event, 0, sizeof(struct ts_event));
-
- event->touch_point = 0;
- num_points = buf[2] & FT_STATUS_NUM_TP_MASK;
-
- for (i = 0; i < num_points; i++) {
- pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
- if (pointid >= FT_MAX_ID)
- break;
- else
- event->touch_point++;
- event->x[i] =
- (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
- 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
- event->y[i] =
- (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
- 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
- event->touch_event[i] =
- buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
- event->finger_id[i] =
- (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
- }
-
- ft5x06_report_value(data);
-
- return 0;
-}
-
static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
{
struct ft5x06_ts_data *data = dev_id;
- int rc;
+ struct input_dev *ip_dev;
+ int rc, i;
+ u32 id, x, y, pressure, status, num_touches;
+ u8 reg = 0x00, *buf;
+ bool update_input = false;
- rc = ft5x06_handle_touchdata(data);
- if (rc)
- pr_err("%s: handling touchdata failed\n", __func__);
+ if (!data) {
+ pr_err("%s: Invalid data\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ ip_dev = data->input_dev;
+ buf = data->tch_data;
+
+ rc = ft5x06_i2c_read(data->client, ®, 1,
+ buf, data->tch_data_len);
+ if (rc < 0) {
+ dev_err(&data->client->dev, "%s: read data fail\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
+ id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
+ if (id >= FT_MAX_ID)
+ break;
+
+ update_input = true;
+
+ x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
+ y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+ (buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
+
+ status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
+
+ num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
+
+ /* invalid combination */
+ if (!num_touches && !status && !id)
+ break;
+
+ input_mt_slot(ip_dev, id);
+ if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
+ pressure = FT_PRESS;
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
+ input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
+ input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure);
+ } else
+ input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+ }
+
+ if (update_input) {
+ input_mt_report_pointer_emulation(ip_dev, false);
+ input_sync(ip_dev);
+ }
return IRQ_HANDLED;
}
@@ -519,7 +437,7 @@
disable_irq(data->client->irq);
/* release all touches */
- for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
+ for (i = 0; i < data->pdata->num_max_touches; i++) {
input_mt_slot(data->input_dev, i);
input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
}
@@ -553,7 +471,7 @@
pwr_off_fail:
if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
enable_irq(data->client->irq);
@@ -566,7 +484,7 @@
int err;
if (!data->suspended) {
- dev_info(dev, "Already in awake state\n");
+ dev_dbg(dev, "Already in awake state\n");
return 0;
}
@@ -586,11 +504,11 @@
if (gpio_is_valid(data->pdata->reset_gpio)) {
gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
enable_irq(data->client->irq);
@@ -649,16 +567,17 @@
static int ft5x06_auto_cal(struct i2c_client *client)
{
+ struct ft5x06_ts_data *data = i2c_get_clientdata(client);
u8 temp = 0, i;
/* set to factory mode */
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* start calibration */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
for (i = 0; i < FT_CAL_RETRY; i++) {
ft5x0x_read_reg(client, FT_REG_CAL, &temp);
/*return to normal mode, calibration finish */
@@ -667,36 +586,17 @@
}
/*calibration OK */
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* store calibration data */
ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
- msleep(2 * FT_STARTUP_DLY);
+ msleep(2 * data->pdata->soft_rst_dly);
/* set to normal mode */
ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
- msleep(2 * FT_STARTUP_DLY);
-
- return 0;
-}
-
-static int ft5x06_get_upgrade_info(u8 family_id, struct upgrade_info *info)
-{
- switch (family_id) {
- case FT5306I_ID:
- FT_UPGRADE_INFO(info, FT5X06);
- break;
- case FT5316_ID:
- FT_UPGRADE_INFO(info, FT5316);
- break;
- case FT6X06_ID:
- FT_UPGRADE_INFO(info, FT6X06);
- break;
- default:
- return -EINVAL;
- }
+ msleep(2 * data->pdata->soft_rst_dly);
return 0;
}
@@ -705,7 +605,7 @@
const u8 *data, u32 data_len)
{
struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
- struct upgrade_info info;
+ struct fw_upgrade_info info = ts_data->pdata->info;
u8 reset_reg;
u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
@@ -713,12 +613,6 @@
u32 pkt_num, pkt_len;
u8 fw_ecc;
- rc = ft5x06_get_upgrade_info(ts_data->family_id, &info);
- if (rc < 0) {
- dev_err(&client->dev, "Cannot get upgrade information!\n");
- return -EINVAL;
- }
-
for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
/* reset - write 0xaa and 0x55 to reset register */
if (ts_data->family_id == FT6X06_ID)
@@ -765,7 +659,7 @@
/* erase app and panel paramenter area */
w_buf[0] = FT_ERASE_APP_REG;
ft5x06_i2c_write(client, w_buf, 1);
- msleep(info.delay_earse_flash);
+ msleep(info.delay_erase_flash);
w_buf[0] = FT_ERASE_PANEL_REG;
ft5x06_i2c_write(client, w_buf, 1);
@@ -840,7 +734,7 @@
/* reset */
w_buf[0] = FT_REG_RESET_FW;
ft5x06_i2c_write(client, w_buf, 1);
- msleep(FT_STARTUP_DLY);
+ msleep(ts_data->pdata->soft_rst_dly);
dev_info(&client->dev, "Firmware upgrade successful\n");
@@ -888,14 +782,16 @@
rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
if (rc < 0)
dev_err(dev, "update failed (%d)\n", rc);
- else
+ else if (data->pdata->info.auto_cal)
ft5x06_auto_cal(data->client);
} else {
dev_err(dev, "FW format error\n");
rc = -EIO;
}
- FT_STORE_TS_INFO(data->ts_info, data->family_id, FT_FW_FILE_VER(fw));
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_name, FT_FW_FILE_VER(fw));
rel_fw:
release_firmware(fw);
return rc;
@@ -1177,6 +1073,13 @@
u32 temp_val, num_buttons;
u32 button_map[MAX_BUTTONS];
+ pdata->name = "focaltech";
+ rc = of_property_read_string(np, "focaltech,name", &pdata->name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read name\n");
+ return rc;
+ }
+
rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
if (rc && (rc != -EINVAL))
return rc;
@@ -1201,6 +1104,86 @@
if (pdata->irq_gpio < 0)
return pdata->irq_gpio;
+ pdata->fw_name = "ft_fw.bin";
+ rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw name\n");
+ return rc;
+ }
+
+ rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
+ if (!rc)
+ pdata->group_id = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->hard_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
+ &temp_val);
+ if (!rc)
+ pdata->soft_rst_dly = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
+ if (!rc)
+ pdata->num_max_touches = temp_val;
+ else
+ return rc;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay aa\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_aa = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay 55\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_55 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id1\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_1 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw upgrade id2\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.upgrade_id_2 = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay read id\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_readid = temp_val;
+
+ rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
+ &temp_val);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw delay erase flash\n");
+ return rc;
+ } else if (rc != -EINVAL)
+ pdata->info.delay_erase_flash = temp_val;
+
+ pdata->info.auto_cal = of_property_read_bool(np,
+ "focaltech,fw-auto-cal");
+
rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
if (!rc)
pdata->family_id = temp_val;
@@ -1241,7 +1224,7 @@
struct dentry *temp;
u8 reg_value;
u8 reg_addr;
- int err;
+ int err, len;
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev,
@@ -1252,8 +1235,10 @@
}
err = ft5x06_parse_dt(&client->dev, pdata);
- if (err)
+ if (err) {
+ dev_err(&client->dev, "DT parsing failed\n");
return err;
+ }
} else
pdata = client->dev.platform_data;
@@ -1267,7 +1252,26 @@
return -ENODEV;
}
- data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ data = devm_kzalloc(&client->dev,
+ sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Not enough memory\n");
+ return -ENOMEM;
+ }
+
+ if (pdata->fw_name) {
+ len = strlen(pdata->fw_name);
+ if (len > FT_FW_NAME_MAX_LEN - 1) {
+ dev_err(&client->dev, "Invalid firmware name\n");
+ return -EINVAL;
+ }
+
+ strlcpy(data->fw_name, pdata->fw_name, len + 1);
+ }
+
+ data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
+ data->tch_data = devm_kzalloc(&client->dev,
+ data->tch_data_len, GFP_KERNEL);
if (!data) {
dev_err(&client->dev, "Not enough memory\n");
return -ENOMEM;
@@ -1275,9 +1279,8 @@
input_dev = input_allocate_device();
if (!input_dev) {
- err = -ENOMEM;
dev_err(&client->dev, "failed to allocate input device\n");
- goto free_mem;
+ return -ENOMEM;
}
data->input_dev = input_dev;
@@ -1296,12 +1299,12 @@
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
- input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS);
+ input_mt_init_slots(input_dev, pdata->num_max_touches);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
pdata->y_max, 0, 0);
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
err = input_register_device(input_dev);
if (err) {
@@ -1364,12 +1367,12 @@
"set_direction for reset gpio failed\n");
goto free_reset_gpio;
}
- msleep(FT_RESET_DLY);
+ msleep(data->pdata->hard_rst_dly);
gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
}
/* make sure CTP already finish startup process */
- msleep(FT_STARTUP_DLY);
+ msleep(data->pdata->soft_rst_dly);
/* check the controller id */
reg_addr = FT_REG_ID;
@@ -1453,7 +1456,8 @@
goto free_debug_dir;
}
- data->ts_info = kzalloc(FT_INFO_MAX_LEN, GFP_KERNEL);
+ data->ts_info = devm_kzalloc(&client->dev,
+ FT_INFO_MAX_LEN, GFP_KERNEL);
if (!data->ts_info) {
dev_err(&client->dev, "Not enough memory\n");
goto free_debug_dir;
@@ -1481,7 +1485,9 @@
dev_info(&client->dev, "Firmware version = 0x%x\n", reg_value);
- FT_STORE_TS_INFO(data->ts_info, data->family_id, reg_value);
+ FT_STORE_TS_INFO(data->ts_info, data->family_id, data->pdata->name,
+ data->pdata->num_max_touches, data->pdata->group_id,
+ data->pdata->fw_name, reg_value);
#if defined(CONFIG_FB)
data->fb_notif.notifier_call = fb_notifier_callback;
@@ -1532,8 +1538,6 @@
input_dev = NULL;
free_inputdev:
input_free_device(input_dev);
-free_mem:
- kfree(data);
return err;
}
@@ -1571,8 +1575,6 @@
ft5x06_power_init(data, false);
input_unregister_device(data->input_dev);
- kfree(data->ts_info);
- kfree(data);
return 0;
}
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index ba0be2b..0b234ce 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -1056,6 +1056,10 @@
rmi4_pdata->i2c_pull_up = of_property_read_bool(np,
"synaptics,i2c-pull-up");
+ rmi4_pdata->power_down_enable = of_property_read_bool(np,
+ "synaptics,power-down");
+ rmi4_pdata->disable_gpios = of_property_read_bool(np,
+ "synaptics,disable-gpios");
rmi4_pdata->x_flip = of_property_read_bool(np, "synaptics,x-flip");
rmi4_pdata->y_flip = of_property_read_bool(np, "synaptics,y-flip");
@@ -2003,7 +2007,7 @@
error_reg_en_vcc_i2c:
if (rmi4_data->board->i2c_pull_up)
- reg_set_optimum_mode_check(rmi4_data->vdd, 0);
+ reg_set_optimum_mode_check(rmi4_data->vcc_i2c, 0);
error_reg_opt_i2c:
regulator_disable(rmi4_data->vdd);
error_reg_en_vdd:
@@ -2020,6 +2024,85 @@
return 0;
}
+static int synaptics_rmi4_gpio_configure(struct synaptics_rmi4_data *rmi4_data,
+ bool on)
+{
+ int retval = 0;
+
+ if (on) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(rmi4_data->board->irq_gpio,
+ "rmi4_irq_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_req;
+ }
+ retval = gpio_direction_input(rmi4_data->board->\
+ irq_gpio);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->irq_gpio);
+ goto err_irq_gpio_dir;
+ }
+ } else {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "irq gpio not provided\n");
+ goto err_irq_gpio_req;
+ }
+
+ if (gpio_is_valid(rmi4_data->board->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(rmi4_data->board->reset_gpio,
+ "rmi4_reset_gpio");
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to request gpio [%d]\n",
+ rmi4_data->board->reset_gpio);
+ goto err_irq_gpio_dir;
+ }
+
+ retval = gpio_direction_output(rmi4_data->board->\
+ reset_gpio, 1);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "unable to set direction for gpio " \
+ "[%d]\n", rmi4_data->board->reset_gpio);
+ goto err_reset_gpio_dir;
+ }
+
+ gpio_set_value(rmi4_data->board->reset_gpio, 0);
+ usleep(RMI4_GPIO_SLEEP_LOW_US);
+ gpio_set_value(rmi4_data->board->reset_gpio, 1);
+ msleep(RESET_DELAY);
+ } else
+ synaptics_rmi4_reset_command(rmi4_data);
+
+ return 0;
+ } else {
+ if (rmi4_data->board->disable_gpios) {
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ }
+
+ return 0;
+ }
+
+err_reset_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+err_irq_gpio_dir:
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_irq_gpio_req:
+ return retval;
+}
+
/**
* synaptics_rmi4_probe()
*
@@ -2149,52 +2232,12 @@
goto err_power_device;
}
- if (gpio_is_valid(platform_data->irq_gpio)) {
- /* configure touchscreen irq gpio */
- retval = gpio_request(platform_data->irq_gpio, "rmi4_irq_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_req;
- }
- retval = gpio_direction_input(platform_data->irq_gpio);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->irq_gpio);
- goto err_irq_gpio_dir;
- }
- } else {
- dev_err(&client->dev, "irq gpio not provided\n");
- goto err_irq_gpio_req;
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&client->dev, "Failed to configure gpios\n");
+ goto err_gpio_config;
}
- if (gpio_is_valid(platform_data->reset_gpio)) {
- /* configure touchscreen reset out gpio */
- retval = gpio_request(platform_data->reset_gpio,
- "rmi4_reset_gpio");
- if (retval) {
- dev_err(&client->dev, "unable to request gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_irq_gpio_dir;
- }
-
- retval = gpio_direction_output(platform_data->reset_gpio, 1);
- if (retval) {
- dev_err(&client->dev,
- "unable to set direction for gpio [%d]\n",
- platform_data->reset_gpio);
- goto err_reset_gpio_dir;
- }
-
- gpio_set_value(platform_data->reset_gpio, 0);
- usleep(RMI4_GPIO_SLEEP_LOW_US);
- gpio_set_value(platform_data->reset_gpio, 1);
- msleep(RESET_DELAY);
- } else
- synaptics_rmi4_reset_command(rmi4_data);
-
-
init_waitqueue_head(&rmi4_data->wait);
mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
@@ -2203,7 +2246,7 @@
dev_err(&client->dev,
"%s: Failed to query device\n",
__func__);
- goto err_reset_gpio_dir;
+ goto err_free_gpios;
}
input_set_abs_params(rmi4_data->input_dev,
@@ -2346,13 +2389,12 @@
kfree(fhandler);
}
}
-err_reset_gpio_dir:
- if (gpio_is_valid(platform_data->reset_gpio))
- gpio_free(platform_data->reset_gpio);
-err_irq_gpio_dir:
- if (gpio_is_valid(platform_data->irq_gpio))
- gpio_free(platform_data->irq_gpio);
-err_irq_gpio_req:
+err_free_gpios:
+ if (gpio_is_valid(rmi4_data->board->reset_gpio))
+ gpio_free(rmi4_data->board->reset_gpio);
+ if (gpio_is_valid(rmi4_data->board->irq_gpio))
+ gpio_free(rmi4_data->board->irq_gpio);
+err_gpio_config:
synaptics_rmi4_power_on(rmi4_data, false);
err_power_device:
synaptics_rmi4_regulator_configure(rmi4_data, false);
@@ -2592,24 +2634,48 @@
bool on)
{
int retval;
+ int load_ua;
if (on == false)
goto regulator_hpm;
- retval = reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
+ if (rmi4_data->board->i2c_pull_up) {
+ load_ua = rmi4_data->board->power_down_enable ?
+ 0 : RMI4_I2C_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
+ load_ua);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c set_opt failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c disable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_lpm;
+ }
+ }
+ }
+
+ load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+ retval = reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
if (retval < 0) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_ana set_opt failed rc=%d\n",
+ "Regulator vdd_ana set_opt failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
- if (rmi4_data->board->i2c_pull_up) {
- retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
- RMI4_I2C_LPM_LOAD_UA);
- if (retval < 0) {
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_disable(rmi4_data->vdd);
+ if (retval) {
dev_err(&rmi4_data->i2c_client->dev,
- "Regulator vcc_i2c set_opt failed rc=%d\n",
+ "Regulator vdd disable failed rc=%d\n",
retval);
goto fail_regulator_lpm;
}
@@ -2628,6 +2694,16 @@
goto fail_regulator_hpm;
}
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vdd);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vdd enable failed rc=%d\n",
+ retval);
+ goto fail_regulator_hpm;
+ }
+ }
+
if (rmi4_data->board->i2c_pull_up) {
retval = reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
RMI4_I2C_LOAD_UA);
@@ -2637,6 +2713,16 @@
retval);
goto fail_regulator_hpm;
}
+
+ if (rmi4_data->board->power_down_enable) {
+ retval = regulator_enable(rmi4_data->vcc_i2c);
+ if (retval) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Regulator vcc_i2c enable failed " \
+ "rc=%d\n", retval);
+ goto fail_regulator_hpm;
+ }
+ }
}
return 0;
@@ -2650,10 +2736,13 @@
return retval;
fail_regulator_hpm:
- reg_set_optimum_mode_check(rmi4_data->vdd, RMI4_LPM_LOAD_UA);
- if (rmi4_data->board->i2c_pull_up)
- reg_set_optimum_mode_check(rmi4_data->vcc_i2c,
- RMI4_I2C_LPM_LOAD_UA);
+ load_ua = rmi4_data->board->power_down_enable ? 0 : RMI4_LPM_LOAD_UA;
+ reg_set_optimum_mode_check(rmi4_data->vdd, load_ua);
+ if (rmi4_data->board->i2c_pull_up) {
+ load_ua = rmi4_data->board->power_down_enable ?
+ 0 : RMI4_I2C_LPM_LOAD_UA;
+ reg_set_optimum_mode_check(rmi4_data->vcc_i2c, load_ua);
+ }
return retval;
}
@@ -2696,6 +2785,13 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in suspend state\n");
+ return retval;
+ }
+ }
rmi4_data->suspended = true;
return 0;
@@ -2721,6 +2817,14 @@
return 0;
}
+ if (rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(dev, "failed to put gpios in active state\n");
+ return retval;
+ }
+ }
+
retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
if (retval < 0) {
dev_err(dev, "failed to enter active power mode\n");
@@ -2731,6 +2835,17 @@
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
+ if (rmi4_data->board->power_down_enable ||
+ rmi4_data->board->disable_gpios) {
+ retval = synaptics_rmi4_reset_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to issue reset command, " \
+ "rc = %d\n", __func__, retval);
+ return retval;
+ }
+ }
+
rmi4_data->suspended = false;
return 0;
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 fcdf34e..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
@@ -371,7 +371,7 @@
break;
case VIDIOC_MSM_ISP_SET_SRC_STATE:
mutex_lock(&vfe_dev->core_mutex);
- msm_isp_set_src_state(vfe_dev, arg);
+ rc = msm_isp_set_src_state(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
@@ -415,7 +415,7 @@
if (resource_size(vfe_dev->vfe_mem) <
(reg_cfg_cmd->u.rw_info.reg_offset +
reg_cfg_cmd->u.rw_info.len)) {
- pr_err("%s: Invalid length\n", __func__);
+ pr_err("%s: VFE_WRITE: Invalid length\n", __func__);
return -EINVAL;
}
msm_camera_io_memcpy(vfe_dev->vfe_base +
@@ -427,16 +427,37 @@
case VFE_WRITE_MB: {
uint32_t *data_ptr = cfg_data +
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
+
+ if ((UINT_MAX - sizeof(*data_ptr) <
+ reg_cfg_cmd->u.rw_info.reg_offset) ||
+ (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.rw_info.reg_offset +
+ sizeof(*data_ptr))) {
+ pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__);
+ return -EINVAL;
+ }
msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base +
reg_cfg_cmd->u.rw_info.reg_offset);
break;
}
case VFE_CFG_MASK: {
uint32_t temp;
+ if (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.mask_info.reg_offset)
+ return -EINVAL;
temp = msm_camera_io_r(vfe_dev->vfe_base +
reg_cfg_cmd->u.mask_info.reg_offset);
+
temp &= ~reg_cfg_cmd->u.mask_info.mask;
temp |= reg_cfg_cmd->u.mask_info.val;
+ if ((UINT_MAX - sizeof(temp) <
+ reg_cfg_cmd->u.mask_info.reg_offset) ||
+ (resource_size(vfe_dev->vfe_mem) <
+ reg_cfg_cmd->u.mask_info.reg_offset +
+ sizeof(temp))) {
+ pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__);
+ return -EINVAL;
+ }
msm_camera_io_w(temp, vfe_dev->vfe_base +
reg_cfg_cmd->u.mask_info.reg_offset);
break;
@@ -448,8 +469,10 @@
uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL;
uint32_t hi_val, lo_val, lo_val1;
if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) {
- if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
- reg_cfg_cmd->u.dmi_info.len > cmd_len) {
+ if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset <
+ reg_cfg_cmd->u.dmi_info.len) ||
+ (reg_cfg_cmd->u.dmi_info.hi_tbl_offset +
+ reg_cfg_cmd->u.dmi_info.len > cmd_len)) {
pr_err("Invalid Hi Table out of bounds\n");
return -EINVAL;
}
@@ -533,6 +556,12 @@
uint32_t *data_ptr = cfg_data +
reg_cfg_cmd->u.rw_info.cmd_data_offset/4;
for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) {
+ if ((data_ptr < cfg_data) ||
+ (UINT_MAX / sizeof(*data_ptr) <
+ (data_ptr - cfg_data)) ||
+ (sizeof(*data_ptr) * (data_ptr - cfg_data) >
+ cmd_len))
+ return -EINVAL;
*data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base +
reg_cfg_cmd->u.rw_info.reg_offset);
reg_cfg_cmd->u.rw_info.reg_offset += 4;
@@ -553,6 +582,11 @@
struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd;
uint32_t *cfg_data;
+ if (!proc_cmd->num_cfg) {
+ pr_err("%s: Passed num_cfg as 0\n", __func__);
+ return -EINVAL;
+ }
+
reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)*
proc_cmd->num_cfg, GFP_KERNEL);
if (!reg_cfg_cmd) {
@@ -768,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);
@@ -791,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",
@@ -900,11 +936,14 @@
}
}
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
{
struct msm_vfe_axi_src_state *src_state = arg;
+ if (src_state->input_src >= VFE_SRC_MAX)
+ return -EINVAL;
vfe_dev->axi_data.src_info[src_state->input_src].active =
src_state->src_active;
+ return 0;
}
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index ee901c3..3364306 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -65,7 +65,7 @@
int msm_isp_get_bit_per_pixel(uint32_t output_format);
enum msm_isp_pack_fmt msm_isp_get_pack_format(uint32_t output_format);
irqreturn_t msm_isp_process_irq(int irq_num, void *data);
-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
+int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
void msm_isp_do_tasklet(unsigned long data);
void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev);
void msm_isp_process_error_info(struct vfe_device *vfe_dev);
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/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
index 6bd7feb..46a0542 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c
@@ -544,7 +544,7 @@
int msm_camera_request_gpio_table(struct gpio *gpio_tbl, uint8_t size,
int gpio_en)
{
- int rc = 0, i = 0;
+ int rc = 0, i = 0, err = 0;
if (!gpio_tbl || !size) {
pr_err("%s:%d invalid gpio_tbl %p / size %d\n", __func__,
@@ -556,11 +556,19 @@
gpio_tbl[i].gpio, gpio_tbl[i].flags);
}
if (gpio_en) {
- rc = gpio_request_array(gpio_tbl, size);
- if (rc < 0) {
- pr_err("%s:%d camera gpio request failed\n", __func__,
- __LINE__);
- return rc;
+ for (i = 0; i < size; i++) {
+ err = gpio_request_one(gpio_tbl[i].gpio,
+ gpio_tbl[i].flags, gpio_tbl[i].label);
+ if (err) {
+ /*
+ * After GPIO request fails, contine to
+ * apply new gpios, outout a error message
+ * for driver bringup debug
+ */
+ pr_err("%s:%d gpio %d:%s request fails\n",
+ __func__, __LINE__,
+ gpio_tbl[i].gpio, gpio_tbl[i].label);
+ }
}
} else {
gpio_free_array(gpio_tbl, size);
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 f94b6f1..36a2658 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2436,6 +2436,7 @@
lock = &inst->bufq[CAPTURE_PORT].lock;
else
lock = &inst->bufq[OUTPUT_PORT].lock;
+ temp->vb->v4l2_planes[0].bytesused = 0;
mutex_lock(lock);
vb2_buffer_done(temp->vb, VB2_BUF_STATE_DONE);
mutex_unlock(lock);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 1eebe61..9c35a55 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1195,15 +1195,54 @@
return 0;
}
+static int wcd9xxx_process_supplies(struct device *dev,
+ struct wcd9xxx_pdata *pdata, const char *supply_list,
+ int supply_cnt, bool is_ondemand, int index)
+{
+ int idx, ret = 0;
+ const char *name;
+
+ if (supply_cnt == 0) {
+ dev_dbg(dev, "%s: no supplies defined for %s\n", __func__,
+ supply_list);
+ return 0;
+ }
+
+ for (idx = 0; idx < supply_cnt; idx++) {
+ ret = of_property_read_string_index(dev->of_node,
+ supply_list, idx,
+ &name);
+ if (ret) {
+ dev_err(dev, "%s: of read string %s idx %d error %d\n",
+ __func__, supply_list, idx, ret);
+ goto err;
+ }
+
+ dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
+ __func__, name, supply_list);
+ ret = wcd9xxx_dt_parse_vreg_info(dev,
+ &pdata->regulator[index + idx],
+ name, is_ondemand);
+ if (ret)
+ goto err;
+ }
+
+ return 0;
+
+err:
+ return ret;
+
+}
+
static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
{
struct wcd9xxx_pdata *pdata;
- int ret, static_cnt, ond_cnt, idx, i;
- const char *name = NULL;
+ int ret, static_cnt, ond_cnt, cp_supplies_cnt;
u32 mclk_rate = 0;
u32 dmic_sample_rate = 0;
const char *static_prop_name = "qcom,cdc-static-supplies";
const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
+ const char *cp_supplies_name = "qcom,cdc-cp-supplies";
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1223,44 +1262,34 @@
if (IS_ERR_VALUE(ond_cnt))
ond_cnt = 0;
- BUG_ON(static_cnt <= 0 || ond_cnt < 0);
- if ((static_cnt + ond_cnt) > ARRAY_SIZE(pdata->regulator)) {
+ /* cp-supplies list is an optional property */
+ cp_supplies_cnt = of_property_count_strings(dev->of_node,
+ cp_supplies_name);
+ if (IS_ERR_VALUE(cp_supplies_cnt))
+ cp_supplies_cnt = 0;
+
+ BUG_ON(static_cnt <= 0 || ond_cnt < 0 || cp_supplies_cnt < 0);
+ if ((static_cnt + ond_cnt + cp_supplies_cnt)
+ > ARRAY_SIZE(pdata->regulator)) {
dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
__func__, static_cnt, ARRAY_SIZE(pdata->regulator));
goto err;
}
- for (idx = 0; idx < static_cnt; idx++) {
- ret = of_property_read_string_index(dev->of_node,
- static_prop_name, idx,
- &name);
- if (ret) {
- dev_err(dev, "%s: of read string %s idx %d error %d\n",
- __func__, static_prop_name, idx, ret);
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, static_prop_name,
+ static_cnt, false, 0);
+ if (ret)
+ goto err;
- dev_dbg(dev, "%s: Found static cdc supply %s\n", __func__,
- name);
- ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
- name, false);
- if (ret)
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, ond_prop_name,
+ ond_cnt, true, static_cnt);
+ if (ret)
+ goto err;
- for (i = 0; i < ond_cnt; i++, idx++) {
- ret = of_property_read_string_index(dev->of_node, ond_prop_name,
- i, &name);
- if (ret)
- goto err;
-
- dev_dbg(dev, "%s: Found on-demand cdc supply %s\n", __func__,
- name);
- ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[idx],
- name, true);
- if (ret)
- goto err;
- }
+ ret = wcd9xxx_process_supplies(dev, pdata, cp_supplies_name,
+ cp_supplies_cnt, false, static_cnt + ond_cnt);
+ if (ret)
+ goto err;
ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
if (ret)
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/bus.c b/drivers/mmc/core/bus.c
index b140510..58ba933 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -397,10 +397,11 @@
mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
- pr_info("%s: new %s%s%s%s%s card at address %04x\n",
+ pr_info("%s: new %s%s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
+ (mmc_card_hs400(card) ? "HS400 " : ""),
(mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "",
uhs_bus_speed_mode, type, card->rca);
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 90d9826..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.
*/
@@ -263,6 +274,12 @@
card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
hs_max_dtr = MMC_HS200_MAX_DTR;
+ if ((caps2 & MMC_CAP2_HS400_1_8V &&
+ card_type & EXT_CSD_CARD_TYPE_HS400_1_8V) ||
+ (caps2 & MMC_CAP2_HS400_1_2V &&
+ card_type & EXT_CSD_CARD_TYPE_HS400_1_2V))
+ hs_max_dtr = MMC_HS400_MAX_DTR;
+
card->ext_csd.hs_max_dtr = hs_max_dtr;
card->ext_csd.card_type = card_type;
}
@@ -301,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];
@@ -465,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 =
@@ -486,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];
@@ -719,7 +744,9 @@
EXT_CSD_PWR_CL_52_195 :
EXT_CSD_PWR_CL_DDR_52_195;
else if (host->ios.clock <= 200000000)
- index = EXT_CSD_PWR_CL_200_195;
+ index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ EXT_CSD_PWR_CL_200_195 :
+ EXT_CSD_PWR_CL_DDR_200_195;
break;
case MMC_VDD_27_28:
case MMC_VDD_28_29:
@@ -737,7 +764,9 @@
EXT_CSD_PWR_CL_52_360 :
EXT_CSD_PWR_CL_DDR_52_360;
else if (host->ios.clock <= 200000000)
- index = EXT_CSD_PWR_CL_200_360;
+ index = (bus_width <= EXT_CSD_BUS_WIDTH_8) ?
+ EXT_CSD_PWR_CL_200_360 :
+ EXT_CSD_PWR_CL_DDR_200_360;
break;
default:
pr_warning("%s: Voltage range not supported "
@@ -766,75 +795,385 @@
}
/*
- * Selects the desired buswidth and switch to the HS200 mode
- * if bus width set without error
+ * Select the correct bus width supported by both host and card
*/
-static int mmc_select_hs200(struct mmc_card *card)
+static int mmc_select_bus_width(struct mmc_card *card, int ddr, u8 *ext_csd)
{
- int idx, err = 0;
struct mmc_host *host;
- static unsigned ext_csd_bits[] = {
- EXT_CSD_BUS_WIDTH_4,
- EXT_CSD_BUS_WIDTH_8,
+ static unsigned ext_csd_bits[][2] = {
+ { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
+ { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
+ { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
};
static unsigned bus_widths[] = {
- MMC_BUS_WIDTH_4,
MMC_BUS_WIDTH_8,
+ MMC_BUS_WIDTH_4,
+ MMC_BUS_WIDTH_1
};
-
- BUG_ON(!card);
+ unsigned idx, bus_width = 0;
+ int err = 0;
host = card->host;
+ if ((card->csd.mmca_vsn < CSD_SPEC_VER_4) ||
+ !(host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
+ goto out;
+
+ if (host->caps & MMC_CAP_8_BIT_DATA)
+ idx = 0;
+ else
+ idx = 1;
+
+ for (; idx < ARRAY_SIZE(bus_widths); idx++) {
+ bus_width = bus_widths[idx];
+ if (bus_width == MMC_BUS_WIDTH_1)
+ ddr = 0; /* no DDR for 1-bit width */
+ err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
+ ext_csd);
+ if (err)
+ pr_warning("%s: power class selection to " \
+ "bus width %d failed\n",
+ mmc_hostname(host),
+ 1 << bus_width);
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ ext_csd_bits[idx][0],
+ card->ext_csd.generic_cmd6_time);
+ if (!err) {
+ mmc_set_bus_width(host, bus_width);
+
+ /*
+ * If controller can't handle bus width test,
+ * compare ext_csd previously read in 1 bit mode
+ * against ext_csd at new bus width
+ */
+ if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
+ err = mmc_compare_ext_csds(card, bus_width);
+ else
+ err = mmc_bus_test(card, bus_width);
+ if (!err)
+ break;
+ }
+ }
+
+ if (!err && ddr) {
+ err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
+ ext_csd);
+ if (err)
+ pr_warning("%s: power class selection to " \
+ "bus width %d ddr %d failed\n",
+ mmc_hostname(host),
+ 1 << bus_width, ddr);
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH,
+ ext_csd_bits[idx][1],
+ card->ext_csd.generic_cmd6_time);
+ }
+
+out:
+ return err;
+}
+
+/*
+ * Switch to HighSpeed mode and select wide bus if supported
+ */
+static int mmc_select_hs(struct mmc_card *card, u8 *ext_csd)
+{
+ int err = 0;
+ struct mmc_host *host;
+
+ host = card->host;
+
+ if (!(host->caps & MMC_CAP_MMC_HIGHSPEED) ||
+ !(card->ext_csd.card_type & EXT_CSD_CARD_TYPE_52)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 1,
+ card->ext_csd.generic_cmd6_time);
+
+ if (err && err != -EBADMSG)
+ goto out;
+
+ mmc_card_set_highspeed(card);
+ mmc_set_timing(host, MMC_TIMING_MMC_HS);
+ mmc_set_clock(host, MMC_HIGH_52_MAX_DTR);
+
+ err = mmc_select_bus_width(card, 0, ext_csd);
+
+out:
+ if (err && err != -EOPNOTSUPP)
+ pr_warning("%s: Switch to HighSpeed mode failed (err:%d)\n",
+ mmc_hostname(host), err);
+ return err;
+}
+
+/*
+ * Select the desired buswidth and switch to HighSpeed DDR mode
+ * if bus width set without error
+ */
+static int mmc_select_hsddr(struct mmc_card *card, u8 *ext_csd)
+{
+ int ddr = 0, err = 0;
+ struct mmc_host *host;
+
+ host = card->host;
+
+ if (!(host->caps & MMC_CAP_HSDDR) ||
+ !(card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_52)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ err = mmc_select_hs(card, ext_csd);
+ if (err)
+ goto out;
+ mmc_card_clr_highspeed(card);
+
+ if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
+ && ((host->caps & (MMC_CAP_1_8V_DDR |
+ MMC_CAP_UHS_DDR50))
+ == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
+ ddr = MMC_1_8V_DDR_MODE;
+ else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
+ && ((host->caps & (MMC_CAP_1_2V_DDR |
+ MMC_CAP_UHS_DDR50))
+ == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
+ ddr = MMC_1_2V_DDR_MODE;
+
+ err = mmc_select_bus_width(card, ddr, ext_csd);
+ if (err)
+ goto out;
+
+ if (host->ios.bus_width == MMC_BUS_WIDTH_1) {
+ pr_err("%s: failed to switch to wide bus\n",
+ mmc_hostname(host));
+ goto out;
+ }
+
+ /*
+ * eMMC cards can support 3.3V to 1.2V i/o (vccq)
+ * signaling.
+ *
+ * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
+ *
+ * 1.8V vccq at 3.3V core voltage (vcc) is not required
+ * in the JEDEC spec for DDR.
+ *
+ * Do not force change in vccq since we are obviously
+ * working and no change to vccq is needed.
+ *
+ * WARNING: eMMC rules are NOT the same as SD DDR
+ */
+ if (ddr == MMC_1_2V_DDR_MODE) {
+ err = mmc_set_signal_voltage(host,
+ MMC_SIGNAL_VOLTAGE_120, 0);
+ if (err)
+ goto out;
+ }
+ mmc_card_set_ddr_mode(card);
+ mmc_set_timing(host, MMC_TIMING_UHS_DDR50);
+ mmc_set_bus_width(host, host->ios.bus_width);
+
+out:
+ if (err && err != -EOPNOTSUPP)
+ pr_warning("%s: Switch to HighSpeed DDR mode failed (err:%d)\n",
+ mmc_hostname(host), err);
+ return err;
+}
+
+/*
+ * Select the desired buswidth and switch to HS200 mode
+ * if bus width set without error
+ */
+static int mmc_select_hs200(struct mmc_card *card, u8 *ext_csd)
+{
+ int err = 0;
+ struct mmc_host *host;
+
+ host = card->host;
+
+ if (!(host->caps2 & MMC_CAP2_HS200) ||
+ !(card->ext_csd.card_type & EXT_CSD_CARD_TYPE_HS200)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0))
err = mmc_set_signal_voltage(host,
MMC_SIGNAL_VOLTAGE_180, 0);
-
/* If fails try again during next card power cycle */
if (err)
- goto err;
-
- idx = (host->caps & MMC_CAP_8_BIT_DATA) ? 1 : 0;
+ goto out;
/*
- * Unlike SD, MMC cards dont have a configuration register to notify
- * supported bus width. So bus test command should be run to identify
- * the supported bus width or compare the ext csd values of current
- * bus width and ext csd values of 1 bit mode read earlier.
+ * For devices supporting HS200 mode, the bus width has
+ * to be set before executing the tuning function. If
+ * set before tuning, then device will respond with CRC
+ * errors for responses on CMD line. So for HS200 the
+ * sequence will be
+ * 1. set bus width 4bit / 8 bit (1 bit not supported)
+ * 2. switch to HS200 mode
+ * 3. set the clock to > 52Mhz <=200MHz and
+ * 4. execute tuning for HS200
*/
- for (; idx >= 0; idx--) {
+ err = mmc_select_bus_width(card, 0, ext_csd);
+ if (err) {
+ pr_err("%s: select bus width failed\n",
+ mmc_hostname(host));
+ goto out;
+ }
- /*
- * Host is capable of 8bit transfer, then switch
- * the device to work in 8bit transfer mode. If the
- * mmc switch command returns error then switch to
- * 4bit transfer mode. On success set the corresponding
- * bus width on the host.
- */
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx],
- card->ext_csd.generic_cmd6_time);
- if (err)
- continue;
-
- mmc_set_bus_width(card->host, bus_widths[idx]);
-
- if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
- err = mmc_compare_ext_csds(card, bus_widths[idx]);
- else
- err = mmc_bus_test(card, bus_widths[idx]);
- if (!err)
- break;
+ if (host->ios.bus_width == MMC_BUS_WIDTH_1) {
+ pr_err("%s: failed to switch to wide bus\n",
+ mmc_hostname(host));
+ goto out;
}
/* switch to HS200 mode if bus width set successfully */
- if (!err)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 2, 0);
-err:
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 2, 0);
+
+ if (err && err != -EBADMSG) {
+ pr_err("%s: HS200 switch failed\n",
+ mmc_hostname(host));
+ goto out;
+ }
+
+ /*
+ * When HS200 activation is performed as part of HS400 selection
+ * set the timing appropriately
+ */
+ if (mmc_card_hs400(card))
+ mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+ else
+ mmc_set_timing(host, MMC_TIMING_MMC_HS200);
+
+ mmc_set_clock(host, MMC_HS200_MAX_DTR);
+
+ if (host->ops->execute_tuning) {
+ mmc_host_clk_hold(host);
+ err = host->ops->execute_tuning(host,
+ MMC_SEND_TUNING_BLOCK_HS200);
+ mmc_host_clk_release(host);
+ }
+ if (err) {
+ pr_warning("%s: tuning execution failed\n",
+ mmc_hostname(host));
+ goto out;
+ }
+ mmc_card_set_hs200(card);
+
+out:
+ if (err && err != -EOPNOTSUPP)
+ pr_warning("%s: Switch to HS200 mode failed (err:%d)\n",
+ mmc_hostname(host), err);
+ return err;
+}
+
+static int mmc_select_hs400(struct mmc_card *card, u8 *ext_csd)
+{
+ int err = 0;
+ struct mmc_host *host;
+
+ host = card->host;
+
+ if (!(host->caps2 & MMC_CAP2_HS400) ||
+ !(card->ext_csd.card_type & EXT_CSD_CARD_TYPE_HS400)) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ /*
+ * eMMC5.0 spec doesn't allow switching to HS400 mode from
+ * HS200 mode directly. Hence follow these steps to switch
+ * to HS400 mode:
+ * Enable HS200 mode
+ * Enable HighSpeed mode (The clk should be low enough
+ * to enable HighSpeed mode) - HS_TIMING is 0x1
+ * Enable DDR mode (Set bus width to 8-bit DDR)
+ * Enable HS400 mode (Set HS_TIMING to 0x3 and change
+ * frequency to <= 200MHz)
+ * Perform tuning if required
+ */
+ mmc_card_set_hs400(card);
+ err = mmc_select_hs200(card, ext_csd);
+ if (err)
+ goto out;
+ mmc_card_clr_hs200(card);
+
+ if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_HS400_1_2V)
+ && (host->caps2 & MMC_CAP2_HS400_1_2V))
+ if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0))
+ err = mmc_set_signal_voltage(host,
+ MMC_SIGNAL_VOLTAGE_180, 0);
+ /* If fails try again during next card power cycle */
+ if (err)
+ goto out;
+
+ /*
+ * Lower the clock and adjust the timing to be able
+ * to switch to HighSpeed mode
+ */
+ mmc_set_timing(host, MMC_TIMING_LEGACY);
+ mmc_set_clock(host, MMC_HIGH_26_MAX_DTR);
+
+ err = mmc_select_hs(card, ext_csd);
+ if (err)
+ goto out;
+ mmc_card_clr_highspeed(card);
+
+ /* Switch to 8-bit DDR mode */
+ err = mmc_select_hsddr(card, ext_csd);
+ if (err)
+ goto out;
+ mmc_card_clr_ddr_mode(card);
+
+ /*
+ * In HS400 mode only DDR 8-bit bus width is allowed.
+ */
+ if (host->ios.bus_width != MMC_BUS_WIDTH_8) {
+ pr_err("%s: failed to switch to 8-bit bus width\n",
+ mmc_hostname(host));
+ goto out;
+ }
+
+ /* Switch to HS400 mode if bus width set successfully */
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_HS_TIMING, 3, 0);
+ if (err && err != -EBADMSG) {
+ pr_err("%s: Setting HS_TIMING to HS400 failed (err:%d)\n",
+ mmc_hostname(host), err);
+ goto out;
+ }
+
+ mmc_set_timing(host, MMC_TIMING_MMC_HS400);
+ mmc_set_clock(host, MMC_HS400_MAX_DTR);
+
+ if (host->ops->execute_tuning) {
+ mmc_host_clk_hold(host);
+ err = host->ops->execute_tuning(host,
+ MMC_SEND_TUNING_BLOCK_HS400);
+ mmc_host_clk_release(host);
+ }
+ if (err) {
+ pr_err("%s: tuning execution failed (err:%d)\n",
+ mmc_hostname(host), err);
+ goto out;
+ }
+ mmc_card_set_hs400(card);
+
+out:
+ if (err && err != -EOPNOTSUPP) {
+ pr_warning("%s: Switch to HS400 mode failed (err:%d)\n",
+ mmc_hostname(host), err);
+ mmc_card_clr_hs400(card);
+ }
return err;
}
@@ -869,7 +1208,8 @@
}
if (mmc_card_highspeed(card) || mmc_card_hs200(card)
- || mmc_card_ddr_mode(card)) {
+ || mmc_card_ddr_mode(card)
+ || mmc_card_hs400(card)) {
if (*freq > card->ext_csd.hs_max_dtr)
*freq = card->ext_csd.hs_max_dtr;
} else if (*freq > card->csd.max_dtr) {
@@ -881,7 +1221,8 @@
mmc_set_clock(host, (unsigned int) (*freq));
- if (mmc_card_hs200(card) && card->host->ops->execute_tuning) {
+ if ((mmc_card_hs400(card) || mmc_card_hs200(card))
+ && card->host->ops->execute_tuning) {
/*
* We try to probe host driver for tuning for any
* frequency, it is host driver responsibility to
@@ -919,6 +1260,35 @@
}
/*
+ * Activate highest bus speed mode supported by both host and card.
+ * On failure activate the next supported highest bus speed mode.
+ */
+static int mmc_select_bus_speed(struct mmc_card *card, u8 *ext_csd)
+{
+ int err = 0;
+
+ BUG_ON(!card);
+
+ if (!mmc_select_hs400(card, ext_csd))
+ goto out;
+ if (!mmc_select_hs200(card, ext_csd))
+ goto out;
+ if (!mmc_select_hsddr(card, ext_csd))
+ goto out;
+ if (!mmc_select_hs(card, ext_csd))
+ goto out;
+
+ /*
+ * Select the default speed and wide bus if supported
+ */
+ mmc_set_clock(card->host, card->csd.max_dtr);
+ err = mmc_select_bus_width(card, 0, ext_csd);
+
+out:
+ return err;
+}
+
+/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
@@ -928,9 +1298,8 @@
struct mmc_card *oldcard)
{
struct mmc_card *card;
- int err, ddr = 0;
+ int err = 0;
u32 cid[4];
- unsigned int max_dtr;
u32 rocr;
u8 *ext_csd = NULL;
@@ -1132,209 +1501,11 @@
}
/*
- * Activate high speed (if supported)
+ * Activate highest bus speed mode supported by both host and card.
*/
- if (card->ext_csd.hs_max_dtr != 0) {
- err = 0;
- if (card->ext_csd.hs_max_dtr > 52000000 &&
- host->caps2 & MMC_CAP2_HS200)
- err = mmc_select_hs200(card);
- else if (host->caps & MMC_CAP_MMC_HIGHSPEED)
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_HS_TIMING, 1,
- card->ext_csd.generic_cmd6_time);
-
- if (err && err != -EBADMSG)
- goto free_card;
-
- if (err) {
- pr_warning("%s: switch to highspeed failed\n",
- mmc_hostname(card->host));
- err = 0;
- } else {
- if (card->ext_csd.hs_max_dtr > 52000000 &&
- host->caps2 & MMC_CAP2_HS200) {
- mmc_card_set_hs200(card);
- mmc_set_timing(card->host,
- MMC_TIMING_MMC_HS200);
- } else {
- mmc_card_set_highspeed(card);
- mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
- }
- }
- }
-
- /*
- * Compute bus speed.
- */
- max_dtr = (unsigned int)-1;
-
- if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
- if (max_dtr > card->ext_csd.hs_max_dtr)
- max_dtr = card->ext_csd.hs_max_dtr;
- } else if (max_dtr > card->csd.max_dtr) {
- max_dtr = card->csd.max_dtr;
- }
-
- mmc_set_clock(host, max_dtr);
-
- /*
- * Indicate DDR mode (if supported).
- */
- if (mmc_card_highspeed(card)) {
- if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
- && ((host->caps & (MMC_CAP_1_8V_DDR |
- MMC_CAP_UHS_DDR50))
- == (MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50)))
- ddr = MMC_1_8V_DDR_MODE;
- else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
- && ((host->caps & (MMC_CAP_1_2V_DDR |
- MMC_CAP_UHS_DDR50))
- == (MMC_CAP_1_2V_DDR | MMC_CAP_UHS_DDR50)))
- ddr = MMC_1_2V_DDR_MODE;
- }
-
- /*
- * Indicate HS200 SDR mode (if supported).
- */
- if (mmc_card_hs200(card)) {
- u32 ext_csd_bits;
- u32 bus_width = card->host->ios.bus_width;
-
- /*
- * For devices supporting HS200 mode, the bus width has
- * to be set before executing the tuning function. If
- * set before tuning, then device will respond with CRC
- * errors for responses on CMD line. So for HS200 the
- * sequence will be
- * 1. set bus width 4bit / 8 bit (1 bit not supported)
- * 2. switch to HS200 mode
- * 3. set the clock to > 52Mhz <=200MHz and
- * 4. execute tuning for HS200
- */
- if ((host->caps2 & MMC_CAP2_HS200) &&
- card->host->ops->execute_tuning) {
- mmc_host_clk_hold(card->host);
- err = card->host->ops->execute_tuning(card->host,
- MMC_SEND_TUNING_BLOCK_HS200);
- mmc_host_clk_release(card->host);
- }
- if (err) {
- pr_warning("%s: tuning execution failed\n",
- mmc_hostname(card->host));
- goto err;
- }
-
- ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
- EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
- err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
- if (err)
- pr_warning("%s: power class selection to bus width %d"
- " failed\n", mmc_hostname(card->host),
- 1 << bus_width);
- }
-
- /*
- * Activate wide bus and DDR (if supported).
- */
- if (!mmc_card_hs200(card) &&
- (card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
- (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
- static unsigned ext_csd_bits[][2] = {
- { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
- { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
- { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
- };
- static unsigned bus_widths[] = {
- MMC_BUS_WIDTH_8,
- MMC_BUS_WIDTH_4,
- MMC_BUS_WIDTH_1
- };
- unsigned idx, bus_width = 0;
-
- if (host->caps & MMC_CAP_8_BIT_DATA)
- idx = 0;
- else
- idx = 1;
- for (; idx < ARRAY_SIZE(bus_widths); idx++) {
- bus_width = bus_widths[idx];
- if (bus_width == MMC_BUS_WIDTH_1)
- ddr = 0; /* no DDR for 1-bit width */
- err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
- ext_csd);
- if (err)
- pr_warning("%s: power class selection to "
- "bus width %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width);
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx][0],
- card->ext_csd.generic_cmd6_time);
- if (!err) {
- mmc_set_bus_width(card->host, bus_width);
-
- /*
- * If controller can't handle bus width test,
- * compare ext_csd previously read in 1 bit mode
- * against ext_csd at new bus width
- */
- if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
- err = mmc_compare_ext_csds(card,
- bus_width);
- else
- err = mmc_bus_test(card, bus_width);
- if (!err)
- break;
- }
- }
-
- if (!err && ddr) {
- err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
- ext_csd);
- if (err)
- pr_warning("%s: power class selection to "
- "bus width %d ddr %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width, ddr);
-
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_BUS_WIDTH,
- ext_csd_bits[idx][1],
- card->ext_csd.generic_cmd6_time);
- }
- if (err) {
- pr_warning("%s: switch to bus width %d ddr %d "
- "failed\n", mmc_hostname(card->host),
- 1 << bus_width, ddr);
- goto free_card;
- } else if (ddr) {
- /*
- * eMMC cards can support 3.3V to 1.2V i/o (vccq)
- * signaling.
- *
- * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
- *
- * 1.8V vccq at 3.3V core voltage (vcc) is not required
- * in the JEDEC spec for DDR.
- *
- * Do not force change in vccq since we are obviously
- * working and no change to vccq is needed.
- *
- * WARNING: eMMC rules are NOT the same as SD DDR
- */
- if (ddr == MMC_1_2V_DDR_MODE) {
- err = mmc_set_signal_voltage(host,
- MMC_SIGNAL_VOLTAGE_120, 0);
- if (err)
- goto err;
- }
- mmc_card_set_ddr_mode(card);
- mmc_set_timing(card->host, MMC_TIMING_UHS_DDR50);
- mmc_set_bus_width(card->host, bus_width);
- }
- }
+ err = mmc_select_bus_speed(card, ext_csd);
+ if (err)
+ goto free_card;
/*
* Enable HPI feature (if supported)
@@ -1356,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/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 33dfad2..a7ce6ae 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -45,6 +45,7 @@
#define SDHCI_VER_100 0x2B
#define CORE_HC_MODE 0x78
#define HC_MODE_EN 0x1
+#define FF_CLK_SW_RST_DIS (1 << 13)
#define CORE_POWER 0x0
#define CORE_SW_RST (1 << 7)
@@ -67,20 +68,57 @@
#define INT_MASK 0xF
#define MAX_PHASES 16
-#define CORE_DLL_LOCK (1 << 7)
+#define CORE_DLL_CONFIG 0x100
+#define CORE_CMD_DAT_TRACK_SEL (1 << 0)
#define CORE_DLL_EN (1 << 16)
#define CORE_CDR_EN (1 << 17)
#define CORE_CK_OUT_EN (1 << 18)
#define CORE_CDR_EXT_EN (1 << 19)
#define CORE_DLL_PDN (1 << 29)
#define CORE_DLL_RST (1 << 30)
-#define CORE_DLL_CONFIG 0x100
-#define CORE_DLL_TEST_CTL 0x104
+
#define CORE_DLL_STATUS 0x108
+#define CORE_DLL_LOCK (1 << 7)
#define CORE_VENDOR_SPEC 0x10C
#define CORE_CLK_PWRSAVE (1 << 1)
+#define CORE_HC_MCLK_SEL_DFLT (2 << 8)
+#define CORE_HC_MCLK_SEL_HS400 (3 << 8)
+#define CORE_HC_MCLK_SEL_MASK (3 << 8)
#define CORE_IO_PAD_PWR_SWITCH (1 << 16)
+#define CORE_HC_SELECT_IN_EN (1 << 18)
+#define CORE_HC_SELECT_IN_HS400 (6 << 19)
+#define CORE_HC_SELECT_IN_MASK (7 << 19)
+
+#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR0 0x114
+#define CORE_VENDOR_SPEC_ADMA_ERR_ADDR1 0x118
+
+#define CORE_CSR_CDC_CTLR_CFG0 0x130
+#define CORE_SW_TRIG_FULL_CALIB (1 << 16)
+#define CORE_HW_AUTOCAL_ENA (1 << 17)
+
+#define CORE_CSR_CDC_CTLR_CFG1 0x134
+#define CORE_CSR_CDC_CAL_TIMER_CFG0 0x138
+#define CORE_TIMER_ENA (1 << 16)
+
+#define CORE_CSR_CDC_CAL_TIMER_CFG1 0x13C
+#define CORE_CSR_CDC_REFCOUNT_CFG 0x140
+#define CORE_CSR_CDC_COARSE_CAL_CFG 0x144
+#define CORE_CDC_OFFSET_CFG 0x14C
+#define CORE_CSR_CDC_DELAY_CFG 0x150
+#define CORE_CDC_SLAVE_DDA_CFG 0x160
+#define CORE_CSR_CDC_STATUS0 0x164
+#define CORE_CALIBRATION_DONE (1 << 0)
+
+#define CORE_CDC_ERROR_CODE_MASK 0x7000000
+
+#define CORE_CSR_CDC_GEN_CFG 0x178
+#define CORE_CDC_SWITCH_BYPASS_OFF (1 << 0)
+#define CORE_CDC_SWITCH_RC_EN (1 << 1)
+
+#define CORE_DDR_200_CFG 0x184
+#define CORE_CDC_T4_DLY_SEL (1 << 0)
+#define CORE_START_CDC_TRAFFIC (1 << 6)
#define CORE_MCI_DATA_CTRL 0x2C
#define CORE_MCI_DPSM_ENABLE (1 << 0)
@@ -114,6 +152,10 @@
#define SDHCI_MSM_MAX_SEGMENTS (1 << 13)
#define SDHCI_MSM_MMC_CLK_GATE_DELAY 200 /* msecs */
+#define CORE_FREQ_100MHZ (100 * 1000 * 1000)
+
+#define INVALID_TUNING_PHASE -1
+
static const u32 tuning_block_64[] = {
0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE,
0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777,
@@ -260,6 +302,8 @@
struct clk *clk; /* main SD/MMC bus clock */
struct clk *pclk; /* SDHC peripheral bus clock */
struct clk *bus_clk; /* SDHC bus voter clock */
+ struct clk *ff_clk; /* CDC calibration fixed feedback clock */
+ struct clk *sleep_clk; /* CDC calibration sleep clock */
atomic_t clks_on; /* Set if clocks are enabled */
struct sdhci_msm_pltfm_data *pdata;
struct mmc_host *mmc;
@@ -270,6 +314,9 @@
struct sdhci_msm_bus_vote msm_bus_vote;
struct device_attribute polling;
u32 clk_rate; /* Keeps track of current clock rate that is set */
+ bool tuning_done;
+ bool calibration_done;
+ u8 saved_tuning_phase;
};
enum vdd_io_level {
@@ -373,8 +420,8 @@
* Find out the greatest range of consecuitive selected
* DLL clock output phases that can be used as sampling
* setting for SD3.0 UHS-I card read operation (in SDR104
- * timing mode) or for eMMC4.5 card read operation (in HS200
- * timing mode).
+ * timing mode) or for eMMC4.5 card read operation (in
+ * HS400/HS200 timing mode).
* Select the 3/4 of the range and configure the DLL with the
* selected DLL clock output phase.
*/
@@ -595,6 +642,137 @@
return rc;
}
+static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
+{
+ u32 wait_cnt;
+ int ret = 0;
+ int cdc_err = 0;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
+ pr_debug("%s: Enter %s\n", mmc_hostname(host->mmc), __func__);
+
+ /*
+ * Retuning in HS400 (DDR mode) will fail, just reset the
+ * tuning block and restore the saved tuning phase.
+ */
+ ret = msm_init_cm_dll(host);
+ if (ret)
+ goto out;
+
+ /* Set the selected phase in delay line hw block */
+ ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+ if (ret)
+ goto out;
+
+ /* Write 1 to CMD_DAT_TRACK_SEL field in DLL_CONFIG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+ | CORE_CMD_DAT_TRACK_SEL),
+ host->ioaddr + CORE_DLL_CONFIG);
+
+ /* Write 0 to CDC_T4_DLY_SEL field in VENDOR_SPEC_DDR200_CFG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ & ~CORE_CDC_T4_DLY_SEL),
+ host->ioaddr + CORE_DDR_200_CFG);
+
+ /* Write 0 to CDC_SWITCH_BYPASS_OFF field in CORE_CSR_CDC_GEN_CFG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG)
+ & ~CORE_CDC_SWITCH_BYPASS_OFF),
+ host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ /* Write 1 to CDC_SWITCH_RC_EN field in CORE_CSR_CDC_GEN_CFG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG)
+ | CORE_CDC_SWITCH_RC_EN),
+ host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+ /* Write 0 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ & ~CORE_START_CDC_TRAFFIC),
+ host->ioaddr + CORE_DDR_200_CFG);
+
+ /*
+ * Perform CDC Register Initialization Sequence
+ *
+ * CORE_CSR_CDC_CTLR_CFG0 0x11800EC
+ * CORE_CSR_CDC_CTLR_CFG1 0x3011111
+ * CORE_CSR_CDC_CAL_TIMER_CFG0 0x1201000
+ * CORE_CSR_CDC_CAL_TIMER_CFG1 0x4
+ * CORE_CSR_CDC_REFCOUNT_CFG 0xCB732020
+ * CORE_CSR_CDC_COARSE_CAL_CFG 0xB19
+ * CORE_CSR_CDC_DELAY_CFG 0x3AC
+ * CORE_CDC_OFFSET_CFG 0x0
+ * CORE_CDC_SLAVE_DDA_CFG 0x16334
+ */
+
+ writel_relaxed(0x11800EC, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+ writel_relaxed(0x3011111, host->ioaddr + CORE_CSR_CDC_CTLR_CFG1);
+ writel_relaxed(0x1201000, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+ writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
+ writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
+ writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
+ writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+ writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
+ writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
+
+ /* CDC HW Calibration */
+
+ /* Write 1 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0)
+ | CORE_SW_TRIG_FULL_CALIB),
+ host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 0 to SW_TRIG_FULL_CALIB field in CORE_CSR_CDC_CTLR_CFG0 */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0)
+ & ~CORE_SW_TRIG_FULL_CALIB),
+ host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 1 to HW_AUTOCAL_ENA field in CORE_CSR_CDC_CTLR_CFG0 */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0)
+ | CORE_HW_AUTOCAL_ENA),
+ host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+ /* Write 1 to TIMER_ENA field in CORE_CSR_CDC_CAL_TIMER_CFG0 */
+ writel_relaxed((readl_relaxed(host->ioaddr +
+ CORE_CSR_CDC_CAL_TIMER_CFG0) | CORE_TIMER_ENA),
+ host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+
+ mb();
+
+ /* Poll on CALIBRATION_DONE field in CORE_CSR_CDC_STATUS0 to be 1 */
+ wait_cnt = 50;
+ while (!(readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
+ & CORE_CALIBRATION_DONE)) {
+ /* max. wait for 50us sec for CALIBRATION_DONE bit to be set */
+ if (--wait_cnt == 0) {
+ pr_err("%s: %s: CDC Calibration was not completed\n",
+ mmc_hostname(host->mmc), __func__);
+ ret = -ETIMEDOUT;
+ goto out;
+ }
+ /* wait for 1us before polling again */
+ udelay(1);
+ }
+
+ /* Verify CDC_ERROR_CODE field in CORE_CSR_CDC_STATUS0 is 0 */
+ cdc_err = readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
+ & CORE_CDC_ERROR_CODE_MASK;
+ if (cdc_err) {
+ pr_err("%s: %s: CDC Error Code %d\n",
+ mmc_hostname(host->mmc), __func__, cdc_err);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Write 1 to START_CDC_TRAFFIC field in CORE_DDR200_CFG */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DDR_200_CFG)
+ | CORE_START_CDC_TRAFFIC),
+ host->ioaddr + CORE_DDR_200_CFG);
+out:
+ pr_debug("%s: Exit %s, ret:%d\n", mmc_hostname(host->mmc),
+ __func__, ret);
+ return ret;
+}
+
int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
{
unsigned long flags;
@@ -605,20 +783,36 @@
int rc;
struct mmc_host *mmc = host->mmc;
struct mmc_ios ios = host->mmc->ios;
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
/*
- * Tuning is required for SDR104 and HS200 cards and if clock frequency
- * is greater than 100MHz in these modes.
+ * Tuning is required for SDR104, HS200 and HS400 cards and
+ * if clock frequency is greater than 100MHz in these modes.
*/
- if (host->clock <= (100 * 1000 * 1000) ||
- !(ios.timing == MMC_TIMING_MMC_HS200 ||
- ios.timing == MMC_TIMING_UHS_SDR104))
+ if (host->clock <= CORE_FREQ_100MHZ ||
+ !((ios.timing == MMC_TIMING_MMC_HS400) ||
+ (ios.timing == MMC_TIMING_MMC_HS200) ||
+ (ios.timing == MMC_TIMING_UHS_SDR104)))
return 0;
pr_debug("%s: Enter %s\n", mmc_hostname(mmc), __func__);
+
+ /* CDCLP533 HW calibration is only required for HS400 mode*/
+ if (msm_host->tuning_done && !msm_host->calibration_done &&
+ (mmc->ios.timing == MMC_TIMING_MMC_HS400)) {
+ rc = sdhci_msm_cdclp533_calibration(host);
+ spin_lock_irqsave(&host->lock, flags);
+ if (!rc)
+ msm_host->calibration_done = true;
+ spin_unlock_irqrestore(&host->lock, flags);
+ goto out;
+ }
+
spin_lock_irqsave(&host->lock, flags);
- if ((opcode == MMC_SEND_TUNING_BLOCK_HS200) &&
+ if (((opcode == MMC_SEND_TUNING_BLOCK_HS400) ||
+ (opcode == MMC_SEND_TUNING_BLOCK_HS200)) &&
(mmc->ios.bus_width == MMC_BUS_WIDTH_8)) {
tuning_block_pattern = tuning_block_128;
size = sizeof(tuning_block_128);
@@ -690,6 +884,7 @@
rc = msm_config_cm_dll_phase(host, phase);
if (rc)
goto kfree;
+ msm_host->saved_tuning_phase = phase;
pr_debug("%s: %s: finally setting the tuning phase to %d\n",
mmc_hostname(mmc), __func__, phase);
} else {
@@ -704,7 +899,11 @@
kfree:
kfree(data_buf);
out:
- pr_debug("%s: Exit %s\n", mmc_hostname(mmc), __func__);
+ spin_lock_irqsave(&host->lock, flags);
+ if (!rc)
+ msm_host->tuning_done = true;
+ spin_unlock_irqrestore(&host->lock, flags);
+ pr_debug("%s: Exit %s, err(%d)\n", mmc_hostname(mmc), __func__, rc);
return rc;
}
@@ -803,7 +1002,7 @@
goto out;
}
sz = *len = *len / sizeof(*arr);
- if (sz <= 0 || (size > 0 && (sz != size))) {
+ if (sz <= 0 || (size > 0 && (sz > size))) {
dev_err(dev, "%s invalid size\n", prop_name);
ret = -EINVAL;
goto out;
@@ -929,9 +1128,9 @@
ret = -ENOMEM;
goto out;
}
- pull_data->size = 3; /* array size for clk, cmd, data */
+ pull_data->size = 4; /* array size for clk, cmd, data and rclk */
- /* Allocate on, off configs for clk, cmd, data */
+ /* Allocate on, off configs for clk, cmd, data and rclk */
pull = devm_kzalloc(dev, 2 * pull_data->size *\
sizeof(struct sdhci_msm_pad_pull), GFP_KERNEL);
if (!pull) {
@@ -1214,7 +1413,11 @@
if (!name)
continue;
- if (!strncmp(name, "HS200_1p8v", sizeof("HS200_1p8v")))
+ if (!strncmp(name, "HS400_1p8v", sizeof("HS400_1p8v")))
+ pdata->caps2 |= MMC_CAP2_HS400_1_8V;
+ else if (!strncmp(name, "HS400_1p2v", sizeof("HS400_1p2v")))
+ pdata->caps2 |= MMC_CAP2_HS400_1_2V;
+ else if (!strncmp(name, "HS200_1p8v", sizeof("HS200_1p8v")))
pdata->caps2 |= MMC_CAP2_HS200_1_8V_SDR;
else if (!strncmp(name, "HS200_1p2v", sizeof("HS200_1p2v")))
pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
@@ -2044,6 +2247,22 @@
mmc_hostname(host->mmc), __func__, rc);
goto disable_pclk;
}
+ if (!IS_ERR(msm_host->ff_clk)) {
+ rc = clk_prepare_enable(msm_host->ff_clk);
+ if (rc) {
+ pr_err("%s: %s: failed to enable the ff_clk with error %d\n",
+ mmc_hostname(host->mmc), __func__, rc);
+ goto disable_clk;
+ }
+ }
+ if (!IS_ERR(msm_host->sleep_clk)) {
+ rc = clk_prepare_enable(msm_host->sleep_clk);
+ if (rc) {
+ pr_err("%s: %s: failed to enable the sleep_clk with error %d\n",
+ mmc_hostname(host->mmc), __func__, rc);
+ goto disable_ff_clk;
+ }
+ }
mb();
} else if (!enable && atomic_read(&msm_host->clks_on)) {
@@ -2051,6 +2270,10 @@
mmc_hostname(host->mmc));
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
mb();
+ if (!IS_ERR_OR_NULL(msm_host->sleep_clk))
+ clk_disable_unprepare(msm_host->sleep_clk);
+ if (!IS_ERR_OR_NULL(msm_host->ff_clk))
+ clk_disable_unprepare(msm_host->ff_clk);
clk_disable_unprepare(msm_host->clk);
if (!IS_ERR(msm_host->pclk))
clk_disable_unprepare(msm_host->pclk);
@@ -2061,6 +2284,12 @@
}
atomic_set(&msm_host->clks_on, enable);
goto out;
+disable_ff_clk:
+ if (!IS_ERR_OR_NULL(msm_host->ff_clk))
+ clk_disable_unprepare(msm_host->ff_clk);
+disable_clk:
+ if (!IS_ERR_OR_NULL(msm_host->clk))
+ clk_disable_unprepare(msm_host->clk);
disable_pclk:
if (!IS_ERR_OR_NULL(msm_host->pclk))
clk_disable_unprepare(msm_host->pclk);
@@ -2093,17 +2322,79 @@
return;
sup_clock = sdhci_msm_get_sup_clk_rate(host, clock);
- if (curr_ios.timing == MMC_TIMING_UHS_DDR50) {
+ if ((curr_ios.timing == MMC_TIMING_UHS_DDR50) ||
+ (curr_ios.timing == MMC_TIMING_MMC_HS400)) {
/*
* The SDHC requires internal clock frequency to be double the
* actual clock that will be set for DDR mode. The controller
- * uses the faster clock(100MHz) for some of its parts and send
- * the actual required clock (50MHz) to the card.
+ * uses the faster clock(100/400MHz) for some of its parts and
+ * send the actual required clock (50/200MHz) to the card.
*/
ddr_clock = clock * 2;
sup_clock = sdhci_msm_get_sup_clk_rate(host,
ddr_clock);
}
+
+ /*
+ * In general all timing modes are controlled via UHS mode select in
+ * Host Control2 register. eMMC specific HS200/HS400 doesn't have
+ * their respective modes defined here, hence we use these values.
+ *
+ * HS200 - SDR104 (Since they both are equivalent in functionality)
+ * HS400 - This involves multiple configurations
+ * Initially SDR104 - when tuning is required as HS200
+ * Then when switching to DDR @ 400MHz (HS400) we use
+ * the vendor specific HC_SELECT_IN to control the mode.
+ *
+ * In addition to controlling the modes we also need to select the
+ * correct input clock for DLL depending on the mode.
+ *
+ * HS400 - divided clock (free running MCLK/2)
+ * All other modes - default (free running MCLK)
+ */
+ if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
+ /* Select the divided clock (free running MCLK/2) */
+ writel_relaxed(((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ & ~CORE_HC_MCLK_SEL_MASK)
+ | CORE_HC_MCLK_SEL_HS400),
+ host->ioaddr + CORE_VENDOR_SPEC);
+ /*
+ * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+ * register
+ */
+ if (msm_host->tuning_done && !msm_host->calibration_done) {
+ /*
+ * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
+ * field in VENDOR_SPEC_FUNC
+ */
+ writel_relaxed((readl_relaxed(host->ioaddr + \
+ CORE_VENDOR_SPEC)
+ | CORE_HC_SELECT_IN_HS400
+ | CORE_HC_SELECT_IN_EN),
+ host->ioaddr + CORE_VENDOR_SPEC);
+ }
+ } else {
+ /* Select the default clock (free running MCLK) */
+ writel_relaxed(((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ & ~CORE_HC_MCLK_SEL_MASK)
+ | CORE_HC_MCLK_SEL_DFLT),
+ host->ioaddr + CORE_VENDOR_SPEC);
+
+ /*
+ * Disable HC_SELECT_IN to be able to use the UHS mode select
+ * configuration from Host Control2 register for all other
+ * modes.
+ *
+ * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+ * in VENDOR_SPEC_FUNC
+ */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
+ & ~CORE_HC_SELECT_IN_EN
+ & ~CORE_HC_SELECT_IN_MASK),
+ host->ioaddr + CORE_VENDOR_SPEC);
+ }
+ mb();
+
if (sup_clock != msm_host->clk_rate) {
pr_debug("%s: %s: setting clk rate to %u\n",
mmc_hostname(host->mmc), __func__, sup_clock);
@@ -2127,12 +2418,16 @@
static int sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
unsigned int uhs)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
u16 ctrl_2;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- if (uhs == MMC_TIMING_MMC_HS200)
+ if (uhs == MMC_TIMING_MMC_HS400)
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+ else if (uhs == MMC_TIMING_MMC_HS200)
ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
else if (uhs == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
@@ -2150,11 +2445,36 @@
* provide feedback clock, the mode selection can be any value less
* than 3'b011 in bits [2:0] of HOST CONTROL2 register.
*/
- if (host->clock <= (100 * 1000 * 1000) &&
- (uhs == MMC_TIMING_MMC_HS200 ||
- uhs == MMC_TIMING_UHS_SDR104))
- ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ if (host->clock <= CORE_FREQ_100MHZ) {
+ if ((uhs == MMC_TIMING_MMC_HS400) ||
+ (uhs == MMC_TIMING_MMC_HS200) ||
+ (uhs == MMC_TIMING_UHS_SDR104))
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ /*
+ * Make sure DLL is disabled when not required
+ *
+ * Write 1 to DLL_RST bit of DLL_CONFIG register
+ */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+ | CORE_DLL_RST),
+ host->ioaddr + CORE_DLL_CONFIG);
+
+ /* Write 1 to DLL_PDN bit of DLL_CONFIG register */
+ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
+ | CORE_DLL_PDN),
+ host->ioaddr + CORE_DLL_CONFIG);
+ mb();
+
+ /*
+ * The DLL needs to be restored and CDCLP533 recalibrated
+ * when the clock frequency is set back to 400MHz.
+ */
+ msm_host->calibration_done = false;
+ }
+
+ pr_debug("%s: %s-clock:%u uhs mode:%u ctrl_2:0x%x\n",
+ mmc_hostname(host->mmc), __func__, host->clock, uhs, ctrl_2);
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
return 0;
@@ -2321,9 +2641,27 @@
msm_host->clk_rate = sdhci_msm_get_min_clock(host);
atomic_set(&msm_host->clks_on, 1);
+ /* Setup CDC calibration fixed feedback clock */
+ msm_host->ff_clk = devm_clk_get(&pdev->dev, "cal_clk");
+ if (!IS_ERR(msm_host->ff_clk)) {
+ ret = clk_prepare_enable(msm_host->ff_clk);
+ if (ret)
+ goto clk_disable;
+ }
+
+ /* Setup CDC calibration sleep clock */
+ msm_host->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+ if (!IS_ERR(msm_host->sleep_clk)) {
+ ret = clk_prepare_enable(msm_host->sleep_clk);
+ if (ret)
+ goto ff_clk_disable;
+ }
+
+ msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+
ret = sdhci_msm_bus_register(msm_host, pdev);
if (ret)
- goto clk_disable;
+ goto sleep_clk_disable;
if (msm_host->msm_bus_vote.client_handle)
INIT_DELAYED_WORK(&msm_host->msm_bus_vote.vote_work,
@@ -2368,6 +2706,10 @@
/* Set HC_MODE_EN bit in HC_MODE register */
writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
+ /* Set FF_CLK_SW_RST_DIS bit in HC_MODE register */
+ writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_HC_MODE) |
+ FF_CLK_SW_RST_DIS, msm_host->core_mem + CORE_HC_MODE);
+
/*
* CORE_SW_RST above may trigger power irq if previous status of PWRCTL
* was either BUS_ON or IO_HIGH_V. So before we enable the power irq
@@ -2554,6 +2896,12 @@
if (msm_host->msm_bus_vote.client_handle)
sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
sdhci_msm_bus_unregister(msm_host);
+sleep_clk_disable:
+ if (!IS_ERR(msm_host->sleep_clk))
+ clk_disable_unprepare(msm_host->sleep_clk);
+ff_clk_disable:
+ if (!IS_ERR(msm_host->ff_clk))
+ clk_disable_unprepare(msm_host->ff_clk);
clk_disable:
if (!IS_ERR(msm_host->clk))
clk_disable_unprepare(msm_host->clk);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 578cc14..f9f3802 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1129,6 +1129,7 @@
/* CMD19 is special in that the Data Present Select should be set */
if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK ||
+ cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400 ||
cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200)
flags |= SDHCI_CMD_DATA;
@@ -1631,7 +1632,8 @@
unsigned int clock;
/* In case of UHS-I modes, set High Speed Enable */
- if ((ios->timing == MMC_TIMING_MMC_HS200) ||
+ if ((ios->timing == MMC_TIMING_MMC_HS400) ||
+ (ios->timing == MMC_TIMING_MMC_HS200) ||
(ios->timing == MMC_TIMING_UHS_SDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
@@ -1686,7 +1688,9 @@
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
- if (ios->timing == MMC_TIMING_MMC_HS200)
+ if (ios->timing == MMC_TIMING_MMC_HS400)
+ ctrl_2 |= SDHCI_CTRL_HS_SDR200;
+ else if (ios->timing == MMC_TIMING_MMC_HS200)
ctrl_2 |= SDHCI_CTRL_HS_SDR200;
else if (ios->timing == MMC_TIMING_UHS_SDR12)
ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
@@ -1982,12 +1986,13 @@
* The Host Controller needs tuning only in case of SDR104 mode
* and for SDR50 mode when Use Tuning for SDR50 is set in the
* Capabilities register.
- * If the Host Controller supports the HS200 mode then the
+ * If the Host Controller supports the HS400/HS200 mode then the
* tuning function has to be executed.
*/
if ((((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) &&
(host->flags & SDHCI_SDR50_NEEDS_TUNING)) ||
- (host->flags & SDHCI_HS200_NEEDS_TUNING))
+ (host->flags & SDHCI_HS200_NEEDS_TUNING) ||
+ (host->flags & SDHCI_HS400_NEEDS_TUNING))
requires_tuning_nonuhs = true;
if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) ||
@@ -2050,7 +2055,8 @@
* block to the Host Controller. So we set the block size
* to 64 here.
*/
- if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
+ if ((cmd.opcode == MMC_SEND_TUNING_BLOCK_HS400) ||
+ (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200)) {
if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
SDHCI_BLOCK_SIZE);
@@ -2451,7 +2457,8 @@
host->cmd->error = -EILSEQ;
if (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING) {
- if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
+ if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400) ||
+ (host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
(host->cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
if (intmask & SDHCI_INT_CRC) {
sdhci_reset(host, SDHCI_RESET_CMD);
@@ -2488,7 +2495,8 @@
}
if (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING) {
- if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
+ if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400) ||
+ (host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
(host->cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
if (intmask & SDHCI_INT_CRC) {
sdhci_finish_command(host);
@@ -2536,7 +2544,8 @@
if (intmask & SDHCI_INT_DATA_AVAIL) {
command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
if (command == MMC_SEND_TUNING_BLOCK ||
- command == MMC_SEND_TUNING_BLOCK_HS200) {
+ command == MMC_SEND_TUNING_BLOCK_HS200 ||
+ command == MMC_SEND_TUNING_BLOCK_HS400) {
host->tuning_done = 1;
wake_up(&host->buf_ready_int);
return;
@@ -2585,7 +2594,8 @@
(host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING)) {
command = SDHCI_GET_CMD(sdhci_readw(host,
SDHCI_COMMAND));
- if ((command != MMC_SEND_TUNING_BLOCK_HS200) &&
+ if ((command != MMC_SEND_TUNING_BLOCK_HS400) &&
+ (command != MMC_SEND_TUNING_BLOCK_HS200) &&
(command != MMC_SEND_TUNING_BLOCK))
pr_msg = true;
} else {
@@ -3217,6 +3227,10 @@
if (mmc->caps2 & MMC_CAP2_HS200)
host->flags |= SDHCI_HS200_NEEDS_TUNING;
+ /* Does the host need tuning for HS400? */
+ if (mmc->caps2 & MMC_CAP2_HS400)
+ host->flags |= SDHCI_HS400_NEEDS_TUNING;
+
/* Driver Type(s) (A, C, D) supported by the host */
if (caps[1] & SDHCI_DRIVER_TYPE_A)
mmc->caps |= MMC_CAP_DRIVER_TYPE_A;
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/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 2f19863..205bf37 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -226,6 +226,8 @@
u8 *puc;
int ret = 0;
u8 la = txn->la;
+ u8 txn_mt;
+ u16 txn_mc = txn->mc;
u8 wbuf[SLIM_MSGQ_BUF_LEN];
if (!pm_runtime_enabled(dev->dev) && dev->state == MSM_CTRL_ASLEEP &&
@@ -402,6 +404,14 @@
puc[1] += dev->port_b;
}
dev->err = 0;
+ /*
+ * If it's a read txn, it may be freed if a response is received by
+ * received thread before reaching end of this function.
+ * mc, mt may have changed to convert standard slimbus code/type to
+ * satellite user-defined message. Reinitialize again
+ */
+ txn_mc = txn->mc;
+ txn_mt = txn->mt;
dev->wr_comp = &tx_sent;
ret = msm_send_msg_buf(dev, pbuf, txn->rl,
NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG);
@@ -427,7 +437,7 @@
void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr,
dev->ver);
dev_err(dev->dev, "TX failed :MC:0x%x,mt:0x%x, ret:%d, ver:%d",
- txn->mc, txn->mt, ret, dev->ver);
+ txn_mc, txn_mt, ret, dev->ver);
conf = readl_relaxed(ngd);
stat = readl_relaxed(ngd + NGD_STATUS);
rx_msgq = readl_relaxed(ngd + NGD_RX_MSGQ_CFG);
@@ -438,10 +448,10 @@
pr_err("conf:0x%x,stat:0x%x,rxmsgq:0x%x", conf, stat, rx_msgq);
pr_err("int_stat:0x%x,int_en:0x%x,int_cll:0x%x", int_stat,
int_en, int_clr);
- } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
- (txn->mc == SLIM_USR_MC_CONNECT_SRC ||
- txn->mc == SLIM_USR_MC_CONNECT_SINK ||
- txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
+ } else if (txn_mt == SLIM_MSG_MT_DEST_REFERRED_USER &&
+ (txn_mc == SLIM_USR_MC_CONNECT_SRC ||
+ txn_mc == SLIM_USR_MC_CONNECT_SINK ||
+ txn_mc == SLIM_USR_MC_DISCONNECT_PORT)) {
int timeout;
mutex_unlock(&dev->tx_lock);
msm_slim_put_ctrl(dev);
@@ -461,7 +471,7 @@
}
ngd_xfer_err:
mutex_unlock(&dev->tx_lock);
- if (txn->mc != SLIM_USR_MC_REPORT_SATELLITE)
+ if (txn_mc != SLIM_USR_MC_REPORT_SATELLITE)
msm_slim_put_ctrl(dev);
return ret ? ret : dev->err;
}
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index d520253..a4a4f28 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -47,6 +47,8 @@
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/wakelock.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
#include <mach/board.h>
#include <mach/msm_serial_hs_lite.h>
#include <mach/msm_bus.h>
@@ -166,12 +168,17 @@
static inline void msm_hsl_write(struct uart_port *port,
unsigned int val, unsigned int off)
{
- iowrite32(val, port->membase + off);
+ __iowmb();
+ __raw_writel_no_log((__force __u32)cpu_to_le32(val),
+ port->membase + off);
}
static inline unsigned int msm_hsl_read(struct uart_port *port,
unsigned int off)
{
- return ioread32(port->membase + off);
+ unsigned int v = le32_to_cpu((__force __le32)__raw_readl_no_log(
+ port->membase + off));
+ __iormb();
+ return v;
}
static unsigned int msm_serial_hsl_has_gsbi(struct uart_port *port)
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 38b1967..9b38ed3 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -388,22 +388,30 @@
}
}
-static void android_enable(struct android_dev *dev)
+static int android_enable(struct android_dev *dev)
{
struct usb_composite_dev *cdev = dev->cdev;
struct android_configuration *conf;
+ int err = 0;
if (WARN_ON(!dev->disable_depth))
- return;
+ return err;
if (--dev->disable_depth == 0) {
- list_for_each_entry(conf, &dev->configs, list_item)
- usb_add_config(cdev, &conf->usb_config,
+ list_for_each_entry(conf, &dev->configs, list_item) {
+ err = usb_add_config(cdev, &conf->usb_config,
android_bind_config);
-
+ if (err < 0) {
+ pr_err("%s: usb_add_config failed : err: %d\n",
+ __func__, err);
+ return err;
+ }
+ }
usb_gadget_connect(cdev->gadget);
}
+
+ return err;
}
static void android_disable(struct android_dev *dev)
@@ -2130,7 +2138,18 @@
list_for_each_entry(f_holder, &conf->enabled_functions, enabled_list) {
ret = f_holder->f->bind_config(f_holder->f, c);
if (ret) {
- pr_err("%s: %s failed", __func__, f_holder->f->name);
+ pr_err("%s: %s failed\n", __func__, f_holder->f->name);
+ while (!list_empty(&c->functions)) {
+ struct usb_function *f;
+
+ f = list_first_entry(&c->functions,
+ struct usb_function, list);
+ list_del(&f->list);
+ if (f->unbind)
+ f->unbind(c, f);
+ }
+ if (c->unbind)
+ c->unbind(c);
return ret;
}
}
@@ -2347,7 +2366,7 @@
int enabled = 0;
bool audio_enabled = false;
static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);
-
+ int err = 0;
if (!cdev)
return -ENODEV;
@@ -2382,7 +2401,14 @@
}
if (audio_enabled)
msleep(100);
- android_enable(dev);
+ err = android_enable(dev);
+ if (err < 0) {
+ pr_err("%s: android_enable failed\n", __func__);
+ dev->connected = 0;
+ dev->enabled = false;
+ mutex_unlock(&dev->mutex);
+ return size;
+ }
dev->enabled = true;
} else if (!enabled && dev->enabled) {
android_disable(dev);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 27d67e3..e4fb26a 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -824,6 +824,11 @@
spin_lock_irqsave(&cdev->lock, flags);
+ if (WARN_ON(!config->cdev)) {
+ spin_unlock_irqrestore(&cdev->lock, flags);
+ return 0;
+ }
+
if (cdev->config == config)
reset_config(cdev);
@@ -1220,6 +1225,15 @@
break;
if (w_value && !f->set_alt)
break;
+ /*
+ * We put interfaces in default settings (alt 0)
+ * upon set config#1. Call set_alt for non-zero
+ * alternate setting.
+ */
+ if (!w_value && cdev->config) {
+ value = 0;
+ break;
+ }
value = f->set_alt(f, w_index, w_value);
if (value == USB_GADGET_DELAYED_STATUS) {
DBG(cdev,
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index f90967f..3b94dd5 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -441,6 +441,10 @@
pr_debug("usb_qdss_disconnect_work\n");
+ status = uninit_data(qdss->data);
+ if (status)
+ pr_err("%s: uninit_data error\n", __func__);
+
/* notify qdss to cancell all active transfers*/
if (qdss->ch.notify) {
qdss->ch.notify(qdss->ch.priv, USB_QDSS_DISCONNECT, NULL,
@@ -458,22 +462,22 @@
{
struct f_qdss *qdss = func_to_qdss(f);
unsigned long flags;
- int status;
pr_debug("qdss_disable\n");
spin_lock_irqsave(&qdss->lock, flags);
+ if (!qdss->usb_connected) {
+ spin_unlock_irqrestore(&qdss->lock, flags);
+ return;
+ }
+
qdss->usb_connected = 0;
spin_unlock_irqrestore(&qdss->lock, flags);
/*cancell all active xfers*/
qdss_eps_disable(f);
- status = uninit_data(qdss->data);
- if (status)
- pr_err("%s: uninit_data error\n", __func__);
-
- schedule_work(&qdss->disconnect_w);
+ queue_work(qdss->wq, &qdss->disconnect_w);
}
static void usb_qdss_connect_work(struct work_struct *work)
@@ -521,6 +525,7 @@
if (gadget->speed != USB_SPEED_SUPER &&
gadget->speed != USB_SPEED_HIGH) {
pr_err("qdss_st_alt: qdss supportes HS or SS only\n");
+ ret = -EINVAL;
goto fail;
}
@@ -562,7 +567,7 @@
qdss->usb_connected = 1;
if (qdss->usb_connected && ch->app_conn)
- schedule_work(&qdss->connect_w);
+ queue_work(qdss->wq, &qdss->connect_w);
return 0;
fail:
@@ -610,7 +615,13 @@
spin_unlock_irqrestore(&d_lock, flags);
return -ENOMEM;
}
-
+ spin_unlock_irqrestore(&d_lock, flags);
+ qdss->wq = create_singlethread_workqueue(name);
+ if (!qdss->wq) {
+ kfree(qdss);
+ return -ENOMEM;
+ }
+ spin_lock_irqsave(&d_lock, flags);
ch = &qdss->ch;
ch->name = name;
list_add_tail(&ch->list, &usb_qdss_ch_list);
@@ -765,6 +776,13 @@
spin_unlock_irqrestore(&d_lock, flags);
return ERR_PTR(-ENOMEM);
}
+ spin_unlock_irqrestore(&d_lock, flags);
+ qdss->wq = create_singlethread_workqueue(name);
+ if (!qdss->wq) {
+ kfree(qdss);
+ return ERR_PTR(-ENOMEM);
+ }
+ spin_lock_irqsave(&d_lock, flags);
ch = &qdss->ch;
list_add_tail(&ch->list, &usb_qdss_ch_list);
} else {
@@ -781,7 +799,7 @@
/* the case USB cabel was connected befor qdss called qdss_open*/
if (qdss->usb_connected == 1)
- schedule_work(&qdss->connect_w);
+ queue_work(qdss->wq, &qdss->connect_w);
return ch;
}
@@ -819,7 +837,7 @@
_ch = list_entry(act, struct usb_qdss_ch, list);
qdss = container_of(_ch, struct f_qdss, ch);
spin_lock_irqsave(&d_lock, flags);
-
+ destroy_workqueue(qdss->wq);
if (!_ch->priv) {
list_del(&_ch->list);
kfree(qdss);
diff --git a/drivers/usb/gadget/f_qdss.h b/drivers/usb/gadget/f_qdss.h
index 93b5b1f..dcc80b7 100644
--- a/drivers/usb/gadget/f_qdss.h
+++ b/drivers/usb/gadget/f_qdss.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,7 @@
unsigned int data_enabled:1;
unsigned int ctrl_in_enabled:1;
unsigned int ctrl_out_enabled:1;
+ struct workqueue_struct *wq;
};
#endif
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 9a019f9..9a9a227 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -510,6 +510,12 @@
}
panel_data->panel_info.yres = (!rc ? tmp : 480);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-physical-width-dimension", &tmp);
+ panel_data->panel_info.physical_width = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-physical-height-dimension", &tmp);
+ panel_data->panel_info.physical_height = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-left-border", &tmp);
panel_data->panel_info.lcdc.xres_pad = (!rc ? tmp : 0);
rc = of_property_read_u32(np, "qcom,mdss-dsi-h-right-border", &tmp);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 3b8096b..24d4723 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1021,6 +1021,10 @@
fix->line_length = var->xres * bpp;
var->yres = panel_info->yres;
+ if (panel_info->physical_width)
+ var->width = panel_info->physical_width;
+ if (panel_info->physical_height)
+ var->height = panel_info->physical_height;
var->xres_virtual = var->xres;
var->yres_virtual = panel_info->yres * mfd->fb_page;
var->bits_per_pixel = bpp * 8; /* FrameBuffer color depth */
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 9c4e43a..38b587d 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -39,6 +39,7 @@
#define MAX_DOWNSCALE_RATIO 4
#define MAX_UPSCALE_RATIO 20
#define MAX_DECIMATION 4
+#define MDP_MIN_VBP 4
#define C3_ALPHA 3 /* alpha */
#define C2_R_Cr 2 /* R/Cr */
@@ -362,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_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index edd4c19..4a426cf 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -242,6 +242,7 @@
u32 *clk_rate)
{
struct mdss_mdp_pipe *pipe;
+ struct mdss_panel_info *pinfo = NULL;
int fps = DEFAULT_FRAME_RATE;
u32 v_total;
int i;
@@ -252,22 +253,21 @@
*clk_rate = 0;
if (!mixer->rotator_mode) {
- int is_writeback = false;
if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
- struct mdss_panel_info *pinfo;
pinfo = &mixer->ctl->panel_data->panel_info;
fps = mdss_panel_get_framerate(pinfo);
v_total = mdss_panel_get_vtotal(pinfo);
if (pinfo->type == WRITEBACK_PANEL)
- is_writeback = true;
+ pinfo = NULL;
} else {
v_total = mixer->height;
-
- is_writeback = true;
}
*clk_rate = mixer->width * v_total * fps;
- if (is_writeback) {
+ if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
+ *clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(*clk_rate);
+
+ if (!pinfo) {
/* perf for bus writeback */
*bus_ab_quota = fps * mixer->width * mixer->height * 3;
*bus_ab_quota >>= MDSS_MDP_BUS_FACTOR_SHIFT;
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_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index ebbf9e7..95eb381 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -3331,7 +3331,7 @@
unsigned int ptr;
ptr = (unsigned int) addr;
/* if request is outside the MDP reg-map or is not aligned 4 */
- if (ptr == 0x0 || ptr > 0x5138 || ptr % 0x4)
+ if (ptr > 0x5138 || ptr % 0x4)
goto end;
if (ptr >= 0x100 && ptr <= 0x5138) {
/* if ptr is in dspp range */
@@ -3386,7 +3386,8 @@
ret = 1;
else if (ptr == 0x2234 || ptr == 0x1e34 || ptr == 0x2634)
ret = 1;
- }
+ } else if (ptr == 0x0)
+ ret = 1;
end:
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index e8a6312..becf455 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -221,6 +221,8 @@
struct mdss_panel_info {
u32 xres;
u32 yres;
+ u32 physical_width;
+ u32 physical_height;
u32 bpp;
u32 type;
u32 wait_cycle;
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index c66d50d..a759e86 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -357,14 +357,20 @@
static int mhl_sii_wait_for_rgnd(struct mhl_tx_ctrl *mhl_ctrl)
{
int timeout;
- /* let isr handle RGND interrupt */
+
pr_debug("%s:%u\n", __func__, __LINE__);
INIT_COMPLETION(mhl_ctrl->rgnd_done);
+ /*
+ * after toggling reset line and enabling disc
+ * tx can take a while to generate intr
+ */
timeout = wait_for_completion_interruptible_timeout
- (&mhl_ctrl->rgnd_done, HZ);
+ (&mhl_ctrl->rgnd_done, HZ * 3);
if (!timeout) {
- /* most likely nothing plugged in USB */
- /* USB HOST connected or already in USB mode */
+ /*
+ * most likely nothing plugged in USB
+ * USB HOST connected or already in USB mode
+ */
pr_warn("%s:%u timedout\n", __func__, __LINE__);
return -ENODEV;
}
@@ -380,9 +386,25 @@
struct i2c_client *client = mhl_ctrl->i2c_handle;
unsigned long flags;
- enable_irq(client->irq);
+ if (!mhl_ctrl->irq_req_done) {
+ rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
+ &mhl_tx_isr,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ client->dev.driver->name, mhl_ctrl);
+ if (rc) {
+ pr_err("request_threaded_irq failed, status: %d\n",
+ rc);
+ return -EINVAL;
+ } else {
+ pr_debug("request_threaded_irq succeeded\n");
+ mhl_ctrl->irq_req_done = true;
+ }
+ } else {
+ enable_irq(client->irq);
+ }
+
/* wait for i2c interrupt line to be activated */
- msleep(300);
+ msleep(100);
if (id) {
/* When MHL cable is disconnected we get a sii8334
@@ -413,8 +435,10 @@
/* chipset PR recommends waiting for at least 100 ms
* the chipset needs longer to come out of D3 state.
*/
- msleep(300);
+ msleep(100);
mhl_init_reg_settings(mhl_ctrl, true);
+ /* allow tx to enable dev disc after D3 state */
+ msleep(100);
rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
} else {
if (mhl_ctrl->cur_state == POWER_STATE_D3) {
@@ -493,6 +517,10 @@
uint8_t i;
struct i2c_client *client = mhl_ctrl->i2c_handle;
+ /* Read the chip rev ID */
+ mhl_ctrl->chip_rev_id = MHL_SII_PAGE0_RD(0x04);
+ pr_debug("MHL: chip rev ID read=[%x]\n", mhl_ctrl->chip_rev_id);
+
/*
* REG_SRST
*/
@@ -1428,40 +1456,6 @@
return IRQ_HANDLED;
}
-static int mhl_tx_chip_init(struct mhl_tx_ctrl *mhl_ctrl)
-{
- uint8_t chip_rev_id = 0x00;
- struct i2c_client *client = mhl_ctrl->i2c_handle;
- unsigned long flags;
-
-
- spin_lock_irqsave(&mhl_ctrl->lock, flags);
- mhl_ctrl->dwnstream_hpd = 0;
- mhl_ctrl->tx_powered_off = false;
- spin_unlock_irqrestore(&mhl_ctrl->lock, flags);
-
- /* Reset the TX chip */
- mhl_sii_reset_pin(mhl_ctrl, 0);
- msleep(20);
- mhl_sii_reset_pin(mhl_ctrl, 1);
- /* TX PR-guide requires a 100 ms wait here */
- msleep(100);
-
- /* Read the chip rev ID */
- chip_rev_id = MHL_SII_PAGE0_RD(0x04);
- pr_debug("MHL: chip rev ID read=[%x]\n", chip_rev_id);
- mhl_ctrl->chip_rev_id = chip_rev_id;
-
- /*
- * Need to disable MHL discovery if
- * MHL-USB handshake is implemented
- */
- mhl_init_reg_settings(mhl_ctrl, true);
- switch_mode(mhl_ctrl, POWER_STATE_D3, true);
- pr_debug("%s:%u: power_down\n", __func__, __LINE__);
- mhl_tx_down(mhl_ctrl);
- return 0;
-}
static int mhl_sii_reg_config(struct i2c_client *client, bool enable)
{
@@ -1791,30 +1785,12 @@
}
}
- rc = mhl_tx_chip_init(mhl_ctrl);
- if (rc) {
- pr_err("%s: tx chip init failed [%d]\n",
- __func__, rc);
- goto failed_probe;
- }
+ mhl_ctrl->dwnstream_hpd = 0;
+ mhl_ctrl->tx_powered_off = false;
+
init_completion(&mhl_ctrl->rgnd_done);
- pr_debug("%s: IRQ from GPIO INTR = %d\n",
- __func__, mhl_ctrl->i2c_handle->irq);
- pr_debug("%s: Driver name = [%s]\n", __func__,
- client->dev.driver->name);
- rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
- &mhl_tx_isr,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- client->dev.driver->name, mhl_ctrl);
- if (rc) {
- pr_err("request_threaded_irq failed, status: %d\n",
- rc);
- goto failed_probe;
- } else {
- pr_debug("request_threaded_irq succeeded\n");
- }
mhl_ctrl->mhl_psy.name = "ext-vbus";
mhl_ctrl->mhl_psy.type = POWER_SUPPLY_TYPE_USB_DCP;
@@ -1940,15 +1916,21 @@
#if defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP)
static int mhl_i2c_suspend_sub(struct i2c_client *client)
{
- enable_irq_wake(client->irq);
- disable_irq(client->irq);
+ struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
+
+ if (mhl_ctrl->irq_req_done) {
+ enable_irq_wake(client->irq);
+ disable_irq(client->irq);
+ }
return 0;
}
static int mhl_i2c_resume_sub(struct i2c_client *client)
{
- disable_irq_wake(client->irq);
- enable_irq(client->irq);
+ struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
+
+ if (mhl_ctrl->irq_req_done)
+ disable_irq_wake(client->irq);
return 0;
}
#endif /* defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP) */
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index af8c332..4da38a4 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -23,7 +23,20 @@
#define FT5X36_ID 0x14
#define FT6X06_ID 0x06
+struct fw_upgrade_info {
+ bool auto_cal;
+ u16 delay_aa;
+ u16 delay_55;
+ u8 upgrade_id_1;
+ u8 upgrade_id_2;
+ u16 delay_readid;
+ u16 delay_erase_flash;
+};
+
struct ft5x06_ts_platform_data {
+ struct fw_upgrade_info info;
+ const char *name;
+ const char *fw_name;
u32 irqflags;
u32 irq_gpio;
u32 irq_gpio_flags;
@@ -38,6 +51,10 @@
u32 panel_miny;
u32 panel_maxx;
u32 panel_maxy;
+ u32 group_id;
+ u32 hard_rst_dly;
+ u32 soft_rst_dly;
+ u32 num_max_touches;
bool no_force_update;
bool i2c_pull_up;
int (*power_init) (bool);
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 73016d6..5df022e 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -35,8 +35,11 @@
* struct synaptics_rmi4_platform_data - rmi4 platform data
* @x_flip: x flip flag
* @y_flip: y flip flag
+ * @i2c_pull_up: pull up i2c bus with regulator
+ * @power_down_enable: enable complete regulator shutdown in suspend
* @irq_gpio: attention interrupt gpio
* @irq_flags: flags used by the irq
+ * @reset_flags: flags used by reset line
* @reset_gpio: reset gpio
* @panel_x: panel maximum values on the x
* @panel_y: panel maximum values on the y
@@ -47,6 +50,8 @@
bool x_flip;
bool y_flip;
bool i2c_pull_up;
+ bool power_down_enable;
+ bool disable_gpios;
unsigned irq_gpio;
u32 irq_flags;
u32 reset_flags;
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/mhl_8334.h b/include/linux/mhl_8334.h
index d1ee11c..71dec42 100644
--- a/include/linux/mhl_8334.h
+++ b/include/linux/mhl_8334.h
@@ -165,6 +165,7 @@
bool tx_powered_off;
uint8_t dwnstream_hpd;
bool mhl_det_discon;
+ bool irq_req_done;
};
int mhl_i2c_reg_read(struct i2c_client *client,
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 2cb297e..9d15908 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -67,6 +67,7 @@
#define MMC_HIGH_52_MAX_DTR 52000000
#define MMC_HIGH_DDR_MAX_DTR 52000000
#define MMC_HS200_MAX_DTR 200000000
+#define MMC_HS400_MAX_DTR 200000000
unsigned int sectors;
unsigned int card_type;
unsigned int hc_erase_size; /* In sectors */
@@ -329,6 +330,7 @@
#define MMC_CARD_SDXC (1<<6) /* card is SDXC */
#define MMC_CARD_REMOVED (1<<7) /* card has been removed */
#define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */
+#define MMC_STATE_HIGHSPEED_400 (1<<9) /* card is in HS400 mode */
#define MMC_STATE_DOING_BKOPS (1<<10) /* card is doing BKOPS */
#define MMC_STATE_NEED_BKOPS (1<<11) /* card needs to do BKOPS */
unsigned int quirks; /* card quirks */
@@ -347,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 */
@@ -426,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;
@@ -435,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), \
@@ -450,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 | \
@@ -502,6 +523,7 @@
#define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED)
#define mmc_card_hs200(c) ((c)->state & MMC_STATE_HIGHSPEED_200)
+#define mmc_card_hs400(c) ((c)->state & MMC_STATE_HIGHSPEED_400)
#define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
#define mmc_card_ddr_mode(c) ((c)->state & MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED)
@@ -514,9 +536,14 @@
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+#define mmc_card_clr_highspeed(c) ((c)->state &= ~MMC_STATE_HIGHSPEED)
#define mmc_card_set_hs200(c) ((c)->state |= MMC_STATE_HIGHSPEED_200)
+#define mmc_card_clr_hs200(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_200)
+#define mmc_card_set_hs400(c) ((c)->state |= MMC_STATE_HIGHSPEED_400)
+#define mmc_card_clr_hs400(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_400)
#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
#define mmc_card_set_ddr_mode(c) ((c)->state |= MMC_STATE_HIGHSPEED_DDR)
+#define mmc_card_clr_ddr_mode(c) ((c)->state &= ~MMC_STATE_HIGHSPEED_DDR)
#define mmc_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED)
#define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index dbafdfc..e1dbd21 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -61,6 +61,7 @@
#define MMC_TIMING_UHS_SDR104 4
#define MMC_TIMING_UHS_DDR50 5
#define MMC_TIMING_MMC_HS200 6
+#define MMC_TIMING_MMC_HS400 7
#define MMC_SDR_MODE 0
#define MMC_1_2V_DDR_MODE 1
@@ -245,6 +246,7 @@
/* DDR mode at 1.8V */
#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */
/* DDR mode at 1.2V */
+#define MMC_CAP_HSDDR (MMC_CAP_1_8V_DDR | MMC_CAP_1_2V_DDR)
#define MMC_CAP_POWER_OFF_CARD (1 << 13) /* Can power off after boot */
#define MMC_CAP_BUS_WIDTH_TEST (1 << 14) /* CMD14/CMD19 bus width ok */
#define MMC_CAP_UHS_SDR12 (1 << 15) /* Host supports UHS SDR12 mode */
@@ -295,6 +297,11 @@
#define MMC_CAP2_CORE_RUNTIME_PM (1 << 19)
/* Allows Asynchronous SDIO irq while card is in 4-bit mode */
#define MMC_CAP2_ASYNC_SDIO_IRQ_4BIT_MODE (1 << 20)
+
+#define MMC_CAP2_HS400_1_8V (1 << 21) /* can support */
+#define MMC_CAP2_HS400_1_2V (1 << 22) /* can support */
+#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
+ MMC_CAP2_HS400_1_2V)
mmc_pm_flag_t pm_caps; /* supported pm features */
int clk_requests; /* internal reference counter */
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index de145d6..764beec 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -52,6 +52,7 @@
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
+#define MMC_SEND_TUNING_BLOCK_HS400 MMC_SEND_TUNING_BLOCK_HS200
/* class 3 */
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
@@ -328,6 +329,8 @@
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
+#define EXT_CSD_PWR_CL_DDR_200_195 253 /* RO */
+#define EXT_CSD_PWR_CL_DDR_200_360 254 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
@@ -359,7 +362,7 @@
#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */
-#define EXT_CSD_CARD_TYPE_MASK 0x3F /* Mask out reserved bits */
+#define EXT_CSD_CARD_TYPE_MASK 0xFF /* Mask out reserved bits */
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
/* DDR mode @1.8V or 3V I/O */
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
@@ -369,6 +372,14 @@
#define EXT_CSD_CARD_TYPE_SDR_1_8V (1<<4) /* Card can run at 200MHz */
#define EXT_CSD_CARD_TYPE_SDR_1_2V (1<<5) /* Card can run at 200MHz */
/* SDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_SDR_1_8V \
+ | EXT_CSD_CARD_TYPE_SDR_1_2V)
+#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz */
+ /* DDR mode @1.8V I/O */
+#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz */
+ /* DDR mode @1.2V I/O */
+#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V \
+ | EXT_CSD_CARD_TYPE_HS400_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 424b1d9..186fff1 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -190,6 +190,7 @@
#define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */
#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
#define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */
+#define SDHCI_HS400_NEEDS_TUNING (1<<11) /* HS400 needs tuning */
unsigned int version; /* SDHCI spec. version */
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/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 af2c53e..c0448f2 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -24,6 +24,7 @@
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
#include <linux/mfd/wcd9xxx/wcd9306_registers.h>
#include <linux/mfd/wcd9xxx/pdata.h>
+#include <linux/regulator/consumer.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -41,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);
@@ -58,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
@@ -189,6 +200,12 @@
0, /* AIF1_CAP */
};
+enum {
+ CP_REG_BUCK = 0,
+ CP_REG_BHELPER,
+ CP_REG_MAX,
+};
+
struct tapan_priv {
struct snd_soc_codec *codec;
u32 adc_count;
@@ -224,6 +241,9 @@
/* class h specific data */
struct wcd9xxx_clsh_cdc_data clsh_d;
+
+ /* pointers to regulators required for chargepump */
+ struct regulator *cp_regulators[CP_REG_MAX];
};
static const u32 comp_shift[] = {
@@ -758,6 +778,9 @@
int i;
for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (pdata->regulator[i].name == NULL)
+ continue;
+
if (!strncmp(pdata->regulator[i].name,
WCD9XXX_SUPPLY_BUCK_NAME,
sizeof(WCD9XXX_SUPPLY_BUCK_NAME))) {
@@ -768,8 +791,13 @@
buck_volt = pdata->regulator[i].min_uV;
break;
}
+ dev_err(codec->dev,
+ "%s: Failed to find regulator for %s\n",
+ __func__, WCD9XXX_SUPPLY_BUCK_NAME);
}
- pr_debug("%s: S4 voltage requested is %d\n", __func__, buck_volt);
+ dev_dbg(codec->dev,
+ "%s: S4 voltage requested is %d\n",
+ __func__, buck_volt);
return buck_volt;
}
@@ -948,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),
@@ -970,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),
@@ -999,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),
@@ -1016,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),
@@ -1064,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),
@@ -1071,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[] = {
@@ -1088,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"
};
@@ -1194,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);
@@ -1283,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);
@@ -2497,90 +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"},
{"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"},
-
- {"HPHR", NULL, "HPHR_PA_MIXER"},
- {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
- {"HPHR DAC", NULL, "RX_BIAS"},
-
{"ANC HEADPHONE", NULL, "ANC HPHL"},
{"ANC HEADPHONE", NULL, "ANC HPHR"},
@@ -2608,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"},
@@ -2618,34 +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"},
@@ -2654,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"},
@@ -2732,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"},
@@ -2759,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"},
@@ -2769,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"},
@@ -2808,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"},
@@ -2823,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)
@@ -2964,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);
@@ -2973,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);
@@ -2981,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);
@@ -3415,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",
@@ -3766,11 +3959,147 @@
return ret;
}
+static int tapan_codec_chargepump_vdd_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+ int ret = 0, i;
+
+ pr_info("%s: event = %d\n", __func__, event);
+
+
+ if (!priv->cp_regulators[CP_REG_BUCK]
+ && !priv->cp_regulators[CP_REG_BHELPER]) {
+ pr_err("%s: No power supply defined for ChargePump\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ for (i = 0; i < CP_REG_MAX ; i++) {
+ if (!priv->cp_regulators[i])
+ continue;
+
+ ret = regulator_enable(priv->cp_regulators[i]);
+ if (ret) {
+ pr_err("%s: CP Regulator enable failed, index = %d\n",
+ __func__, i);
+ continue;
+ } else {
+ pr_debug("%s: Enabled CP regulator, index %d\n",
+ __func__, i);
+ }
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (i = 0; i < CP_REG_MAX; i++) {
+ if (!priv->cp_regulators[i])
+ continue;
+
+ ret = regulator_disable(priv->cp_regulators[i]);
+ if (ret) {
+ pr_err("%s: CP Regulator disable failed, index = %d\n",
+ __func__, i);
+ return ret;
+ } else {
+ pr_debug("%s: Disabled CP regulator %d\n",
+ __func__, i);
+ }
+ }
+ break;
+ }
+ 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,
@@ -3824,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),
@@ -3844,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 |
@@ -3864,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),
@@ -3882,6 +4192,11 @@
tapan_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMD),
+ /* CDC_CP_VDD */
+ SND_SOC_DAPM_SUPPLY("CDC_CP_VDD", SND_SOC_NOPM, 0, 0,
+ tapan_codec_chargepump_vdd_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
/*EAR */
SND_SOC_DAPM_PGA_E("EAR PA", TAPAN_A_RX_EAR_EN, 4, 0, NULL, 0,
tapan_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU |
@@ -3922,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),
@@ -3984,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 |
@@ -4035,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 |
@@ -4071,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,
@@ -4102,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),
@@ -4710,6 +4972,93 @@
return 0;
}
+static struct regulator *tapan_codec_find_regulator(
+ struct snd_soc_codec *codec,
+ const char *name)
+{
+ int i;
+ struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+ for (i = 0; i < core->num_of_supplies; i++) {
+ if (core->supplies[i].supply &&
+ !strcmp(core->supplies[i].supply, name))
+ return core->supplies[i].consumer;
+ }
+ 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;
@@ -4752,6 +5101,11 @@
return ret;
}
+ tapan->cp_regulators[CP_REG_BUCK] = tapan_codec_find_regulator(codec,
+ WCD9XXX_SUPPLY_BUCK_NAME);
+ tapan->cp_regulators[CP_REG_BHELPER] = tapan_codec_find_regulator(codec,
+ "cdc-vdd-buckhelper");
+
tapan->clsh_d.buck_mv = tapan_codec_get_buck_mv(codec);
/*
* If 1.8 volts is requested on the vdd_cp line, then
@@ -4822,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));
@@ -4860,6 +5226,7 @@
static int tapan_codec_remove(struct snd_soc_codec *codec)
{
struct tapan_priv *tapan = snd_soc_codec_get_drvdata(codec);
+ int index = 0;
WCD9XXX_BG_CLK_LOCK(&tapan->resmgr);
atomic_set(&kp_tapan_priv, 0);
@@ -4876,6 +5243,9 @@
/* cleanup resmgr */
wcd9xxx_resmgr_deinit(&tapan->resmgr);
+ for (index = 0; index < CP_REG_MAX; index++)
+ tapan->cp_regulators[index] = NULL;
+
kfree(tapan);
return 0;
}
@@ -4894,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),
};
@@ -4928,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);