Merge "msm: clock-rpm: Remove last_set_khz/last_set_sleep_khz from rpm clk"
diff --git a/Documentation/devicetree/bindings/arm/arch_timer.txt b/Documentation/devicetree/bindings/arm/arch_timer.txt
index eb3986e..7851d53 100644
--- a/Documentation/devicetree/bindings/arm/arch_timer.txt
+++ b/Documentation/devicetree/bindings/arm/arch_timer.txt
@@ -6,7 +6,7 @@
The timer is attached to a GIC to deliver its two per-processor
interrupts (one for the secure mode, one for the non-secure mode).
-** Timer node properties:
+** CP15 Timer node properties:
- compatible : Should be "arm,armv7-timer"
@@ -21,3 +21,52 @@
interrupts = <1 13 0xf08 1 14 0xf08>;
clock-frequency = <100000000>;
};
+
+** Memory mapped timer node properties:
+
+- compatible : Should at least contain "arm,armv7-timer-mem".
+
+- clock-frequency : The frequency of the main counter, in Hz. Optional.
+
+- reg : The control frame base address.
+
+Note that #address-cells, #size-cells, and ranges shall be present to ensure
+the CPU can address the frame's registers.
+
+Each timer node has up to 8 frame sub-nodes with the following properties:
+
+- frame-number: 0 to 7.
+
+- interrupts : Interrupt list for physical and virtual timers in that order.
+ The virtual timer interrupt is optional.
+
+- reg : The first and second view base addresses in that order. The second view
+ base address is optional.
+
+- status : "disabled" indicates the frame is not available for use. Optional.
+
+Example:
+
+ timer@f0000000 {
+ compatible = "arm,armv7-timer-mem";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg = <0xf0000000 0x1000>;
+ clock-frequency = <50000000>;
+
+ frame0@f0001000 {
+ frame-number = <0>
+ interrupts = <0 13 0x8>,
+ <0 14 0x8>;
+ reg = <0xf0001000 0x1000>,
+ <0xf0002000 0x1000>;
+ };
+
+ frame1@f0003000 {
+ frame-number = <1>
+ interrupts = <0 15 0x8>;
+ reg = <0xf0003000 0x1000>;
+ status = "disabled";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index f5465a4..b8a39d3 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -7,12 +7,12 @@
Each of these peripherals are implemented as subnodes in the example at the
end of this file.
-- qcom,chg-chgr: Supports charging control and status
+- qcom,chgr: Supports charging control and status
reporting.
-- qcom,chg-bat-if: Battery status reporting such as presence,
+- qcom,bat-if: Battery status reporting such as presence,
temperature reporting and voltage collapse
protection.
-- qcom,chg-buck: Charger buck configuration and status
+- qcom,buck: Charger buck configuration and status
reporting with regards to several regulation
loops such as vdd, ibat etc.
- qcom,usb-chgpth: USB charge path detection and input current
@@ -23,38 +23,38 @@
settings, comparator override features etc.
Parent node required properties:
-- qcom,chg-vddmax-mv: Target voltage of battery in mV.
-- qcom,chg-vddsafe-mv: Maximum Vdd voltage in mV.
-- qcom,chg-vinmin-mv: Minimum input voltage in mV.
-- qcom,chg-ibatmax-ma: Maximum battery charge current in mA
-- qcom,chg-ibatsafe-ma: Safety battery current setting
-- qcom,chg-thermal-mitigation: Array of ibatmax values for different
+- qcom,vddmax-mv: Target voltage of battery in mV.
+- qcom,vddsafe-mv: Maximum Vdd voltage in mV.
+- qcom,vinmin-mv: Minimum input voltage in mV.
+- qcom,ibatmax-ma: Maximum battery charge current in mA
+- qcom,ibatsafe-ma: Safety battery current setting
+- qcom,thermal-mitigation: Array of ibatmax values for different
system thermal mitigation level.
Parent node optional properties:
-- qcom,chg-ibatterm-ma: Current at which charging is terminated when
+- qcom,ibatterm-ma: Current at which charging is terminated when
the analog end of charge option is selected.
-- qcom,chg-maxinput-usb-ma: Maximum input current USB.
-- qcom,chg-maxinput-dc-ma: Maximum input current DC.
-- qcom,chg-vbatdet-delta-mv: Battery charging resume delta.
-- qcom,chg-charging-disabled: Set this property to disable charging
+- qcom,maxinput-usb-ma: Maximum input current USB.
+- qcom,maxinput-dc-ma: Maximum input current DC.
+- qcom,vbatdet-delta-mv: Battery charging resume delta.
+- qcom,charging-disabled: Set this property to disable charging
by default. This can then be overriden
writing the the module parameter
"charging_disabled".
-- qcom,chg-use-default-batt-values: Set this flag to force reporting of
+- qcom,use-default-batt-values: Set this flag to force reporting of
battery temperature of 250 decidegree
Celsius, state of charge to be 50%
and disable charging.
-- qcom,chg-warm-bat-decidegc: Warm battery temperature in decidegC.
-- qcom,chg-cool-bat-decidegc: Cool battery temperature in decidegC.
+- qcom,warm-bat-decidegc: Warm battery temperature in decidegC.
+- qcom,cool-bat-decidegc: Cool battery temperature in decidegC.
Note that if both warm and cool battery
temperatures are set, the corresponding
ibatmax and bat-mv properties are
required to be set.
-- qcom,chg-ibatmax-cool-ma: Maximum cool battery charge current.
-- qcom,chg-ibatmax-warm-ma: Maximum warm battery charge current.
-- qcom,chg-warm-bat-mv: Warm temperature battery target voltage.
-- qcom,chg-cool-bat-mv: Cool temperature battery target voltage.
+- qcom,ibatmax-cool-ma: Maximum cool battery charge current.
+- qcom,ibatmax-warm-ma: Maximum warm battery charge current.
+- qcom,warm-bat-mv: Warm temperature battery target voltage.
+- qcom,cool-bat-mv: Cool temperature battery target voltage.
Sub node required structure:
- A qcom,chg node must be a child of an SPMI node that has specified
@@ -77,13 +77,13 @@
qcom,usb-chgpth:
- usbin-valid
- qcom,chg-chgr:
+ qcom,chgr:
- chg-done
- chg-failed
The following interrupts are available:
- qcom,chg-chgr:
+ qcom,chgr:
- chg-done: Triggers on charge completion.
- chg-failed: Notifies of charge failures.
- fast-chg-on: Notifies of fast charging state.
@@ -98,7 +98,7 @@
setting, can be used as
battery alarm.
- qcom,chg-buck:
+ qcom,buck:
- vdd-loop: VDD loop change interrupt.
- ibat-loop: Ibat loop change interrupt.
- ichg-loop: Charge current loop change.
@@ -107,7 +107,7 @@
- vref-ov: Reference overvoltage interrupt.
- vbat-ov: Battery overvoltage interrupt.
- qcom,chg-bat-if:
+ qcom,bat-if:
- psi: PMIC serial interface interrupt.
- vcp-on: Voltage collapse protection
status interrupt.
@@ -140,22 +140,22 @@
#address-cells = <1>;
#size-cells = <1>;
- qcom,chg-vddmax-mv = <4200>;
- qcom,chg-vddsafe-mv = <4200>;
- qcom,chg-vinmin-mv = <4200>;
- qcom,chg-ibatmax-ma = <1500>;
- qcom,chg-ibatterm-ma = <200>;
- qcom,chg-ibatsafe-ma = <1500>;
- qcom,chg-thermal-mitigation = <1500 700 600 325>;
- qcom,chg-cool-bat-degc = <10>;
- qcom,chg-cool-bat-mv = <4100>;
- qcom,chg-ibatmax-warm-ma = <350>;
- qcom,chg-warm-bat-degc = <45>;
- qcom,chg-warm-bat-mv = <4100>;
- qcom,chg-ibatmax-cool-ma = <350>;
- qcom,chg-vbatdet-delta-mv = <60>;
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4200>;
+ qcom,ibatmax-ma = <1500>;
+ qcom,ibatterm-ma = <200>;
+ qcom,ibatsafe-ma = <1500>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,cool-bat-degc = <10>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <350>;
+ qcom,warm-bat-degc = <45>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,ibatmax-cool-ma = <350>;
+ qcom,vbatdet-delta-mv = <60>;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
reg = <0x1000 0x100>;
interrupts = <0x0 0x10 0x0>,
<0x0 0x10 0x1>,
@@ -176,7 +176,7 @@
"vbat-det-lo";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
reg = <0x1100 0x100>;
interrupts = <0x0 0x11 0x0>,
<0x0 0x11 0x1>,
@@ -195,7 +195,7 @@
"vbat-ov";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
<0x0 0x12 0x1>,
@@ -210,7 +210,7 @@
"batt-pres";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
<0 0x13 0x1>,
@@ -221,7 +221,7 @@
"chg-gone";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
reg = <0x1400 0x100>;
interrupts = <0x0 0x14 0x0>,
<0x0 0x14 0x1>;
@@ -230,7 +230,7 @@
"coarse-det-dc";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
<0x0 0x15 0x1>;
@@ -239,7 +239,7 @@
"boost-pwr-ok";
};
- qcom,chg-misc@1600 {
+ qcom,misc@1600 {
reg = <0x1600 0x100>;
};
};
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index ffea58f..777933a 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -35,6 +35,10 @@
- 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.
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+ hardware probe. Supplies in this list will be
+ stay enabled.
+
- qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
- qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
@@ -67,6 +71,11 @@
values for 9.6MHZ mclk can be 2400000 Hz, 3200000 Hz
and 4800000 Hz. The values for 12.288MHz mclk can be
3072200 Hz, 4096000 Hz and 6144000 Hz.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+ dynamically.
+ Supplies in this list are off by default.
+
Example:
taiko_codec {
@@ -103,6 +112,16 @@
qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
qcom,cdc-vddcx-2-current = <5000>;
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v",
+ "cdc-vddcx-1",
+ "cdc-vddcx-2";
+
+ com,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -155,6 +174,10 @@
- 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.
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+ hardware probe. Supplies in this list will be
+ stay enabled.
+
- qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
- qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
@@ -179,6 +202,20 @@
- qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
codec.
+Optional properties:
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+ dynamically.
+ Supplies in this list are off by default.
+
Example:
i2c@f9925000 {
cell-index = <3>;
@@ -228,6 +265,16 @@
qcom,cdc-vddcx-2-voltage = <1200000 1200000>;
qcom,cdc-vddcx-2-current = <10000>;
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v",
+ "cdc-vddcx-1",
+ "cdc-vddcx-2";
+
+ com,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index e394b56..c130b26 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -7,8 +7,8 @@
Required properties:
- compatible: "wcnss_wlan"
-- reg: offset and length of the register set for the device. The pair
- corresponds to PRONTO.
+- reg: physical address and length of the register set for the device.
+- reg-names: "wcnss_mmio", "wcnss_fiq"
- interupts: Pronto to Apps interrupts for tx done and rx pending.
- qcom,pronto-vddmx-supply: regulator to supply pronto pll.
- qcom,pronto-vddcx-supply: regulator to supply WLAN/BT/FM digital module.
@@ -25,8 +25,9 @@
qcom,wcnss-wlan@fb000000 {
compatible = "qcom,wcnss_wlan";
- reg = <0xfb000000 0x280000>;
- reg-names = "wcnss_mmio";
+ reg = <0xfb000000 0x280000>,
+ <0xf9011008 0x04>;
+ reg-names = "wcnss_mmio", "wcnss_fiq";
interrupts = <0 145 0 0 146 0>;
interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index c52b7dd..c0c9107 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -38,7 +38,7 @@
qcom,mdss-pan-dsi-stream = <0>;
qcom,mdss-pan-dsi-mdp-tr = <0x0>;
qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
20 00 01];
qcom,panel-phy-timingSettings = [7d 25 1d 00 37 33
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index 7bd95e7..448d357 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -36,7 +36,7 @@
qcom,mdss-pan-dsi-stream = <0>;
qcom,mdss-pan-dsi-mdp-tr = <0x0>;
qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
qcom,panel-phy-regulatorSettings = [03 01 01 00 /* Regualotor settings */
20 00 01];
qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index 98074c8..9a734a0 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -37,7 +37,7 @@
qcom,mdss-pan-dsi-stream = <0>;
qcom,mdss-pan-dsi-mdp-tr = <0x04>;
qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
qcom,on-cmds-dsi-state = "DSI_LP_MODE";
qcom,panel-off-cmds = [22 01 00 00 00 02 00 00];
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index 42f6033..2937cde 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -40,7 +40,7 @@
qcom,mdss-pan-dsi-stream = <0>;
qcom,mdss-pan-dsi-mdp-tr = <0x0>;
qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-frame-rate = <60>;
+ qcom,mdss-pan-dsi-frame-rate = <60>;
qcom,panel-phy-regulatorSettings = [07 09 03 00 /* Regualotor settings */
20 00 01];
qcom,panel-phy-timingSettings = [b0 23 1b 00 94 93
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index f702abb..161b580 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -56,16 +56,16 @@
#size-cells = <1>;
status = "disabled";
- qcom,chg-vddmax-mv = <4200>;
- qcom,chg-vddsafe-mv = <4200>;
- qcom,chg-vinmin-mv = <4200>;
- qcom,chg-vbatdet-mv = <4100>;
- qcom,chg-ibatmax-ma = <1500>;
- qcom,chg-ibatterm-ma = <200>;
- qcom,chg-ibatsafe-ma = <1500>;
- qcom,chg-thermal-mitigation = <1500 700 600 325>;
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4200>;
+ qcom,vbatdet-mv = <4100>;
+ qcom,ibatmax-ma = <1500>;
+ qcom,ibatterm-ma = <200>;
+ qcom,ibatsafe-ma = <1500>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "disabled";
reg = <0x1000 0x100>;
interrupts = <0x0 0x10 0x0>,
@@ -87,7 +87,7 @@
"chg-done";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "disabled";
reg = <0x1100 0x100>;
interrupts = <0x0 0x11 0x0>,
@@ -107,7 +107,7 @@
"vdd-loop";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
@@ -124,7 +124,7 @@
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "disabled";
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
@@ -136,7 +136,7 @@
"chg-gone";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "disabled";
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 1881311..21606e2 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -171,21 +171,21 @@
#size-cells = <1>;
status = "disabled";
- qcom,chg-vddmax-mv = <4200>;
- qcom,chg-vddsafe-mv = <4200>;
- qcom,chg-vinmin-mv = <4200>;
- qcom,chg-ibatmax-ma = <1500>;
- qcom,chg-ibatsafe-ma = <1500>;
- qcom,chg-thermal-mitigation = <1500 700 600 325>;
- qcom,chg-cool-bat-decidegc = <100>;
- qcom,chg-cool-bat-mv = <4100>;
- qcom,chg-ibatmax-warm-ma = <350>;
- qcom,chg-warm-bat-decidegc = <450>;
- qcom,chg-warm-bat-mv = <4100>;
- qcom,chg-ibatmax-cool-ma = <350>;
- qcom,chg-vbatdet-delta-mv = <350>;
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4200>;
+ qcom,ibatmax-ma = <1500>;
+ qcom,ibatsafe-ma = <1500>;
+ qcom,thermal-mitigation = <1500 700 600 325>;
+ qcom,cool-bat-decidegc = <100>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <350>;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,ibatmax-cool-ma = <350>;
+ qcom,vbatdet-delta-mv = <350>;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "disabled";
reg = <0x1000 0x100>;
interrupts = <0x0 0x10 0x0>,
@@ -207,7 +207,7 @@
"chg-done";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "disabled";
reg = <0x1100 0x100>;
interrupts = <0x0 0x11 0x0>,
@@ -227,7 +227,7 @@
"vdd-loop";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
@@ -244,7 +244,7 @@
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "disabled";
reg = <0x1300 0x100>;
interrupts = <0 0x13 0x0>,
@@ -256,7 +256,7 @@
"chg-gone";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
status = "disabled";
reg = <0x1400 0x100>;
interrupts = <0x0 0x14 0x0>,
@@ -266,7 +266,7 @@
"dcin-valid";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "disabled";
reg = <0x1500 0x100>;
interrupts = <0x0 0x15 0x0>,
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index bf2ab4f..510bb7d 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -272,6 +272,6 @@
};
&pm8226_chg {
- qcom,chg-charging-disabled;
- qcom,chg-use-default-batt-values;
+ qcom,charging-disabled;
+ qcom,use-default-batt-values;
};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 16a7177..f8a4e31 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -65,6 +65,65 @@
clock-frequency = <19200000>;
};
+ timer@f9020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xf9020000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@f9021000 {
+ frame-number = <0>;
+ interrupts = <0 8 0x4>,
+ <0 7 0x4>;
+ reg = <0xf9021000 0x1000>,
+ <0xf9022000 0x1000>;
+ };
+
+ frame@f9023000 {
+ frame-number = <1>;
+ interrupts = <0 9 0x4>;
+ reg = <0xf9023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9024000 {
+ frame-number = <2>;
+ interrupts = <0 10 0x4>;
+ reg = <0xf9024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9025000 {
+ frame-number = <3>;
+ interrupts = <0 11 0x4>;
+ reg = <0xf9025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9026000 {
+ frame-number = <4>;
+ interrupts = <0 12 0x4>;
+ reg = <0xf9026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9027000 {
+ frame-number = <5>;
+ interrupts = <0 13 0x4>;
+ reg = <0xf9027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9028000 {
+ frame-number = <6>;
+ interrupts = <0 14 0x4>;
+ reg = <0xf9028000 0x1000>;
+ status = "disabled";
+ };
+ };
+
qcom,vidc@fdc00000 {
compatible = "qcom,msm-vidc";
reg = <0xfdc00000 0xff000>;
@@ -234,6 +293,12 @@
qcom,cdc-vdd-cx-voltage = <1200000 1200000>;
qcom,cdc-vdd-cx-current = <10000>;
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-h",
+ "cdc-vdd-px",
+ "cdc-vdd-a-1p2v",
+ "cdc-vdd-cx";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <1800>;
@@ -412,8 +477,9 @@
qcom,wcnss-wlan@fb000000 {
compatible = "qcom,wcnss_wlan";
- reg = <0xfb000000 0x280000>;
- reg-names = "wcnss_mmio";
+ reg = <0xfb000000 0x280000>,
+ <0xf9011008 0x04>;
+ reg-names = "wcnss_mmio", "wcnss_fiq";
interrupts = <0 145 0 0 146 0>;
interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
@@ -950,23 +1016,23 @@
&pm8226_chg {
status = "ok";
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "ok";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "ok";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
status = "ok";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "ok";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8610-ion.dtsi b/arch/arm/boot/dts/msm8610-ion.dtsi
index 848a6f5..41b58da 100644
--- a/arch/arm/boot/dts/msm8610-ion.dtsi
+++ b/arch/arm/boot/dts/msm8610-ion.dtsi
@@ -35,14 +35,6 @@
qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
qcom,memory-reservation-size = <0x100000>;
};
-
- qcom,ion-heap@28 { /* AUDIO HEAP */
- compatible = "qcom,msm-ion-reserve";
- reg = <28>;
- qcom,heap-align = <0x1000>;
- qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
- qcom,memory-reservation-size = <0x314000>;
- };
};
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 91d3bc0..0319128 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -235,6 +235,19 @@
<85 512 40000 160000>;
};
+ wlan0: qca,wlan {
+ compatible = "qca,ar6004-hsic";
+ qcom,msm-bus,name = "wlan";
+ qcom,msm-bus,num-cases = <5>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <85 512 0 0>,
+ <85 512 40000 160000>,
+ <85 512 40000 320000>,
+ <85 512 40000 480000>,
+ <85 512 40000 640000>;
+ };
};
&spmi_bus {
@@ -381,23 +394,23 @@
&pm8941_chg {
status = "ok";
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "ok";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "ok";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "ok";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
status = "ok";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index de370e7..79e6371 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -355,27 +355,27 @@
status = "ok";
qcom,chg-charging-disabled;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "ok";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "ok";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
status = "ok";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "ok";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
status = "ok";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 0ae20a0..be890b1 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -736,25 +736,25 @@
&pm8941_chg {
status = "ok";
- qcom,chg-charging-disabled;
+ qcom,charging-disabled;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "ok";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "ok";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "ok";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
status = "ok";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index a81fc20..cd83668 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -338,27 +338,27 @@
status = "ok";
qcom,chg-charging-disabled;
- qcom,chg-chgr@1000 {
+ qcom,chgr@1000 {
status = "ok";
};
- qcom,chg-buck@1100 {
+ qcom,buck@1100 {
status = "ok";
};
- qcom,chg-bat-if@1200 {
+ qcom,bat-if@1200 {
status = "ok";
};
- qcom,chg-usb-chgpth@1300 {
+ qcom,usb-chgpth@1300 {
status = "ok";
};
- qcom,chg-dc-chgpth@1400 {
+ qcom,dc-chgpth@1400 {
status = "ok";
};
- qcom,chg-boost@1500 {
+ qcom,boost@1500 {
status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 8f2ef31..8ab24df 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -23,7 +23,7 @@
};
&pm8941_chg {
- qcom,chg-charging-disabled;
+ qcom,charging-disabled;
};
&sdcc1 {
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 6cb9f09..09ea84b 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -22,5 +22,5 @@
};
&pm8941_chg {
- qcom,chg-charging-disabled;
+ qcom,charging-disabled;
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 273c677..a7ea5c3 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -84,6 +84,66 @@
clock-frequency = <19200000>;
};
+ timer@f9020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xf9020000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@f9021000 {
+ frame-number = <0>;
+ interrupts = <0 8 0x4>,
+ <0 7 0x4>;
+ reg = <0xf9021000 0x1000>,
+ <0xf9022000 0x1000>;
+ };
+
+ frame@f9023000 {
+ frame-number = <1>;
+ interrupts = <0 9 0x4>;
+ reg = <0xf9023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9024000 {
+ frame-number = <2>;
+ interrupts = <0 10 0x4>;
+ reg = <0xf9024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9025000 {
+ frame-number = <3>;
+ interrupts = <0 11 0x4>;
+ reg = <0xf9025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9026000 {
+ frame-number = <4>;
+ interrupts = <0 12 0x4>;
+ reg = <0xf9026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9027000 {
+ frame-number = <5>;
+ interrupts = <0 13 0x4>;
+ reg = <0xf9027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9028000 {
+ frame-number = <6>;
+ interrupts = <0 14 0x4>;
+ reg = <0xf9028000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+
qcom,mpm2-sleep-counter@fc4a3000 {
compatible = "qcom,mpm2-sleep-counter";
reg = <0xfc4a3000 0x1000>;
@@ -573,6 +633,14 @@
qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
qcom,cdc-vddcx-2-current = <10000>;
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v",
+ "cdc-vddcx-1",
+ "cdc-vddcx-2";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
@@ -1058,8 +1126,9 @@
qcom,wcnss-wlan@fb000000 {
compatible = "qcom,wcnss_wlan";
- reg = <0xfb000000 0x280000>;
- reg-names = "wcnss_mmio";
+ reg = <0xfb000000 0x280000>,
+ <0xf9011008 0x04>;
+ reg-names = "wcnss_mmio", "wcnss_fiq";
interrupts = <0 145 0 0 146 0>;
interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 0e98aa8..7faa07d 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -66,6 +66,72 @@
clock-frequency = <19200000>;
};
+ timer@f9020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xf9020000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@f9021000 {
+ frame-number = <0>;
+ interrupts = <0 7 0x4>,
+ <0 6 0x4>;
+ reg = <0xf9021000 0x1000>,
+ <0xf9022000 0x1000>;
+ };
+
+ frame@f9023000 {
+ frame-number = <1>;
+ interrupts = <0 8 0x4>;
+ reg = <0xf9023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9024000 {
+ frame-number = <2>;
+ interrupts = <0 9 0x4>;
+ reg = <0xf9024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9025000 {
+ frame-number = <3>;
+ interrupts = <0 10 0x4>;
+ reg = <0xf9025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9026000 {
+ frame-number = <4>;
+ interrupts = <0 11 0x4>;
+ reg = <0xf9026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9027000 {
+ frame-number = <5>;
+ interrupts = <0 12 0x4>;
+ reg = <0xf9027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9028000 {
+ frame-number = <6>;
+ interrupts = <0 13 0x4>;
+ reg = <0xf9028000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@f9029000 {
+ frame-number = <7>;
+ interrupts = <0 14 0x4>;
+ reg = <0xf9029000 0x1000>;
+ status = "disabled";
+ };
+ };
+
qcom,sps@f9980000 {
compatible = "qcom,msm_sps";
reg = <0xf9984000 0x15000>,
@@ -505,6 +571,14 @@
qcom,cdc-vddcx-2-voltage = <1200000 1200000>;
qcom,cdc-vddcx-2-current = <10000>;
+ qcom,cdc-static-supplies = "cdc-vdd-buck",
+ "cdc-vdd-tx-h",
+ "cdc-vdd-rx-h",
+ "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v",
+ "cdc-vddcx-1",
+ "cdc-vddcx-2";
+
qcom,cdc-micbias-ldoh-v = <0x3>;
qcom,cdc-micbias-cfilt1-mv = <1800>;
qcom,cdc-micbias-cfilt2-mv = <2700>;
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 7e835f6..3291919 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -329,7 +329,6 @@
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
CONFIG_MSM_IOMMU=y
-CONFIG_MSM_IOMMU_PMON=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_TMC=y
CONFIG_CORESIGHT_TPIU=y
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 3b92171..705275c 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -1097,8 +1097,9 @@
ARRAY_SIZE(msm_blsp2_uart7_configs));
msm_gpiomux_install(wcnss_5wire_interface,
ARRAY_SIZE(wcnss_5wire_interface));
- msm_gpiomux_install_nowrite(ath_gpio_configs,
- ARRAY_SIZE(ath_gpio_configs));
+ if (of_board_is_liquid())
+ msm_gpiomux_install_nowrite(ath_gpio_configs,
+ ARRAY_SIZE(ath_gpio_configs));
msm_gpiomux_install(msm8974_slimbus_config,
ARRAY_SIZE(msm8974_slimbus_config));
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 4a716fc..87572da 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -2550,6 +2550,8 @@
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991f000.serial"),
CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991e000.serial"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, "f991e000.serial"),
CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", pnoc_qseecom_clk.c, "qseecom"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index c42da92..b96924f 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4823,6 +4823,11 @@
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "qseecom"),
CLK_LOOKUP("core_clk_src", ce1_clk_src.c, "qseecom"),
+ CLK_LOOKUP("ce_drv_core_clk", gcc_ce2_clk.c, "qseecom"),
+ CLK_LOOKUP("ce_drv_iface_clk", gcc_ce2_ahb_clk.c, "qseecom"),
+ CLK_LOOKUP("ce_drv_bus_clk", gcc_ce2_axi_clk.c, "qseecom"),
+ CLK_LOOKUP("ce_drv_core_clk_src", ce2_clk_src.c, "qseecom"),
+
CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "scm"),
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "scm"),
CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, "scm"),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 0d97401..4984255 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2018,12 +2018,6 @@
*/
clk_prepare_enable(&cxo_a_clk_src.c);
- /*
- * TODO: This call is to prevent sending 0Hz to rpm to turn off pnoc.
- * Needs to remove this after vote of pnoc from sdcc driver is ready.
- */
- clk_prepare_enable(&pnoc_msmbus_a_clk.c);
-
/* Set rates for single-rate clocks. */
clk_set_rate(&usb_hs_system_clk_src.c,
usb_hs_system_clk_src.freq_tbl[0].freq_hz);
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 6665d66..a07b13d 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -38,7 +38,7 @@
#define EN_FEW_WAIT_VAL (0x8 << 16)
#define CLK_DIS_WAIT_VAL (0x2 << 12)
-#define TIMEOUT_US 100
+#define TIMEOUT_US 1000
struct gdsc {
struct regulator_dev *rdev;
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index dcae83b..dc4671c 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -63,6 +63,7 @@
* @iommu_dev: pointer to iommu device
* @ops: iommu access operations pointer.
* @hw_ops: iommu pm hw access operations pointer.
+ * @always_on: 1 if iommu is always on, 0 otherwise.
*/
struct iommu_info {
const char *iommu_name;
@@ -71,6 +72,7 @@
struct device *iommu_dev;
struct iommu_access_ops *ops;
struct iommu_pm_hw_ops *hw_ops;
+ unsigned int always_on;
};
/**
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 4258dbd..72eb999 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -24,6 +24,7 @@
#define SCM_SVC_MP 0xC
#define SCM_SVC_CRYPTO 0xA
#define SCM_SVC_DCVS 0xD
+#define SCM_SVC_ES 0x10
#define SCM_SVC_TZSCHEDULER 0xFC
#ifdef CONFIG_MSM_SCM
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index b931ee6..af2fbab 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -133,6 +133,7 @@
#define LDO_DELTA_MIN 10000
#define LDO_DELTA_MAX 100000
+#define MSM_L2_SAW_PHYS 0xf9012000
/**
* struct pmic_gang_vreg -
* @name: the string used to represent the gang
@@ -1309,6 +1310,8 @@
void secondary_cpu_hs_init(void *base_ptr)
{
+ void *l2_saw_base;
+
/* Turn on the BHS, turn off LDO Bypass and power down LDO */
writel_relaxed(
BHS_CNT_DEFAULT << BHS_CNT_BIT_POS
@@ -1335,6 +1338,23 @@
| BHS_SEG_EN_DEFAULT << BHS_SEG_EN_BIT_POS
| BHS_EN_MASK,
base_ptr + APC_PWR_GATE_CTL);
+
+ if (the_gang && the_gang->manage_phases)
+ return;
+
+ /* If the driver has not yet started to manage phases then enable
+ * max phases.
+ */
+ l2_saw_base = ioremap_nocache(MSM_L2_SAW_PHYS, SZ_4K);
+ if (!l2_saw_base) {
+ __WARN();
+ return;
+ }
+ writel_relaxed(0x10003, l2_saw_base + 0x1c);
+ mb();
+ udelay(PHASE_SETTLING_TIME_US);
+
+ iounmap(l2_saw_base);
}
MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index a2c74a5..53d5752 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -203,11 +203,14 @@
struct msm_rpm_log_buffer *buf;
buf = file->private_data;
- pdata = buf->pdata;
- if (!pdata)
- return -EINVAL;
+
if (!buf)
return -ENOMEM;
+
+ pdata = buf->pdata;
+
+ if (!pdata)
+ return -EINVAL;
if (!buf->data)
return -ENOMEM;
if (!bufu || count < 0)
diff --git a/block/row-iosched.c b/block/row-iosched.c
index c8ba344..e71f6af 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -200,9 +200,9 @@
struct request *pending_urgent_rq;
int last_served_ioprio_class;
-#define ROW_REG_STARVATION_TOLLERANCE 50
+#define ROW_REG_STARVATION_TOLLERANCE 5000
struct starvation_data reg_prio_starvation;
-#define ROW_LOW_STARVATION_TOLLERANCE 1000
+#define ROW_LOW_STARVATION_TOLLERANCE 10000
struct starvation_data low_prio_starvation;
unsigned int cycle_flags;
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 2557983..0383d8f 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -39,6 +39,8 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
+#include <linux/proc_fs.h>
+
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -47,8 +49,10 @@
#include <mach/msm_serial_hs.h>
#endif
-unsigned int enableuartsleep = 1;
-module_param(enableuartsleep, uint, 0644);
+static int enableuartsleep = 1;
+module_param(enableuartsleep, int, 0644);
+MODULE_PARM_DESC(enableuartsleep, "Enable Atheros Sleep Protocol");
+
/*
* Global variables
*/
@@ -62,6 +66,9 @@
/** Global state flags */
static unsigned long flags;
+/** To Check LPM is enabled */
+static bool is_lpm_enabled;
+
/** Workqueue to respond to change in hostwake line */
static void wakeup_host_work(struct work_struct *work);
@@ -72,6 +79,8 @@
/** Lock for state transitions */
static spinlock_t rw_lock;
+#define PROC_DIR "bluetooth/sleep"
+
#define POLARITY_LOW 0
#define POLARITY_HIGH 1
@@ -80,8 +89,11 @@
unsigned ext_wake; /* wake up device */
unsigned host_wake_irq;
int irq_polarity;
+ struct uart_port *uport;
};
+struct work_struct ws_sleep;
+
/* 1 second timeout */
#define TX_TIMER_INTERVAL 1
@@ -99,23 +111,24 @@
struct sk_buff_head txq;
struct work_struct ctxtsw;
- struct work_struct ws_sleep;
};
-static void hsuart_serial_clock_on(struct tty_struct *tty)
+static void hsuart_serial_clock_on(struct uart_port *port)
{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
BT_DBG("");
- msm_hs_request_clock_on(port);
+ if (port)
+ msm_hs_request_clock_on(port);
+ else
+ BT_INFO("Uart has not voted for Clock ON");
}
-static void hsuart_serial_clock_off(struct tty_struct *tty)
+static void hsuart_serial_clock_off(struct uart_port *port)
{
- struct uart_state *state = tty->driver_data;
- struct uart_port *port = state->uart_port;
BT_DBG("");
- msm_hs_request_clock_off(port);
+ if (port)
+ msm_hs_request_clock_off(port);
+ else
+ BT_INFO("Uart has not voted for Clock OFF");
}
static void modify_timer_task(void)
@@ -127,31 +140,31 @@
}
-static int ath_wakeup_ar3k(struct tty_struct *tty)
+static int ath_wakeup_ar3k(void)
{
int status = 0;
if (test_bit(BT_TXEXPIRED, &flags)) {
- hsuart_serial_clock_on(tty);
- BT_INFO("wakeup device\n");
+ hsuart_serial_clock_on(bsi->uport);
+ BT_DBG("wakeup device\n");
gpio_set_value(bsi->ext_wake, 0);
msleep(20);
gpio_set_value(bsi->ext_wake, 1);
}
- modify_timer_task();
+ if (!is_lpm_enabled)
+ modify_timer_task();
return status;
}
static void wakeup_host_work(struct work_struct *work)
{
- struct ath_struct *ath =
- container_of(work, struct ath_struct, ws_sleep);
- BT_INFO("wake up host");
+ BT_DBG("wake up host");
if (test_bit(BT_SLEEPENABLE, &flags)) {
if (test_bit(BT_TXEXPIRED, &flags))
- hsuart_serial_clock_on(ath->hu->tty);
+ hsuart_serial_clock_on(bsi->uport);
}
- modify_timer_task();
+ if (!is_lpm_enabled)
+ modify_timer_task();
}
static void ath_hci_uart_work(struct work_struct *work)
@@ -159,16 +172,14 @@
int status;
struct ath_struct *ath;
struct hci_uart *hu;
- struct tty_struct *tty;
ath = container_of(work, struct ath_struct, ctxtsw);
hu = ath->hu;
- tty = hu->tty;
/* verify and wake up controller */
if (test_bit(BT_SLEEPENABLE, &flags))
- status = ath_wakeup_ar3k(tty);
+ status = ath_wakeup_ar3k();
/* Ready to send Data */
clear_bit(HCI_UART_SENDING, &hu->tx_state);
hci_uart_tx_wakeup(hu);
@@ -176,15 +187,15 @@
static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
{
- /* schedule a tasklet to handle the change in the host wake line */
- struct ath_struct *ath = (struct ath_struct *)dev_id;
-
- schedule_work(&ath->ws_sleep);
+ /* schedule a work to global shared workqueue to handle
+ * the change in the host wake line
+ */
+ schedule_work(&ws_sleep);
return IRQ_HANDLED;
}
-static int ath_bluesleep_gpio_config(struct ath_struct *ath, int on)
+static int ath_bluesleep_gpio_config(int on)
{
int ret = 0;
@@ -232,16 +243,16 @@
/* Initialize timer */
init_timer(&tx_timer);
tx_timer.function = bluesleep_tx_timer_expire;
- tx_timer.data = (u_long)ath->hu;
+ tx_timer.data = 0;
if (bsi->irq_polarity == POLARITY_LOW) {
ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- "bluetooth hostwake", (void *)ath);
+ "bluetooth hostwake", NULL);
} else {
ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING,
- "bluetooth hostwake", (void *)ath);
+ "bluetooth hostwake", NULL);
}
if (ret < 0) {
BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
@@ -257,7 +268,7 @@
return 0;
free_host_wake_irq:
- free_irq(bsi->host_wake_irq, (void *)ath);
+ free_irq(bsi->host_wake_irq, NULL);
delete_timer:
del_timer(&tx_timer);
gpio_ext_wake:
@@ -268,26 +279,76 @@
return ret;
}
+static int ath_lpm_start(void)
+{
+ BT_DBG("Start LPM mode");
+
+ if (!bsi) {
+ BT_ERR("HCIATH3K bluesleep info does not exist");
+ return -EIO;
+ }
+
+ bsi->uport = msm_hs_get_uart_port(0);
+ if (!bsi->uport) {
+ BT_ERR("UART Port is not available");
+ return -ENODEV;
+ }
+
+ INIT_WORK(&ws_sleep, wakeup_host_work);
+
+ if (ath_bluesleep_gpio_config(1) < 0) {
+ BT_ERR("HCIATH3K GPIO Config failed");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int ath_lpm_stop(void)
+{
+ BT_DBG("Stop LPM mode");
+ cancel_work_sync(&ws_sleep);
+
+ if (bsi) {
+ bsi->uport = NULL;
+ ath_bluesleep_gpio_config(0);
+ }
+
+ return 0;
+}
+
/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
+ struct uart_state *state;
BT_DBG("hu %p, bsi %p", hu, bsi);
- if (!bsi)
+ if (!bsi) {
+ BT_ERR("HCIATH3K bluesleep info does not exist");
return -EIO;
+ }
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
- if (!ath)
+ if (!ath) {
+ BT_ERR("HCIATH3K Memory not enough to init driver");
return -ENOMEM;
+ }
skb_queue_head_init(&ath->txq);
hu->priv = ath;
ath->hu = hu;
+ state = hu->tty->driver_data;
- if (ath_bluesleep_gpio_config(ath, 1) < 0) {
+ if (!state) {
+ BT_ERR("HCIATH3K tty driver data does not exist");
+ return -ENXIO;
+ }
+ bsi->uport = state->uart_port;
+
+ if (ath_bluesleep_gpio_config(1) < 0) {
BT_ERR("HCIATH3K GPIO Config failed");
hu->priv = NULL;
kfree(ath);
@@ -300,7 +361,7 @@
modify_timer_task();
}
INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
- INIT_WORK(&ath->ws_sleep, wakeup_host_work);
+ INIT_WORK(&ws_sleep, wakeup_host_work);
return 0;
}
@@ -327,12 +388,13 @@
cancel_work_sync(&ath->ctxtsw);
- cancel_work_sync(&ath->ws_sleep);
+ cancel_work_sync(&ws_sleep);
if (bsi)
- ath_bluesleep_gpio_config(ath, 0);
+ ath_bluesleep_gpio_config(0);
hu->priv = NULL;
+ bsi->uport = NULL;
kfree(ath);
return 0;
@@ -423,14 +485,13 @@
static void bluesleep_tx_timer_expire(unsigned long data)
{
- struct hci_uart *hu = (struct hci_uart *) data;
if (!test_bit(BT_SLEEPENABLE, &flags))
return;
BT_INFO("Tx timer expired\n");
set_bit(BT_TXEXPIRED, &flags);
- hsuart_serial_clock_off(hu->tty);
+ hsuart_serial_clock_off(bsi->uport);
}
static struct hci_uart_proto athp = {
@@ -443,6 +504,88 @@
.flush = ath_flush,
};
+static int lpm_enabled;
+
+static int bluesleep_lpm_set(const char *val, const struct kernel_param *kp)
+{
+ int ret;
+
+ ret = param_set_int(val, kp);
+
+ if (ret) {
+ BT_ERR("HCIATH3K: lpm enable parameter set failed");
+ return ret;
+ }
+
+ BT_DBG("lpm : %d", lpm_enabled);
+
+ if ((lpm_enabled == 0) && is_lpm_enabled) {
+ ath_lpm_stop();
+ clear_bit(BT_SLEEPENABLE, &flags);
+ is_lpm_enabled = false;
+ } else if ((lpm_enabled == 1) && !is_lpm_enabled) {
+ if (ath_lpm_start() < 0) {
+ BT_ERR("HCIATH3K LPM mode failed");
+ return -EIO;
+ }
+ set_bit(BT_SLEEPENABLE, &flags);
+ is_lpm_enabled = true;
+ } else {
+ BT_ERR("HCIATH3K invalid lpm value");
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
+static struct kernel_param_ops bluesleep_lpm_ops = {
+ .set = bluesleep_lpm_set,
+ .get = param_get_int,
+};
+
+module_param_cb(ath_lpm, &bluesleep_lpm_ops,
+ &lpm_enabled, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ath_lpm, "Enable Atheros LPM sleep Protocol");
+
+static int lpm_btwrite;
+
+static int bluesleep_lpm_btwrite(const char *val, const struct kernel_param *kp)
+{
+ int ret;
+
+ ret = param_set_int(val, kp);
+
+ if (ret) {
+ BT_ERR("HCIATH3K: lpm btwrite parameter set failed");
+ return ret;
+ }
+
+ BT_DBG("btwrite : %d", lpm_btwrite);
+ if (is_lpm_enabled) {
+ if (lpm_btwrite == 0) {
+ /*Setting TXEXPIRED bit to make it
+ compatible with current solution*/
+ set_bit(BT_TXEXPIRED, &flags);
+ hsuart_serial_clock_off(bsi->uport);
+ } else if (lpm_btwrite == 1) {
+ ath_wakeup_ar3k();
+ clear_bit(BT_TXEXPIRED, &flags);
+ } else {
+ BT_ERR("HCIATH3K invalid btwrite value");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static struct kernel_param_ops bluesleep_lpm_btwrite_ops = {
+ .set = bluesleep_lpm_btwrite,
+ .get = param_get_int,
+};
+
+module_param_cb(ath_btwrite, &bluesleep_lpm_btwrite_ops,
+ &lpm_btwrite, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ath_lpm, "Assert/Deassert the sleep");
static int bluesleep_populate_dt_pinfo(struct platform_device *pdev)
{
@@ -581,5 +724,6 @@
int __exit ath_deinit(void)
{
platform_driver_unregister(&bluesleep_driver);
+
return hci_uart_unregister_proto(&athp);
}
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index af7f04b..f3f627d 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -57,7 +57,7 @@
continue;
if (split_pages)
split_page(page, orders[i]);
- info = kmap(page);
+ info = kmalloc(sizeof(struct page_info *), GFP_KERNEL);
info->page = page;
info->order = orders[i];
return info;
@@ -118,7 +118,7 @@
sg = sg_next(sg);
}
list_del(&info->list);
- kunmap(page);
+ kfree(info);
}
dma_sync_sg_for_device(NULL, table->sgl, table->nents,
@@ -137,7 +137,7 @@
else
__free_pages(info->page, info->order);
- kunmap(info->page);
+ kfree(info);
}
return -ENOMEM;
}
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 549800f..7ae0b21 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -414,6 +414,7 @@
pmon_info->iommu.ops = &iommu_access_ops_v0;
pmon_info->iommu.hw_ops = iommu_pm_get_hw_ops_v0();
pmon_info->iommu.iommu_name = drvdata->name;
+ pmon_info->iommu.always_on = 1;
ret = msm_iommu_pm_iommu_register(pmon_info);
if (ret) {
pr_err("%s iommu register fail\n",
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index fee8a4a..a11d794 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -90,6 +90,19 @@
return pos;
}
+static int iommu_pm_event_class_supported(struct iommu_pmon *pmon,
+ int event_class)
+{
+ unsigned int nevent_cls = pmon->nevent_cls_supported;
+ unsigned int i;
+
+ for (i = 0; i < nevent_cls; ++i) {
+ if (event_class == pmon->event_cls_supported[i])
+ return event_class;
+ }
+ return MSM_IOMMU_PMU_NO_EVENT_CLASS;
+}
+
static const char *iommu_pm_find_event_class_name(int event_class)
{
size_t array_len;
@@ -113,7 +126,8 @@
return event_class_name;
}
-static int iommu_pm_find_event_class(const char *event_class_name)
+static int iommu_pm_find_event_class(struct iommu_pmon *pmon,
+ const char *event_class_name)
{
size_t array_len;
struct event_class *ptr;
@@ -134,6 +148,7 @@
}
out:
+ event_class = iommu_pm_event_class_supported(pmon, event_class);
return event_class;
}
@@ -389,11 +404,11 @@
rv = kstrtol(buf, 10, &value);
if (!rv) {
counter->current_event_class =
- iommu_pm_find_event_class(
+ iommu_pm_find_event_class(pmon,
iommu_pm_find_event_class_name(value));
} else {
counter->current_event_class =
- iommu_pm_find_event_class(buf);
+ iommu_pm_find_event_class(pmon, buf);
} }
if (current_event_class != counter->current_event_class)
@@ -488,14 +503,17 @@
rv = kstrtoul(buf, 10, &cmd);
if (!rv && (cmd < 2)) {
if (pmon->enabled == 1 && cmd == 0) {
- if (pmon->iommu_attach_count > 0)
+ if (pmon->iommu.always_on ||
+ pmon->iommu_attach_count > 0)
iommu_pm_off(pmon);
} else if (pmon->enabled == 0 && cmd == 1) {
/* We can only turn on perf. monitoring if
- * iommu is attached. Delay turning on perf.
- * monitoring until we are attached.
+ * iommu is attached (if not always on).
+ * Delay turning on perf. monitoring until
+ * we are attached.
*/
- if (pmon->iommu_attach_count > 0)
+ if (pmon->iommu.always_on ||
+ pmon->iommu_attach_count > 0)
iommu_pm_on(pmon);
else
pmon->enabled = 1;
@@ -788,9 +806,9 @@
++pmon->iommu_attach_count;
if (pmon->iommu_attach_count == 1) {
/* If perf. mon was enabled before we attached we do
- * the actual after we attach.
+ * the actual enabling after we attach.
*/
- if (pmon->enabled)
+ if (pmon->enabled && !pmon->iommu.always_on)
iommu_pm_on(pmon);
}
mutex_unlock(&pmon->lock);
@@ -805,9 +823,9 @@
mutex_lock(&pmon->lock);
if (pmon->iommu_attach_count == 1) {
/* If perf. mon is still enabled we have to disable
- * before we do the detach.
+ * before we do the detach if iommu is not always on.
*/
- if (pmon->enabled)
+ if (pmon->enabled && !pmon->iommu.always_on)
iommu_pm_off(pmon);
}
BUG_ON(pmon->iommu_attach_count == 0);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index e011d8f..046faac 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -34,8 +34,6 @@
#define SLIMBUS_PRESENT_TIMEOUT 100
#define MAX_WCD9XXX_DEVICE 4
-#define TABLA_I2C_MODE 0x03
-#define SITAR_I2C_MODE 0x01
#define CODEC_DT_MAX_PROP_SIZE 40
#define WCD9XXX_I2C_GSBI_SLAVE_ID "3-000d"
#define WCD9XXX_I2C_TOP_SLAVE_ADDR 0x0d
@@ -59,18 +57,9 @@
int mod_id;
};
-static char *taiko_supplies[] = {
- WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
- "cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
-};
-
-static char *tapan_supplies[] = {
- WCD9XXX_SUPPLY_BUCK_NAME, "cdc-vdd-h", "cdc-vdd-px",
- "cdc-vdd-a-1p2v", "cdc-vdd-cx"
-};
-
static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
- struct wcd9xxx_regulator *vreg, const char *vreg_name);
+ struct wcd9xxx_regulator *vreg,
+ const char *vreg_name, bool ondemand);
static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
struct wcd9xxx_micbias_setting *micbias);
static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev);
@@ -292,49 +281,60 @@
},
};
-static struct wcd9xx_codec_type {
- u8 byte[4];
- struct mfd_cell *dev;
- int size;
- int num_irqs;
- int version; /* -1 to retrive version from chip version register */
- enum wcd9xxx_slim_slave_addr_type slim_slave_type;
-} wcd9xxx_codecs[] = {
+
+enum wcd9xxx_chipid_major {
+ TABLA_MAJOR = cpu_to_le16(0x100),
+ SITAR_MAJOR = cpu_to_le16(0x101),
+ TAIKO_MAJOR = cpu_to_le16(0x102),
+ TAPAN_MAJOR = cpu_to_le16(0x103),
+};
+
+static const struct wcd9xxx_codec_type wcd9xxx_codecs[] = {
{
- {0x2, 0x0, 0x0, 0x1}, tabla_devs, ARRAY_SIZE(tabla_devs),
- TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+ TABLA_MAJOR, cpu_to_le16(0x1), tabla1x_devs,
+ ARRAY_SIZE(tabla1x_devs), TABLA_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03,
},
{
- {0x1, 0x0, 0x0, 0x1}, tabla1x_devs, ARRAY_SIZE(tabla1x_devs),
- TABLA_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
- },
- { /* wcd9320 version 1 */
- {0x0, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
- TAIKO_NUM_IRQS, 1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
- },
- { /* wcd9320 version 2 */
- {0x1, 0x0, 0x2, 0x1}, taiko_devs, ARRAY_SIZE(taiko_devs),
- TAIKO_NUM_IRQS, 2, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+ TABLA_MAJOR, cpu_to_le16(0x2), tabla_devs,
+ ARRAY_SIZE(tabla_devs), TABLA_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x03
},
{
- {0x0, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
- TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+ /* Siter version 1 has same major chip id with Tabla */
+ TABLA_MAJOR, cpu_to_le16(0x0), sitar_devs,
+ ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
},
{
- {0x1, 0x0, 0x3, 0x1}, tapan_devs, ARRAY_SIZE(tapan_devs),
- TAPAN_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO
+ SITAR_MAJOR, cpu_to_le16(0x1), sitar_devs,
+ ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
},
{
- {0x0, 0x0, 0x0, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
- SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+ SITAR_MAJOR, cpu_to_le16(0x2), sitar_devs,
+ ARRAY_SIZE(sitar_devs), SITAR_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA, 0x01
},
{
- {0x1, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
- SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+ TAIKO_MAJOR, cpu_to_le16(0x0), taiko_devs,
+ ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
},
{
- {0x2, 0x0, 0x1, 0x1}, sitar_devs, ARRAY_SIZE(sitar_devs),
- SITAR_NUM_IRQS, -1, WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA
+ TAIKO_MAJOR, cpu_to_le16(0x1), taiko_devs,
+ ARRAY_SIZE(taiko_devs), TAIKO_NUM_IRQS, 2,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x01
+ },
+ {
+ TAPAN_MAJOR, cpu_to_le16(0x0), tapan_devs,
+ ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
+ },
+ {
+ TAPAN_MAJOR, cpu_to_le16(0x1), tapan_devs,
+ ARRAY_SIZE(tapan_devs), TAPAN_NUM_IRQS, -1,
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TAIKO, 0x03
},
};
@@ -384,65 +384,80 @@
wcd9xxx->reset_gpio = 0;
}
}
-static int wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx,
- struct mfd_cell **wcd9xxx_dev,
- int *wcd9xxx_dev_size,
- int *wcd9xxx_dev_num_irqs)
+
+static const struct wcd9xxx_codec_type
+*wcd9xxx_check_codec_type(struct wcd9xxx *wcd9xxx, u8 *version)
{
- int i;
- int ret;
- i = WCD9XXX_A_CHIP_ID_BYTE_0;
- while (i <= WCD9XXX_A_CHIP_ID_BYTE_3) {
- ret = wcd9xxx_reg_read(wcd9xxx, i);
- if (ret < 0)
- goto exit;
- wcd9xxx->idbyte[i-WCD9XXX_A_CHIP_ID_BYTE_0] = (u8)ret;
- pr_debug("%s: wcd9xx read = %x, byte = %x\n", __func__, ret,
- i);
- i++;
+ int i, rc;
+ const struct wcd9xxx_codec_type *c, *d = NULL;
+
+ rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0,
+ sizeof(wcd9xxx->id_minor),
+ (u8 *)&wcd9xxx->id_minor);
+ if (rc < 0)
+ goto exit;
+
+ rc = wcd9xxx_bulk_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_2,
+ sizeof(wcd9xxx->id_major),
+ (u8 *)&wcd9xxx->id_major);
+ if (rc < 0)
+ goto exit;
+ dev_dbg(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
+ __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
+
+ for (i = 0, c = &wcd9xxx_codecs[0]; i < ARRAY_SIZE(wcd9xxx_codecs);
+ i++, c++) {
+ if (c->id_major == wcd9xxx->id_major) {
+ if (c->id_minor == wcd9xxx->id_minor) {
+ d = c;
+ dev_dbg(wcd9xxx->dev,
+ "%s: exact match %s\n", __func__,
+ d->dev->name);
+ break;
+ } else if (!d) {
+ d = c;
+ } else {
+ if ((d->id_minor < c->id_minor) ||
+ (d->id_minor == c->id_minor &&
+ d->version < c->version))
+ d = c;
+ }
+ dev_dbg(wcd9xxx->dev,
+ "%s: best match %s, major 0x%x, minor 0x%x\n",
+ __func__, d->dev->name, d->id_major,
+ d->id_minor);
+ }
}
- /* Read codec version */
- ret = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
- if (ret < 0)
- goto exit;
- wcd9xxx->version = (u8)ret & 0x1F;
- i = 0;
- while (i < ARRAY_SIZE(wcd9xxx_codecs)) {
- if ((wcd9xxx_codecs[i].byte[0] == wcd9xxx->idbyte[0]) &&
- (wcd9xxx_codecs[i].byte[1] == wcd9xxx->idbyte[1]) &&
- (wcd9xxx_codecs[i].byte[2] == wcd9xxx->idbyte[2]) &&
- (wcd9xxx_codecs[i].byte[3] == wcd9xxx->idbyte[3])) {
- pr_info("%s: codec is %s", __func__,
- wcd9xxx_codecs[i].dev->name);
- *wcd9xxx_dev = wcd9xxx_codecs[i].dev;
- *wcd9xxx_dev_size = wcd9xxx_codecs[i].size;
- *wcd9xxx_dev_num_irqs = wcd9xxx_codecs[i].num_irqs;
- wcd9xxx->slim_slave_type =
- wcd9xxx_codecs[i].slim_slave_type;
- if (wcd9xxx_codecs[i].version > -1)
- wcd9xxx->version = wcd9xxx_codecs[i].version;
- break;
+ if (!d) {
+ dev_warn(wcd9xxx->dev,
+ "%s: driver for id major 0x%x, minor 0x%x not found\n",
+ __func__, wcd9xxx->id_major, wcd9xxx->id_minor);
+ } else {
+ if (d->version > -1) {
+ *version = d->version;
+ } else {
+ rc = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_VERSION);
+ if (rc < 0) {
+ d = NULL;
+ goto exit;
+ }
+ *version = (u8)rc & 0x1F;
}
- i++;
+ dev_info(wcd9xxx->dev,
+ "%s: detected %s, major 0x%x, minor 0x%x, ver 0x%x\n",
+ __func__, d->dev->name, d->id_major, d->id_minor,
+ *version);
}
- if (*wcd9xxx_dev == NULL || *wcd9xxx_dev_size == 0)
- ret = -ENODEV;
- pr_info("%s: Read codec idbytes & version\n"
- "byte_0[%08x] byte_1[%08x] byte_2[%08x]\n"
- " byte_3[%08x] version = %x\n", __func__,
- wcd9xxx->idbyte[0], wcd9xxx->idbyte[1],
- wcd9xxx->idbyte[2], wcd9xxx->idbyte[3],
- wcd9xxx->version);
exit:
- return ret;
+ return d;
}
static int wcd9xxx_device_init(struct wcd9xxx *wcd9xxx)
{
int ret;
- struct mfd_cell *wcd9xxx_dev = NULL;
- int wcd9xxx_dev_size = 0;
+ u8 version;
+ const struct wcd9xxx_codec_type *found;
mutex_init(&wcd9xxx->io_lock);
mutex_init(&wcd9xxx->xfer_lock);
@@ -458,10 +473,14 @@
wcd9xxx_bring_up(wcd9xxx);
- ret = wcd9xxx_check_codec_type(wcd9xxx, &wcd9xxx_dev, &wcd9xxx_dev_size,
- &wcd9xxx->num_irqs);
- if (ret < 0)
+ found = wcd9xxx_check_codec_type(wcd9xxx, &version);
+ if (!found) {
+ ret = -ENODEV;
goto err_irq;
+ } else {
+ wcd9xxx->codec_type = found;
+ wcd9xxx->version = version;
+ }
if (wcd9xxx->irq != -1) {
ret = wcd9xxx_irq_init(wcd9xxx);
@@ -471,7 +490,7 @@
}
}
- ret = mfd_add_devices(wcd9xxx->dev, -1, wcd9xxx_dev, wcd9xxx_dev_size,
+ ret = mfd_add_devices(wcd9xxx->dev, -1, found->dev, found->size,
NULL, 0);
if (ret != 0) {
dev_err(wcd9xxx->dev, "Failed to add children: %d\n", ret);
@@ -605,8 +624,8 @@
};
#endif
-static int wcd9xxx_enable_supplies(struct wcd9xxx *wcd9xxx,
- struct wcd9xxx_pdata *pdata)
+static int wcd9xxx_init_supplies(struct wcd9xxx *wcd9xxx,
+ struct wcd9xxx_pdata *pdata)
{
int ret;
int i;
@@ -620,7 +639,7 @@
wcd9xxx->num_of_supplies = 0;
- if (ARRAY_SIZE(pdata->regulator) > MAX_REGULATOR) {
+ if (ARRAY_SIZE(pdata->regulator) > WCD9XXX_MAX_REGULATOR) {
pr_err("%s: Array Size out of bound\n", __func__);
ret = -EINVAL;
goto err;
@@ -642,8 +661,12 @@
}
for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+ if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
+ 0)
+ continue;
ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
- pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
+ pdata->regulator[i].min_uV,
+ pdata->regulator[i].max_uV);
if (ret) {
pr_err("%s: Setting regulator voltage failed for "
"regulator %s err = %d\n", __func__,
@@ -652,30 +675,19 @@
}
ret = regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer,
- pdata->regulator[i].optimum_uA);
+ pdata->regulator[i].optimum_uA);
if (ret < 0) {
pr_err("%s: Setting regulator optimum mode failed for "
"regulator %s err = %d\n", __func__,
wcd9xxx->supplies[i].supply, ret);
goto err_get;
+ } else {
+ ret = 0;
}
}
- ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
- wcd9xxx->supplies);
- if (ret != 0) {
- dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
- ret);
- goto err_configure;
- }
return ret;
-err_configure:
- for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
- regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
- pdata->regulator[i].max_uV);
- regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
- }
err_get:
regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
err_supplies:
@@ -684,6 +696,33 @@
return ret;
}
+static int wcd9xxx_enable_static_supplies(struct wcd9xxx *wcd9xxx,
+ struct wcd9xxx_pdata *pdata)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+ if (pdata->regulator[i].ondemand)
+ continue;
+ ret = regulator_enable(wcd9xxx->supplies[i].consumer);
+ if (ret) {
+ pr_err("%s: Failed to enable %s\n", __func__,
+ wcd9xxx->supplies[i].supply);
+ break;
+ } else {
+ pr_debug("%s: Enabled regulator %s\n", __func__,
+ wcd9xxx->supplies[i].supply);
+ }
+ }
+
+ while (ret && --i)
+ if (!pdata->regulator[i].ondemand)
+ regulator_disable(wcd9xxx->supplies[i].consumer);
+
+ return ret;
+}
+
static void wcd9xxx_disable_supplies(struct wcd9xxx *wcd9xxx,
struct wcd9xxx_pdata *pdata)
{
@@ -692,8 +731,11 @@
regulator_bulk_disable(wcd9xxx->num_of_supplies,
wcd9xxx->supplies);
for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
+ if (regulator_count_voltages(wcd9xxx->supplies[i].consumer) <=
+ 0)
+ continue;
regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
- pdata->regulator[i].max_uV);
+ pdata->regulator[i].max_uV);
regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
}
regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
@@ -856,7 +898,6 @@
struct wcd9xxx_pdata *pdata = NULL;
int val = 0;
int ret = 0;
- int i2c_mode = 0;
int wcd9xx_index = 0;
struct device *dev;
@@ -913,18 +954,26 @@
wcd9xxx->slim_device_bootup = true;
if (client->dev.of_node)
wcd9xxx->mclk_rate = pdata->mclk_rate;
- ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
+
+ ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
if (ret) {
pr_err("%s: Fail to enable Codec supplies\n",
__func__);
goto err_codec;
}
+ ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
+ if (ret) {
+ pr_err("%s: Fail to enable Codec pre-reset supplies\n",
+ __func__);
+ goto err_codec;
+ }
usleep_range(5, 5);
+
ret = wcd9xxx_reset(wcd9xxx);
if (ret) {
pr_err("%s: Resetting Codec failed\n", __func__);
- goto err_supplies;
+ goto err_supplies;
}
ret = wcd9xxx_i2c_get_client_index(client, &wcd9xx_index);
@@ -948,18 +997,14 @@
goto err_device_init;
}
- if ((wcd9xxx->idbyte[0] == 0x2) || (wcd9xxx->idbyte[0] == 0x1))
- i2c_mode = TABLA_I2C_MODE;
- else if (wcd9xxx->idbyte[0] == 0x0)
- i2c_mode = SITAR_I2C_MODE;
-
ret = wcd9xxx_read(wcd9xxx, WCD9XXX_A_CHIP_STATUS, 1, &val, 0);
+ if (ret < 0)
+ pr_err("%s: failed to read the wcd9xxx status (%d)\n",
+ __func__, ret);
+ if (val != wcd9xxx->codec_type->i2c_chip_status)
+ pr_err("%s: unknown chip status 0x%x\n", __func__, val);
- if ((ret < 0) || (val != i2c_mode))
- pr_err("failed to read the wcd9xxx status ret = %d\n",
- ret);
-
- wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
+ wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_I2C;
return ret;
} else
@@ -988,7 +1033,9 @@
}
static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
- struct wcd9xxx_regulator *vreg, const char *vreg_name)
+ struct wcd9xxx_regulator *vreg,
+ const char *vreg_name,
+ bool ondemand)
{
int len, ret = 0;
const __be32 *prop;
@@ -1006,6 +1053,7 @@
return -ENODEV;
}
vreg->name = vreg_name;
+ vreg->ondemand = ondemand;
snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
"qcom,%s-voltage", vreg_name);
@@ -1014,7 +1062,7 @@
if (!prop || (len != (2 * sizeof(__be32)))) {
dev_err(dev, "%s %s property\n",
prop ? "invalid format" : "no", prop_name);
- return -ENODEV;
+ return -EINVAL;
} else {
vreg->min_uV = be32_to_cpup(&prop[0]);
vreg->max_uV = be32_to_cpup(&prop[1]);
@@ -1027,12 +1075,12 @@
if (ret) {
dev_err(dev, "Looking up %s property in node %s failed",
prop_name, dev->of_node->full_name);
- return -ENODEV;
+ return -EFAULT;
}
vreg->optimum_uA = prop_val;
- dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
- vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+ dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n", vreg->name,
+ vreg->min_uV, vreg->max_uV, vreg->optimum_uA, vreg->ondemand);
return 0;
}
@@ -1150,40 +1198,66 @@
static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
{
struct wcd9xxx_pdata *pdata;
- int ret, i;
- char **codec_supplies;
- u32 num_of_supplies = 0;
+ int ret, static_cnt, ond_cnt, idx, i;
+ const char *name = NULL;
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";
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "could not allocate memory for platform data\n");
return NULL;
}
- if (!strcmp(dev_name(dev), "taiko-slim-pgd") ||
- (!strcmp(dev_name(dev), WCD9XXX_I2C_GSBI_SLAVE_ID))) {
- codec_supplies = taiko_supplies;
- num_of_supplies = ARRAY_SIZE(taiko_supplies);
- } else if (!strcmp(dev_name(dev), "tapan-slim-pgd")) {
- codec_supplies = tapan_supplies;
- num_of_supplies = ARRAY_SIZE(tapan_supplies);
- } else {
- dev_err(dev, "%s unsupported device %s\n",
- __func__, dev_name(dev));
+
+ static_cnt = of_property_count_strings(dev->of_node, static_prop_name);
+ if (IS_ERR_VALUE(static_cnt)) {
+ dev_err(dev, "%s: Failed to get static supplies %d\n", __func__,
+ static_cnt);
goto err;
}
- if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+ /* On-demand supply list is an optional property */
+ ond_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
+ 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)) {
dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
- __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
-
+ __func__, static_cnt, ARRAY_SIZE(pdata->regulator));
goto err;
}
- for (i = 0; i < num_of_supplies; i++) {
- ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
- codec_supplies[i]);
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
}
@@ -1325,9 +1399,17 @@
wcd9xxx->mclk_rate = pdata->mclk_rate;
wcd9xxx->slim_device_bootup = true;
- ret = wcd9xxx_enable_supplies(wcd9xxx, pdata);
- if (ret)
+ ret = wcd9xxx_init_supplies(wcd9xxx, pdata);
+ if (ret) {
+ pr_err("%s: Fail to init Codec supplies %d\n", __func__, ret);
goto err_codec;
+ }
+ ret = wcd9xxx_enable_static_supplies(wcd9xxx, pdata);
+ if (ret) {
+ pr_err("%s: Fail to enable Codec pre-reset supplies\n",
+ __func__);
+ goto err_codec;
+ }
usleep_range(5, 5);
ret = wcd9xxx_reset(wcd9xxx);
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index f2c3959..356aecb 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -218,7 +218,8 @@
static int wcd9xxx_num_irq_regs(const struct wcd9xxx *wcd9xxx)
{
- return (wcd9xxx->num_irqs / 8) + ((wcd9xxx->num_irqs % 8) ? 1 : 0);
+ return (wcd9xxx->codec_type->num_irqs / 8) +
+ ((wcd9xxx->codec_type->num_irqs % 8) ? 1 : 0);
}
static irqreturn_t wcd9xxx_irq_thread(int irq, void *data)
@@ -266,7 +267,8 @@
if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
wcd9xxx_irq_dispatch(wcd9xxx, i);
}
- for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->num_irqs; i++) {
+ for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->codec_type->num_irqs;
+ i++) {
if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
wcd9xxx_irq_dispatch(wcd9xxx, i);
}
@@ -301,7 +303,7 @@
pr_debug("%s: enter\n", __func__);
- for (irq = 0; irq < wcd9xxx->num_irqs; irq++) {
+ for (irq = 0; irq < wcd9xxx->codec_type->num_irqs; irq++) {
/* Map OF irq */
virq = wcd9xxx_map_irq(wcd9xxx, irq);
pr_debug("%s: irq %d -> %d\n", __func__, irq, virq);
@@ -365,7 +367,7 @@
/* mask all the interrupts */
memset(irq_level, 0, wcd9xxx_num_irq_regs(wcd9xxx));
- for (i = 0; i < wcd9xxx->num_irqs; i++) {
+ for (i = 0; i < wcd9xxx->codec_type->num_irqs; i++) {
wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i);
irq_level[BIT_BYTE(i)] |=
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index f2d71b6..81262b58 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -31,7 +31,8 @@
static int wcd9xxx_configure_ports(struct wcd9xxx *wcd9xxx)
{
- if (wcd9xxx->slim_slave_type == WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA) {
+ if (wcd9xxx->codec_type->slim_slave_type ==
+ WCD9XXX_SLIM_SLAVE_ADDR_TYPE_TABLA) {
sh_ch.rx_port_ch_reg_base = 0x180;
sh_ch.port_rx_cfg_reg_base = 0x040;
sh_ch.port_tx_cfg_reg_base = 0x040;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index c02eecf..05a15b1 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1,5 +1,3 @@
-
-
/*Qualcomm Secure Execution Environment Communicator (QSEECOM) driver
*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
@@ -53,6 +51,7 @@
#define QSEE_VERSION_01 0x401000
#define QSEE_VERSION_02 0x402000
#define QSEE_VERSION_03 0x403000
+#define QSEE_VERSION_04 0x404000
#define QSEOS_CHECK_VERSION_CMD 0x00001803
@@ -62,6 +61,12 @@
#define QSEECOM_MAX_SG_ENTRY 512
#define QSEECOM_DISK_ENCRYTPION_KEY_ID 0
+/* Save partition image hash for authentication check */
+#define SCM_SAVE_PARTITION_HASH_ID 0x01
+
+/* Check if enterprise security is activate */
+#define SCM_IS_ACTIVATED_ID 0x02
+
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
@@ -74,6 +79,11 @@
QSEECOM_GENERIC,
};
+enum qseecom_ce_hw_instance {
+ CLK_QSEE = 0,
+ CLK_CE_DRV,
+};
+
static struct class *driver_class;
static dev_t qseecom_device_no;
static struct cdev qseecom_cdev;
@@ -85,6 +95,7 @@
static DEFINE_MUTEX(qsee_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
+static DEFINE_MUTEX(clk_access_lock);
struct qseecom_registered_listener_list {
struct list_head list;
@@ -117,10 +128,12 @@
};
struct qseecom_clk {
+ enum qseecom_ce_hw_instance instance;
struct clk *ce_core_clk;
struct clk *ce_clk;
struct clk *ce_core_src_clk;
struct clk *ce_bus_clk;
+ uint32_t clk_access_cnt;
};
struct qseecom_control {
@@ -148,6 +161,7 @@
uint32_t qsee_perf_client;
struct qseecom_clk qsee;
+ struct qseecom_clk ce_drv;
};
struct qseecom_client_handle {
@@ -1891,12 +1905,23 @@
return 0;
}
-static int __qseecom_enable_clk(void)
+static int __qseecom_enable_clk(enum qseecom_ce_hw_instance ce)
{
int rc = 0;
struct qseecom_clk *qclk;
+ if (ce == CLK_QSEE)
qclk = &qseecom.qsee;
+ else
+ qclk = &qseecom.ce_drv;
+
+ mutex_lock(&clk_access_lock);
+ if (qclk->clk_access_cnt > 0) {
+ qclk->clk_access_cnt++;
+ mutex_unlock(&clk_access_lock);
+ return rc;
+ }
+
/* Enable CE core clk */
rc = clk_prepare_enable(qclk->ce_core_clk);
if (rc) {
@@ -1915,6 +1940,8 @@
pr_err("Unable to enable/prepare CE bus clk\n");
goto ce_bus_clk_err;
}
+ qclk->clk_access_cnt++;
+ mutex_unlock(&clk_access_lock);
return 0;
ce_bus_clk_err:
@@ -1922,20 +1949,30 @@
ce_clk_err:
clk_disable_unprepare(qclk->ce_core_clk);
err:
+ mutex_unlock(&clk_access_lock);
return -EIO;
}
-static void __qseecom_disable_clk(void)
+static void __qseecom_disable_clk(enum qseecom_ce_hw_instance ce)
{
struct qseecom_clk *qclk;
- qclk = &qseecom.qsee;
- if (qclk->ce_clk != NULL)
- clk_disable_unprepare(qclk->ce_clk);
- if (qclk->ce_core_clk != NULL)
- clk_disable_unprepare(qclk->ce_core_clk);
- if (qclk->ce_bus_clk != NULL)
- clk_disable_unprepare(qclk->ce_bus_clk);
+ if (ce == CLK_QSEE)
+ qclk = &qseecom.qsee;
+ else
+ qclk = &qseecom.ce_drv;
+
+ mutex_lock(&clk_access_lock);
+ if (qclk->clk_access_cnt == 1) {
+ if (qclk->ce_clk != NULL)
+ clk_disable_unprepare(qclk->ce_clk);
+ if (qclk->ce_core_clk != NULL)
+ clk_disable_unprepare(qclk->ce_core_clk);
+ if (qclk->ce_bus_clk != NULL)
+ clk_disable_unprepare(qclk->ce_bus_clk);
+ }
+ qclk->clk_access_cnt--;
+ mutex_unlock(&clk_access_lock);
}
static int qsee_vote_for_clock(struct qseecom_dev_handle *data,
@@ -1957,14 +1994,14 @@
qseecom.qsee_perf_client, 3);
else {
if (qclk->ce_core_src_clk != NULL)
- ret = __qseecom_enable_clk();
+ ret = __qseecom_enable_clk(CLK_QSEE);
if (!ret) {
ret =
msm_bus_scale_client_update_request(
qseecom.qsee_perf_client, 1);
if ((ret) &&
(qclk->ce_core_src_clk != NULL))
- __qseecom_disable_clk();
+ __qseecom_disable_clk(CLK_QSEE);
}
}
if (ret)
@@ -1988,14 +2025,14 @@
qseecom.qsee_perf_client, 3);
else {
if (qclk->ce_core_src_clk != NULL)
- ret = __qseecom_enable_clk();
+ ret = __qseecom_enable_clk(CLK_QSEE);
if (!ret) {
ret =
msm_bus_scale_client_update_request(
qseecom.qsee_perf_client, 2);
if ((ret) &&
(qclk->ce_core_src_clk != NULL))
- __qseecom_disable_clk();
+ __qseecom_disable_clk(CLK_QSEE);
}
}
@@ -2046,7 +2083,7 @@
ret = msm_bus_scale_client_update_request(
qseecom.qsee_perf_client, 0);
if ((!ret) && (qclk->ce_core_src_clk != NULL))
- __qseecom_disable_clk();
+ __qseecom_disable_clk(CLK_QSEE);
}
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
@@ -2076,7 +2113,7 @@
ret = msm_bus_scale_client_update_request(
qseecom.qsee_perf_client, 0);
if ((!ret) && (qclk->ce_core_src_clk != NULL))
- __qseecom_disable_clk();
+ __qseecom_disable_clk(CLK_QSEE);
}
if (ret)
pr_err("SFPB Bandwidth req fail (%d)\n",
@@ -2345,11 +2382,13 @@
memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
ireq.flags = flags;
+ __qseecom_enable_clk(CLK_QSEE);
ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
&ireq, sizeof(struct qseecom_key_generate_ireq),
&resp, sizeof(resp));
if (ret) {
pr_err("scm call to generate key failed : %d\n", ret);
+ __qseecom_disable_clk(CLK_QSEE);
return ret;
}
@@ -2367,6 +2406,7 @@
ret = -EINVAL;
break;
}
+ __qseecom_disable_clk(CLK_QSEE);
return ret;
}
@@ -2386,11 +2426,13 @@
memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
ireq.flags = flags;
+ __qseecom_enable_clk(CLK_QSEE);
ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
&ireq, sizeof(struct qseecom_key_delete_ireq),
&resp, sizeof(struct qseecom_command_scm_resp));
if (ret) {
pr_err("scm call to delete key failed : %d\n", ret);
+ __qseecom_disable_clk(CLK_QSEE);
return ret;
}
@@ -2409,6 +2451,7 @@
ret = -EINVAL;
break;
}
+ __qseecom_disable_clk(CLK_QSEE);
return ret;
}
@@ -2424,6 +2467,12 @@
pr_err("Error:: unsupported usage %d\n", usage);
return -EFAULT;
}
+
+ if (qseecom.qsee.instance == qseecom.ce_drv.instance)
+ __qseecom_enable_clk(CLK_QSEE);
+ else
+ __qseecom_enable_clk(CLK_CE_DRV);
+
memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
ireq.ce = set_key_para->ce_hw;
ireq.pipe = set_key_para->pipe;
@@ -2459,6 +2508,11 @@
break;
}
+ if (qseecom.qsee.instance == qseecom.ce_drv.instance)
+ __qseecom_disable_clk(CLK_QSEE);
+ else
+ __qseecom_disable_clk(CLK_CE_DRV);
+
return ret;
}
@@ -2570,6 +2624,70 @@
return ret;
}
+static int qseecom_is_es_activated(void __user *argp)
+{
+ struct qseecom_is_es_activated_req req;
+ int ret;
+ int resp_buf;
+
+ if (qseecom.qsee_version < QSEE_VERSION_04) {
+ pr_err("invalid qsee version");
+ return -ENODEV;
+ }
+
+ if (argp == NULL) {
+ pr_err("arg is null");
+ return -EINVAL;
+ }
+
+ ret = scm_call(SCM_SVC_ES, SCM_IS_ACTIVATED_ID, NULL, 0,
+ (void *) &resp_buf, sizeof(resp_buf));
+ if (ret) {
+ pr_err("scm_call failed");
+ return ret;
+ }
+
+ req.is_activated = resp_buf;
+ ret = copy_to_user(argp, &req, sizeof(req));
+ if (ret) {
+ pr_err("copy_to_user failed");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int qseecom_save_partition_hash(void __user *argp)
+{
+ struct qseecom_save_partition_hash_req req;
+ int ret;
+
+ if (qseecom.qsee_version < QSEE_VERSION_04) {
+ pr_err("invalid qsee version ");
+ return -ENODEV;
+ }
+
+ if (argp == NULL) {
+ pr_err("arg is null");
+ return -EINVAL;
+ }
+
+ ret = copy_from_user(&req, argp, sizeof(req));
+ if (ret) {
+ pr_err("copy_from_user failed");
+ return ret;
+ }
+
+ ret = scm_call(SCM_SVC_ES, SCM_SAVE_PARTITION_HASH_ID,
+ (void *) &req, sizeof(req), NULL, 0);
+ if (ret) {
+ pr_err("scm_call failed");
+ return ret;
+ }
+
+ return 0;
+}
+
static long qseecom_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
@@ -2782,6 +2900,24 @@
mutex_unlock(&app_access_lock);
break;
}
+ case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_save_partition_hash(argp);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
+ case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_is_es_activated(argp);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
default:
return -EINVAL;
}
@@ -2877,18 +3013,43 @@
.release = qseecom_release
};
-static int __qseecom_init_clk(void)
+static int __qseecom_init_clk(enum qseecom_ce_hw_instance ce)
{
int rc = 0;
struct device *pdev;
struct qseecom_clk *qclk;
+ char *core_clk_src = NULL;
+ char *core_clk = NULL;
+ char *iface_clk = NULL;
+ char *bus_clk = NULL;
- qclk = &qseecom.qsee;
-
+ switch (ce) {
+ case CLK_QSEE: {
+ core_clk_src = "core_clk_src";
+ core_clk = "core_clk";
+ iface_clk = "iface_clk";
+ bus_clk = "bus_clk";
+ qclk = &qseecom.qsee;
+ qclk->instance = CLK_QSEE;
+ break;
+ };
+ case CLK_CE_DRV: {
+ core_clk_src = "ce_drv_core_clk_src";
+ core_clk = "ce_drv_core_clk";
+ iface_clk = "ce_drv_iface_clk";
+ bus_clk = "ce_drv_bus_clk";
+ qclk = &qseecom.ce_drv;
+ qclk->instance = CLK_CE_DRV;
+ break;
+ };
+ default:
+ pr_err("Invalid ce hw instance: %d!\n", ce);
+ return -EIO;
+ }
pdev = qseecom.pdev;
- /* Get CE3 src core clk. */
- qclk->ce_core_src_clk = clk_get(pdev, "core_clk_src");
+ /* Get CE3 src core clk. */
+ qclk->ce_core_src_clk = clk_get(pdev, core_clk_src);
if (!IS_ERR(qclk->ce_core_src_clk)) {
/* Set the core src clk @100Mhz */
rc = clk_set_rate(qclk->ce_core_src_clk, QSEE_CE_CLK_100MHZ);
@@ -2903,7 +3064,7 @@
}
/* Get CE core clk */
- qclk->ce_core_clk = clk_get(pdev, "core_clk");
+ qclk->ce_core_clk = clk_get(pdev, core_clk);
if (IS_ERR(qclk->ce_core_clk)) {
rc = PTR_ERR(qclk->ce_core_clk);
pr_err("Unable to get CE core clk\n");
@@ -2913,7 +3074,7 @@
}
/* Get CE Interface clk */
- qclk->ce_clk = clk_get(pdev, "iface_clk");
+ qclk->ce_clk = clk_get(pdev, iface_clk);
if (IS_ERR(qclk->ce_clk)) {
rc = PTR_ERR(qclk->ce_clk);
pr_err("Unable to get CE interface clk\n");
@@ -2924,7 +3085,7 @@
}
/* Get CE AXI clk */
- qclk->ce_bus_clk = clk_get(pdev, "bus_clk");
+ qclk->ce_bus_clk = clk_get(pdev, bus_clk);
if (IS_ERR(qclk->ce_bus_clk)) {
rc = PTR_ERR(qclk->ce_bus_clk);
pr_err("Unable to get CE BUS interface clk\n");
@@ -2937,11 +3098,14 @@
return rc;
}
-static void __qseecom_deinit_clk(void)
+static void __qseecom_deinit_clk(enum qseecom_ce_hw_instance ce)
{
struct qseecom_clk *qclk;
- qclk = &qseecom.qsee;
+ if (ce == CLK_QSEE)
+ qclk = &qseecom.qsee;
+ else
+ qclk = &qseecom.ce_drv;
if (qclk->ce_clk != NULL) {
clk_put(qclk->ce_clk);
@@ -2979,6 +3143,11 @@
qseecom.qsee.ce_core_src_clk = NULL;
qseecom.qsee.ce_bus_clk = NULL;
+ qseecom.ce_drv.ce_core_clk = NULL;
+ qseecom.ce_drv.ce_clk = NULL;
+ qseecom.ce_drv.ce_core_src_clk = NULL;
+ qseecom.ce_drv.ce_bus_clk = NULL;
+
rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
if (rc < 0) {
pr_err("alloc_chrdev_region failed %d\n", rc);
@@ -3053,6 +3222,7 @@
/* register client for bus scaling */
if (pdev->dev.of_node) {
+
if (of_property_read_u32((&pdev->dev)->of_node,
"qcom,disk-encrypt-pipe-pair",
&qseecom.ce_info.disk_encrypt_pipe)) {
@@ -3089,10 +3259,29 @@
qseecom.ce_info.hlos_ce_hw_instance);
}
- ret = __qseecom_init_clk();
+ qseecom.qsee.instance = qseecom.ce_info.qsee_ce_hw_instance;
+ qseecom.ce_drv.instance = qseecom.ce_info.hlos_ce_hw_instance;
+
+ ret = __qseecom_init_clk(CLK_QSEE);
if (ret)
goto err;
+ if (qseecom.qsee.instance != qseecom.ce_drv.instance) {
+ ret = __qseecom_init_clk(CLK_CE_DRV);
+ if (ret) {
+ __qseecom_deinit_clk(CLK_QSEE);
+ goto err;
+ }
+ } else {
+ struct qseecom_clk *qclk;
+
+ qclk = &qseecom.qsee;
+ qseecom.ce_drv.ce_core_clk = qclk->ce_core_clk;
+ qseecom.ce_drv.ce_clk = qclk->ce_clk;
+ qseecom.ce_drv.ce_core_src_clk = qclk->ce_core_src_clk;
+ qseecom.ce_drv.ce_bus_clk = qclk->ce_bus_clk;
+ }
+
qseecom_platform_support = (struct msm_bus_scale_pdata *)
msm_bus_cl_get_pdata(pdev);
if (qseecom.qsee_version >= (QSEE_VERSION_02)) {
@@ -3203,9 +3392,11 @@
msm_bus_scale_client_update_request(qseecom.qsee_perf_client,
0);
/* register client for bus scaling */
- if (pdev->dev.of_node)
- __qseecom_deinit_clk();
-
+ if (pdev->dev.of_node) {
+ __qseecom_deinit_clk(CLK_QSEE);
+ if (qseecom.qsee.instance != qseecom.ce_drv.instance)
+ __qseecom_deinit_clk(CLK_CE_DRV);
+ }
return ret;
};
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 44465dc..1a175c9 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -197,6 +197,7 @@
void __iomem *riva_ccu_base;
void __iomem *pronto_a2xb_base;
void __iomem *pronto_ccpu_base;
+ void __iomem *fiq_reg;
} *penv = NULL;
static ssize_t wcnss_serial_number_show(struct device *dev,
@@ -401,7 +402,7 @@
if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
wcnss_pronto_log_debug_regs();
wmb();
- __raw_writel(1 << 16, MSM_APCS_GCC_BASE + 0x8);
+ __raw_writel(1 << 16, penv->fiq_reg);
} else {
wcnss_riva_log_debug_regs();
wmb();
@@ -1068,6 +1069,7 @@
struct qcom_wcnss_opts *pdata;
unsigned long wcnss_phys_addr;
int size = 0;
+ struct resource *res;
int has_pronto_hw = of_property_read_bool(pdev->dev.of_node,
"qcom,has_pronto_hw");
@@ -1183,11 +1185,28 @@
pr_err("%s: ioremap wcnss physical failed\n", __func__);
goto fail_ioremap2;
}
+ /* for reset FIQ */
+ res = platform_get_resource_byname(penv->pdev,
+ IORESOURCE_MEM, "wcnss_fiq");
+ if (!res) {
+ dev_err(&pdev->dev, "insufficient irq mem resources\n");
+ ret = -ENOENT;
+ goto fail_ioremap3;
+ }
+ penv->fiq_reg = ioremap_nocache(res->start, resource_size(res));
+ if (!penv->fiq_reg) {
+ pr_err("wcnss: %s: ioremap_nocache() failed fiq_reg addr:%pr\n",
+ __func__, &res->start);
+ ret = -ENOMEM;
+ goto fail_ioremap3;
+ }
}
penv->cold_boot_done = 1;
return 0;
+fail_ioremap3:
+ iounmap(penv->pronto_ccpu_base);
fail_ioremap2:
iounmap(penv->pronto_a2xb_base);
fail_ioremap:
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index db7f7f0..5cc5d46 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -41,6 +41,7 @@
#define IPA_DMA_POOL_SIZE (512)
#define IPA_DMA_POOL_ALIGNMENT (4)
#define IPA_DMA_POOL_BOUNDARY (1024)
+#define IPA_NUM_DESC_PER_SW_TX (2)
#define IPA_ROUTING_RULE_BYTE_SIZE (4)
#define IPA_BAM_CNFG_BITS_VAL (0x7FFFE004)
@@ -1761,15 +1762,20 @@
* This is an issue with IPA HW v1.0 only.
*/
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_0) {
- ipa_ctx->one_kb_no_straddle_pool = dma_pool_create("ipa_1k",
+ ipa_ctx->dma_pool = dma_pool_create("ipa_1k",
NULL,
IPA_DMA_POOL_SIZE, IPA_DMA_POOL_ALIGNMENT,
IPA_DMA_POOL_BOUNDARY);
- if (!ipa_ctx->one_kb_no_straddle_pool) {
- IPAERR("cannot setup 1kb alloc DMA pool.\n");
- result = -ENOMEM;
- goto fail_dma_pool;
- }
+ } else {
+ ipa_ctx->dma_pool = dma_pool_create("ipa_tx", NULL,
+ IPA_NUM_DESC_PER_SW_TX * sizeof(struct sps_iovec),
+ 0, 0);
+ }
+
+ if (!ipa_ctx->dma_pool) {
+ IPAERR("cannot alloc DMA pool.\n");
+ result = -ENOMEM;
+ goto fail_dma_pool;
}
ipa_ctx->glob_flt_tbl[IPA_IP_v4].in_sys = !ipa_ctx->ip4_flt_tbl_lcl;
@@ -1976,7 +1982,7 @@
* DMA pool need to be released only for IPA HW v1.0 only.
*/
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_0)
- dma_pool_destroy(ipa_ctx->one_kb_no_straddle_pool);
+ dma_pool_destroy(ipa_ctx->dma_pool);
fail_dma_pool:
kmem_cache_destroy(ipa_ctx->tree_node_cache);
fail_tree_node_cache:
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 5f7f3d9..2555c6b 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -42,7 +42,7 @@
* the order for sent packet is the same as expected
* - delete all the tx packet descriptors from the system
* pipe context (not needed anymore)
- * - return the tx buffer back to one_kb_no_straddle_pool
+ * - return the tx buffer back to dma_pool
*/
void ipa_wq_write_done(struct work_struct *work)
{
@@ -80,7 +80,7 @@
list_del(&tx_pkt->link);
spin_unlock_irqrestore(&tx_pkt->sys->spinlock, irq_flags);
if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0)) {
- dma_pool_free(ipa_ctx->one_kb_no_straddle_pool,
+ dma_pool_free(ipa_ctx->dma_pool,
tx_pkt->bounce,
tx_pkt->mem.phys_base);
} else {
@@ -97,7 +97,7 @@
}
if (mult.phys_base)
- dma_free_coherent(NULL, mult.size, mult.base, mult.phys_base);
+ dma_pool_free(ipa_ctx->dma_pool, mult.base, mult.phys_base);
}
/**
@@ -144,7 +144,7 @@
* does not cross a 1KB boundary
*/
tx_pkt->bounce = dma_pool_alloc(
- ipa_ctx->one_kb_no_straddle_pool,
+ ipa_ctx->dma_pool,
mem_flag, &dma_address);
if (!tx_pkt->bounce) {
dma_address = 0;
@@ -208,7 +208,7 @@
list_del(&tx_pkt->link);
spin_unlock_irqrestore(&sys->spinlock, irq_flags);
if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
- dma_pool_free(ipa_ctx->one_kb_no_straddle_pool, tx_pkt->bounce,
+ dma_pool_free(ipa_ctx->dma_pool, tx_pkt->bounce,
dma_address);
else
dma_unmap_single(NULL, dma_address, desc->len, DMA_TO_DEVICE);
@@ -259,7 +259,7 @@
if (unlikely(!in_atomic))
mem_flag = GFP_KERNEL;
- transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, mem_flag);
+ transfer.iovec = dma_pool_alloc(ipa_ctx->dma_pool, mem_flag, &dma_addr);
transfer.iovec_phys = dma_addr;
transfer.iovec_count = num_desc;
spin_lock_irqsave(&sys->spinlock, irq_flags);
@@ -306,7 +306,7 @@
* packet does not cross a 1KB boundary
*/
tx_pkt->bounce =
- dma_pool_alloc(ipa_ctx->one_kb_no_straddle_pool,
+ dma_pool_alloc(ipa_ctx->dma_pool,
mem_flag,
&tx_pkt->mem.phys_base);
if (!tx_pkt->bounce) {
@@ -377,7 +377,7 @@
next_pkt = list_next_entry(tx_pkt, link);
list_del(&tx_pkt->link);
if (unlikely(ipa_ctx->ipa_hw_type == IPA_HW_v1_0))
- dma_pool_free(ipa_ctx->one_kb_no_straddle_pool,
+ dma_pool_free(ipa_ctx->dma_pool,
tx_pkt->bounce,
tx_pkt->mem.phys_base);
else
@@ -392,7 +392,7 @@
if (fail_dma_wrap)
kmem_cache_free(ipa_ctx->tx_pkt_wrapper_cache, tx_pkt);
if (transfer.iovec_phys)
- dma_free_coherent(NULL, size, transfer.iovec,
+ dma_pool_free(ipa_ctx->dma_pool, transfer.iovec,
transfer.iovec_phys);
failure_coherent:
spin_unlock_irqrestore(&sys->spinlock, irq_flags);
diff --git a/drivers/platform/msm/ipa/ipa_i.h b/drivers/platform/msm/ipa/ipa_i.h
index ca5740d..cb67514 100644
--- a/drivers/platform/msm/ipa/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_i.h
@@ -585,7 +585,7 @@
* @ip6_flt_tbl_lcl: where ip6 flt tables reside 1-local; 0-system
* @empty_rt_tbl_mem: empty routing tables memory
* @pipe_mem_pool: pipe memory pool
- * @one_kb_no_straddle_pool: one kb no straddle pool
+ * @dma_pool: special purpose DMA pool
* @ipa_hw_type: type of IPA HW type (e.g. IPA 1.0, IPA 1.1 etc')
* @ipa_hw_mode: mode of IPA HW mode (e.g. Normal, Virtual or over PCIe)
*
@@ -643,7 +643,7 @@
bool ip6_flt_tbl_lcl;
struct ipa_mem_buffer empty_rt_tbl_mem;
struct gen_pool *pipe_mem_pool;
- struct dma_pool *one_kb_no_straddle_pool;
+ struct dma_pool *dma_pool;
atomic_t ipa_active_clients;
u32 clnt_hdl_cmd;
u32 clnt_hdl_data_in;
diff --git a/drivers/platform/msm/ipa/ipa_intf.c b/drivers/platform/msm/ipa/ipa_intf.c
index 0f41d2c..5ee1929 100644
--- a/drivers/platform/msm/ipa/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_intf.c
@@ -432,6 +432,7 @@
}
IPA_STATS_INC_CNT(
ipa_ctx->stats.msg_r[msg->meta.msg_type]);
+ kfree(msg);
}
ret = -EAGAIN;
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 1d88280..fc5f668 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -505,6 +505,8 @@
IPAERR("failed to add to tree\n");
WARN_ON(1);
}
+ } else {
+ kmem_cache_free(ipa_ctx->tree_node_cache, node);
}
return entry;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e9cf973..459ab1d 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -4574,12 +4574,12 @@
int rc;
struct pm8921_chg_chip *chip = dev_get_drvdata(dev);
- pm8921_chg_force_19p2mhz_clk(chip);
-
rc = pm8921_chg_set_lpm(chip, 0);
if (rc)
pr_err("Failed to set lpm rc=%d\n", rc);
+ pm8921_chg_force_19p2mhz_clk(chip);
+
rc = pm_chg_masked_write(chip, CHG_CNTRL, VREF_BATT_THERM_FORCE_ON,
VREF_BATT_THERM_FORCE_ON);
if (rc)
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 331c7f1..6cc27c2 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1737,7 +1737,7 @@
}
/* Get the vddmax property */
- rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
+ rc = of_property_read_u32(spmi->dev.of_node, "qcom,vddmax-mv",
&chip->max_voltage_mv);
if (rc) {
pr_err("Error reading vddmax property %d\n", rc);
@@ -1745,7 +1745,7 @@
}
/* Get the vinmin property */
- rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
+ rc = of_property_read_u32(spmi->dev.of_node, "qcom,vinmin-mv",
&chip->min_voltage_mv);
if (rc) {
pr_err("Error reading vddmax property %d\n", rc);
@@ -1753,7 +1753,7 @@
}
/* Get the vddmax property */
- rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
+ rc = of_property_read_u32(spmi->dev.of_node, "qcom,vddsafe-mv",
&chip->safe_voltage_mv);
if (rc) {
pr_err("Error reading vddsave property %d\n", rc);
@@ -1762,7 +1762,7 @@
/* Get the vbatdet-delta property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-vbatdet-delta-mv",
+ "qcom,vbatdet-delta-mv",
&chip->resume_delta_mv);
if (rc && rc != -EINVAL) {
pr_err("Error reading vbatdet-delta property %d\n", rc);
@@ -1771,7 +1771,7 @@
/* Get the ibatsafe property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-ibatsafe-ma",
+ "qcom,ibatsafe-ma",
&chip->safe_current);
if (rc) {
pr_err("Error reading ibatsafe property %d\n", rc);
@@ -1780,7 +1780,7 @@
/* Get the ibatterm property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-ibatterm-ma",
+ "qcom,ibatterm-ma",
&chip->term_current);
if (rc && rc != -EINVAL) {
pr_err("Error reading ibatterm property %d\n", rc);
@@ -1788,7 +1788,7 @@
}
/* Get the ibatmax property */
- rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
+ rc = of_property_read_u32(spmi->dev.of_node, "qcom,ibatmax-ma",
&chip->max_bat_chg_current);
if (rc) {
pr_err("Error reading ibatmax property %d\n", rc);
@@ -1797,7 +1797,7 @@
/* Get the maxinput-dc-ma property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-maxinput-dc-ma",
+ "qcom,maxinput-dc-ma",
&chip->maxinput_dc_ma);
if (rc && rc != -EINVAL) {
pr_err("Error reading maxinput-dc-ma property %d\n", rc);
@@ -1806,7 +1806,7 @@
/* Get the maxinput-usb-ma property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-maxinput-usb-ma",
+ "qcom,maxinput-usb-ma",
&chip->maxinput_usb_ma);
if (rc && rc != -EINVAL) {
pr_err("Error reading maxinput-usb-ma property %d\n", rc);
@@ -1815,11 +1815,11 @@
/* Get the charging-disabled property */
chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
- "qcom,chg-charging-disabled");
+ "qcom,charging-disabled");
/* Get the warm-bat-degc property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-warm-bat-decidegc",
+ "qcom,warm-bat-decidegc",
&chip->warm_bat_decidegc);
if (rc && rc != -EINVAL) {
pr_err("Error reading warm-bat-degc property %d\n", rc);
@@ -1828,7 +1828,7 @@
/* Get the cool-bat-degc property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-cool-bat-decidegc",
+ "qcom,cool-bat-decidegc",
&chip->cool_bat_decidegc);
if (rc && rc != -EINVAL) {
pr_err("Error reading cool-bat-degc property %d\n", rc);
@@ -1844,7 +1844,7 @@
/* Get the ibatmax-warm property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-ibatmax-warm-ma",
+ "qcom,ibatmax-warm-ma",
&chip->warm_bat_chg_ma);
if (rc) {
pr_err("Error reading ibatmax-warm-ma %d\n", rc);
@@ -1853,7 +1853,7 @@
/* Get the ibatmax-cool property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-ibatmax-cool-ma",
+ "qcom,ibatmax-cool-ma",
&chip->cool_bat_chg_ma);
if (rc) {
pr_err("Error reading ibatmax-cool-ma %d\n", rc);
@@ -1861,7 +1861,7 @@
}
/* Get the cool-bat-mv property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-cool-bat-mv",
+ "qcom,cool-bat-mv",
&chip->cool_bat_mv);
if (rc) {
pr_err("Error reading cool-bat-mv property %d\n", rc);
@@ -1870,7 +1870,7 @@
/* Get the warm-bat-mv property */
rc = of_property_read_u32(spmi->dev.of_node,
- "qcom,chg-warm-bat-mv",
+ "qcom,warm-bat-mv",
&chip->warm_bat_mv);
if (rc) {
pr_err("Error reading warm-bat-mv property %d\n", rc);
@@ -1880,9 +1880,9 @@
/* Get the fake-batt-values property */
chip->use_default_batt_values = of_property_read_bool(spmi->dev.of_node,
- "qcom,chg-use-default-batt-values");
+ "qcom,use-default-batt-values");
- of_get_property(spmi->dev.of_node, "qcom,chg-thermal-mitigation",
+ of_get_property(spmi->dev.of_node, "qcom,thermal-mitigation",
&(chip->thermal_levels));
if (chip->thermal_levels > sizeof(int)) {
@@ -1897,10 +1897,10 @@
chip->thermal_levels /= sizeof(int);
rc = of_property_read_u32_array(spmi->dev.of_node,
- "qcom,chg-thermal-mitigation",
+ "qcom,thermal-mitigation",
chip->thermal_mitigation, chip->thermal_levels);
if (rc) {
- pr_err("qcom,chg-thermal-mitigation missing in dt\n");
+ pr_err("qcom,thermal-mitigation missing in dt\n");
goto fail_chg_enable;
}
}
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index 706fba7..9a4ea63 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -58,6 +58,17 @@
If unsure, say N.
+config SCSI_UFSHCD_PLATFORM
+ tristate "Platform bus based UFS Controller support"
+ depends on SCSI_UFSHCD
+ ---help---
+ This selects the UFS host controller support. Select this if
+ you have an UFS controller on Platform bus.
+
+ If you have a controller with this interface, say Y or M here.
+
+ If unsure, say N.
+
config SCSI_UFS_TEST
tristate "Universal Flash Storage host controller driver unit-tests"
depends on SCSI_UFSHCD && IOSCHED_TEST
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index bbcc202..8d6665b 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,4 +1,5 @@
# UFSHCD makefile
obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
+obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
obj-$(CONFIG_SCSI_UFS_TEST) += ufs_test.o
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
new file mode 100644
index 0000000..03319ac
--- /dev/null
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -0,0 +1,217 @@
+/*
+ * Universal Flash Storage Host controller Platform bus based glue driver
+ *
+ * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
+ * Copyright (C) 2011-2013 Samsung India Software Operations
+ *
+ * Authors:
+ * Santosh Yaraganavi <santosh.sy@samsung.com>
+ * Vinayak Holikatti <h.vinayak@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * See the COPYING file in the top-level directory or visit
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ *
+ * 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.
+ *
+ * This program is provided "AS IS" and "WITH ALL FAULTS" and
+ * without warranty of any kind. You are solely responsible for
+ * determining the appropriateness of using and distributing
+ * the program and assume all risks associated with your exercise
+ * of rights with respect to the program, including but not limited
+ * to infringement of third party rights, the risks and costs of
+ * program errors, damage to or loss of data, programs or equipment,
+ * and unavailability or interruption of operations. Under no
+ * circumstances will the contributor of this Program be liable for
+ * any damages of any kind arising from your use or distribution of
+ * this program.
+ */
+
+#include "ufshcd.h"
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM
+/**
+ * ufshcd_pltfrm_suspend - suspend power management function
+ * @dev: pointer to device handle
+ *
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ /*
+ * TODO:
+ * 1. Call ufshcd_suspend
+ * 2. Do bus specific power management
+ */
+
+ disable_irq(hba->irq);
+
+ return 0;
+}
+
+/**
+ * ufshcd_pltfrm_resume - resume power management function
+ * @dev: pointer to device handle
+ *
+ * Returns 0
+ */
+static int ufshcd_pltfrm_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ /*
+ * TODO:
+ * 1. Call ufshcd_resume.
+ * 2. Do bus specific wake up
+ */
+
+ enable_irq(hba->irq);
+
+ return 0;
+}
+#else
+#define ufshcd_pltfrm_suspend NULL
+#define ufshcd_pltfrm_resume NULL
+#endif
+
+/**
+ * ufshcd_pltfrm_probe - probe routine of the driver
+ * @pdev: pointer to Platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_probe(struct platform_device *pdev)
+{
+ struct ufs_hba *hba;
+ void __iomem *mmio_base;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ resource_size_t mem_size;
+ int err;
+ struct device *dev = &pdev->dev;
+
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res) {
+ dev_err(&pdev->dev,
+ "Memory resource not available\n");
+ err = -ENODEV;
+ goto out_error;
+ }
+
+ mem_size = resource_size(mem_res);
+ if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) {
+ dev_err(&pdev->dev,
+ "Cannot reserve the memory resource\n");
+ err = -EBUSY;
+ goto out_error;
+ }
+
+ mmio_base = ioremap_nocache(mem_res->start, mem_size);
+ if (!mmio_base) {
+ dev_err(&pdev->dev, "memory map failed\n");
+ err = -ENOMEM;
+ goto out_release_regions;
+ }
+
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq_res) {
+ dev_err(&pdev->dev, "IRQ resource not available\n");
+ err = -ENODEV;
+ goto out_iounmap;
+ }
+
+ err = dma_set_coherent_mask(dev, dev->coherent_dma_mask);
+ if (err) {
+ dev_err(&pdev->dev, "set dma mask failed\n");
+ goto out_iounmap;
+ }
+
+ err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start);
+ if (err) {
+ dev_err(&pdev->dev, "Intialization failed\n");
+ goto out_iounmap;
+ }
+
+ platform_set_drvdata(pdev, hba);
+
+ return 0;
+
+out_iounmap:
+ iounmap(mmio_base);
+out_release_regions:
+ release_mem_region(mem_res->start, mem_size);
+out_error:
+ return err;
+}
+
+/**
+ * ufshcd_pltfrm_remove - remove platform driver routine
+ * @pdev: pointer to platform device handle
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+ struct resource *mem_res;
+ resource_size_t mem_size;
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ disable_irq(hba->irq);
+
+ /* Some buggy controllers raise interrupt after
+ * the resources are removed. So first we unregister the
+ * irq handler and then the resources used by driver
+ */
+
+ free_irq(hba->irq, hba);
+ ufshcd_remove(hba);
+ mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem_res)
+ dev_err(&pdev->dev, "ufshcd: Memory resource not available\n");
+ else {
+ mem_size = resource_size(mem_res);
+ release_mem_region(mem_res->start, mem_size);
+ }
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+static const struct of_device_id ufs_of_match[] = {
+ { .compatible = "jedec,ufs-1.1"},
+};
+
+static const struct dev_pm_ops ufshcd_dev_pm_ops = {
+ .suspend = ufshcd_pltfrm_suspend,
+ .resume = ufshcd_pltfrm_resume,
+};
+
+static struct platform_driver ufshcd_pltfrm_driver = {
+ .probe = ufshcd_pltfrm_probe,
+ .remove = ufshcd_pltfrm_remove,
+ .driver = {
+ .name = "ufshcd",
+ .owner = THIS_MODULE,
+ .pm = &ufshcd_dev_pm_ops,
+ .of_match_table = ufs_of_match,
+ },
+};
+
+module_platform_driver(ufshcd_pltfrm_driver);
+
+MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
+MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
+MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(UFSHCD_DRIVER_VERSION);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 60fd40c..c32a478 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -478,7 +478,7 @@
ucd_cmd_ptr->header.dword_2 = 0;
ucd_cmd_ptr->exp_data_transfer_len =
- cpu_to_be32(lrbp->cmd->transfersize);
+ cpu_to_be32(lrbp->cmd->sdb.length);
memcpy(ucd_cmd_ptr->cdb,
lrbp->cmd->cmnd,
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 2dccca8..f095efb 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -301,6 +301,7 @@
int ret;
int port_idx;
int i;
+ u8 base;
pr_debug("%s: bam ports: %u bam2bam ports: %u data hsic ports: %u data hsuart ports: %u"
" smd ports: %u ctrl hsic ports: %u ctrl hsuart ports: %u"
@@ -317,9 +318,13 @@
}
if (no_ctrl_smd_ports) {
- ret = gsmd_ctrl_setup(no_ctrl_smd_ports);
+ ret = gsmd_ctrl_setup(FRMNET_CTRL_CLIENT,
+ no_ctrl_smd_ports, &base);
if (ret)
return ret;
+ for (i = 0; i < nr_rmnet_ports; i++)
+ if (rmnet_ports[i].port)
+ rmnet_ports[i].port->port_num += base;
}
if (no_data_hsic_ports) {
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index a9cca50..98307d3 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -46,6 +46,12 @@
void (*connect)(struct grmnet *g);
};
+enum ctrl_client {
+ FRMNET_CTRL_CLIENT,
+
+ NR_CTRL_CLIENTS
+};
+
int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
int gbam_connect(struct grmnet *gr, u8 port_num,
enum transport_type trans, u8 src_connection_idx,
@@ -56,7 +62,8 @@
void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans);
int gsmd_ctrl_connect(struct grmnet *gr, int port_num);
void gsmd_ctrl_disconnect(struct grmnet *gr, u8 port_num);
-int gsmd_ctrl_setup(unsigned int count);
+int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
+ u8 *first_port_idx);
int gqti_ctrl_connect(struct grmnet *gr);
void gqti_ctrl_disconnect(struct grmnet *gr);
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index 161634e..9b824bb 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -24,11 +24,15 @@
#include "u_rmnet.h"
-#define NR_CTRL_SMD_PORTS 3
-static int n_rmnet_ctrl_ports;
-static char *rmnet_ctrl_names[] = {"DATA40_CNTL", "DATA39_CNTL", "DATA38_CNTL"};
+#define MAX_CTRL_PER_CLIENT 3
+#define MAX_CTRL_PORT (MAX_CTRL_PER_CLIENT * NR_CTRL_CLIENTS)
+static char *ctrl_names[NR_CTRL_CLIENTS][MAX_CTRL_PER_CLIENT] = {
+ {"DATA40_CNTL", "DATA39_CNTL", "DATA38_CNTL"},
+};
static struct workqueue_struct *grmnet_ctrl_wq;
+u8 online_clients;
+
#define SMD_CH_MAX_LEN 20
#define CH_OPENED 0
#define CH_READY 1
@@ -68,7 +72,7 @@
static struct rmnet_ctrl_ports {
struct rmnet_ctrl_port *port;
struct platform_driver pdrv;
-} ctrl_smd_ports[NR_CTRL_SMD_PORTS];
+} ctrl_smd_ports[MAX_CTRL_PORT];
/*---------------misc functions---------------- */
@@ -172,6 +176,15 @@
}
spin_unlock_irqrestore(&port->port_lock, flags);
}
+static int is_legal_port_num(u8 portno)
+{
+ if (portno >= MAX_CTRL_PORT)
+ return false;
+ if (ctrl_smd_ports[portno].port == NULL)
+ return false;
+
+ return true;
+}
static int
grmnet_ctrl_smd_send_cpkt_tomodem(u8 portno,
@@ -182,7 +195,7 @@
struct smd_ch_info *c;
struct rmnet_ctrl_pkt *cpkt;
- if (portno >= n_rmnet_ctrl_ports) {
+ if (!is_legal_port_num(portno)) {
pr_err("%s: Invalid portno#%d\n", __func__, portno);
return -ENODEV;
}
@@ -225,7 +238,7 @@
int clear_bits = 0;
int temp = 0;
- if (portno >= n_rmnet_ctrl_ports) {
+ if (!is_legal_port_num(portno)) {
pr_err("%s: Invalid portno#%d\n", __func__, portno);
return;
}
@@ -375,8 +388,8 @@
pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
- if (port_num >= n_rmnet_ctrl_ports) {
- pr_err("%s: invalid portno#%d\n", __func__, port_num);
+ if (!is_legal_port_num(port_num)) {
+ pr_err("%s: Invalid port_num#%d\n", __func__, port_num);
return -ENODEV;
}
@@ -431,8 +444,8 @@
pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
- if (port_num >= n_rmnet_ctrl_ports) {
- pr_err("%s: invalid portno#%d\n", __func__, port_num);
+ if (!is_legal_port_num(port_num)) {
+ pr_err("%s: Invalid port_num#%d\n", __func__, port_num);
return;
}
@@ -478,7 +491,10 @@
pr_debug("%s: name:%s\n", __func__, pdev->name);
- for (i = 0; i < n_rmnet_ctrl_ports; i++) {
+ for (i = 0; i < MAX_CTRL_PORT; i++) {
+ if (!ctrl_smd_ports[i].port)
+ continue;
+
port = ctrl_smd_ports[i].port;
c = &port->ctrl_ch;
@@ -508,7 +524,10 @@
pr_debug("%s: name:%s\n", __func__, pdev->name);
- for (i = 0; i < n_rmnet_ctrl_ports; i++) {
+ for (i = 0; i < MAX_CTRL_PORT; i++) {
+ if (!ctrl_smd_ports[i].port)
+ continue;
+
port = ctrl_smd_ports[i].port;
c = &port->ctrl_ch;
@@ -555,7 +574,8 @@
INIT_DELAYED_WORK(&port->disconnect_w, grmnet_ctrl_smd_disconnect_w);
c = &port->ctrl_ch;
- c->name = rmnet_ctrl_names[portno];
+ c->name = ctrl_names[portno / MAX_CTRL_PER_CLIENT]
+ [portno % MAX_CTRL_PER_CLIENT];
c->port = port;
init_waitqueue_head(&c->wait);
INIT_LIST_HEAD(&c->tx_q);
@@ -575,44 +595,54 @@
return 0;
}
-int gsmd_ctrl_setup(unsigned int count)
+int gsmd_ctrl_setup(enum ctrl_client client_num, unsigned int count,
+ u8 *first_port_idx)
{
- int i;
+ int i, start_port, allocated_ports;
int ret;
pr_debug("%s: requested ports:%d\n", __func__, count);
- if (!count || count > NR_CTRL_SMD_PORTS) {
+ if (!count || count > MAX_CTRL_PER_CLIENT) {
pr_err("%s: Invalid num of ports count:%d\n",
__func__, count);
return -EINVAL;
}
- grmnet_ctrl_wq = alloc_workqueue("gsmd_ctrl",
- WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
- if (!grmnet_ctrl_wq) {
- pr_err("%s: Unable to create workqueue grmnet_ctrl\n",
- __func__);
- return -ENOMEM;
+ if (!online_clients) {
+ grmnet_ctrl_wq = alloc_workqueue("gsmd_ctrl",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!grmnet_ctrl_wq) {
+ pr_err("%s: Unable to create workqueue grmnet_ctrl\n",
+ __func__);
+ return -ENOMEM;
+ }
}
+ online_clients++;
- for (i = 0; i < count; i++) {
- n_rmnet_ctrl_ports++;
+ start_port = MAX_CTRL_PER_CLIENT * client_num;
+ allocated_ports = 0;
+ for (i = start_port; i < count + start_port; i++) {
+ allocated_ports++;
ret = grmnet_ctrl_smd_port_alloc(i);
if (ret) {
pr_err("%s: Unable to alloc port:%d\n", __func__, i);
- n_rmnet_ctrl_ports--;
+ allocated_ports--;
goto free_ctrl_smd_ports;
}
}
-
+ if (first_port_idx)
+ *first_port_idx = start_port;
return 0;
free_ctrl_smd_ports:
- for (i = 0; i < n_rmnet_ctrl_ports; i++)
- grmnet_ctrl_smd_port_free(i);
+ for (i = 0; i < allocated_ports; i++)
+ grmnet_ctrl_smd_port_free(start_port + i);
- destroy_workqueue(grmnet_ctrl_wq);
+
+ online_clients--;
+ if (!online_clients)
+ destroy_workqueue(grmnet_ctrl_wq);
return ret;
}
@@ -634,10 +664,11 @@
if (!buf)
return -ENOMEM;
- for (i = 0; i < n_rmnet_ctrl_ports; i++) {
- port = ctrl_smd_ports[i].port;
- if (!port)
+ for (i = 0; i < MAX_CTRL_PORT; i++) {
+ if (!ctrl_smd_ports[i].port)
continue;
+ port = ctrl_smd_ports[i].port;
+
spin_lock_irqsave(&port->port_lock, flags);
c = &port->ctrl_ch;
@@ -677,10 +708,10 @@
int i;
unsigned long flags;
- for (i = 0; i < n_rmnet_ctrl_ports; i++) {
- port = ctrl_smd_ports[i].port;
- if (!port)
+ for (i = 0; i < MAX_CTRL_PORT; i++) {
+ if (!ctrl_smd_ports[i].port)
continue;
+ port = ctrl_smd_ports[i].port;
spin_lock_irqsave(&port->port_lock, flags);
@@ -727,6 +758,7 @@
static int __init gsmd_ctrl_init(void)
{
gsmd_ctrl_debugfs_init();
+ online_clients = 0;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 51776db..baedd03 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -878,6 +878,7 @@
{
int i, j;
char *offset;
+ struct mdss_mdp_pipe *vig;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
@@ -899,7 +900,16 @@
writel_relaxed(j, offset);
/* swap */
- writel_relaxed(i, offset + 4);
+ writel_relaxed(1, offset + 4);
+ }
+ vig = mdata->vig_pipes;
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ offset = vig[i].base +
+ MDSS_MDP_REG_VIG_HIST_LUT_BASE;
+ for (j = 0; j < ENHIST_LUT_ENTRIES; j++)
+ writel_relaxed(j, offset);
+ /* swap */
+ writel_relaxed(1, offset + 16);
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
pr_debug("MDP hw init done\n");
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 25c5871..175a07f 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -249,6 +249,7 @@
struct mdss_pipe_pp_res {
u32 igc_c0_c1[IGC_LUT_ENTRIES];
u32 igc_c2[IGC_LUT_ENTRIES];
+ u32 hist_lut[ENHIST_LUT_ENTRIES];
struct pp_hist_col_info hist;
struct pp_sts_type pp_sts;
};
@@ -438,13 +439,14 @@
struct mdp_histogram_start_req *req);
int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block);
int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist,
- u32 *hist_data_addr);
+ struct mdp_histogram_data *hist);
void mdss_mdp_hist_intr_done(u32 isr);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
u32 type);
struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
+struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+ u32 ndx);
int mdss_mdp_pipe_map(struct mdss_mdp_pipe *pipe);
void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer);
@@ -466,6 +468,8 @@
struct mdss_mdp_plane_sizes *ps, u32 bwc_mode);
int mdss_mdp_get_rau_strides(u32 w, u32 h, struct mdss_mdp_format_params *fmt,
struct mdss_mdp_plane_sizes *ps);
+void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
+ struct mdss_mdp_plane_sizes *ps, struct mdss_mdp_format_params *fmt);
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 4e51100..03a33cd 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -279,8 +279,6 @@
return -EINVAL;
}
- mutex_lock(&mdss_mdp_ctl_lock);
- ctl->ref_cnt--;
if (ctl->mixer_left) {
mdss_mdp_mixer_free(ctl->mixer_left);
ctl->mixer_left = NULL;
@@ -289,6 +287,8 @@
mdss_mdp_mixer_free(ctl->mixer_right);
ctl->mixer_right = NULL;
}
+ mutex_lock(&mdss_mdp_ctl_lock);
+ ctl->ref_cnt--;
ctl->power_on = false;
ctl->start_fnc = NULL;
ctl->stop_fnc = NULL;
@@ -437,7 +437,6 @@
if (ctl->stop_fnc)
ctl->stop_fnc(ctl);
- mdss_mdp_mixer_free(mixer);
mdss_mdp_ctl_free(ctl);
mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 7fbb031..b3f15a7 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -33,9 +33,11 @@
u32 intf_num;
u32 opmode;
- u32 format;
+ struct mdss_mdp_format_params *dst_fmt;
u16 width;
u16 height;
+ struct mdss_mdp_img_rect dst_rect;
+
u8 rot90;
u32 bwc_mode;
int initialized;
@@ -81,48 +83,55 @@
}
static int mdss_mdp_writeback_addr_setup(struct mdss_mdp_writeback_ctx *ctx,
- struct mdss_mdp_data *data)
+ const struct mdss_mdp_data *in_data)
{
int ret;
+ struct mdss_mdp_data data;
- if (!data)
+ if (!in_data)
return -EINVAL;
+ data = *in_data;
- pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data->p[0].addr);
+ pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data.p[0].addr);
if (ctx->bwc_mode)
- data->bwc_enabled = 1;
+ data.bwc_enabled = 1;
- ret = mdss_mdp_data_check(data, &ctx->dst_planes);
+ ret = mdss_mdp_data_check(&data, &ctx->dst_planes);
if (ret)
return ret;
- mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST0_ADDR, data->p[0].addr);
- mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST1_ADDR, data->p[1].addr);
- mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST2_ADDR, data->p[2].addr);
- mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST3_ADDR, data->p[3].addr);
+ mdss_mdp_data_calc_offset(&data, ctx->dst_rect.x, ctx->dst_rect.y,
+ &ctx->dst_planes, ctx->dst_fmt);
+
+ mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST0_ADDR, data.p[0].addr);
+ mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST1_ADDR, data.p[1].addr);
+ mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST2_ADDR, data.p[2].addr);
+ mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST3_ADDR, data.p[3].addr);
return 0;
}
-static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx)
+static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx,
+ u32 format)
{
struct mdss_mdp_format_params *fmt;
u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp;
u32 opmode = ctx->opmode;
struct mdss_data_type *mdata;
- pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
+ pr_debug("wb_num=%d format=%d\n", ctx->wb_num, format);
- mdss_mdp_get_plane_sizes(ctx->format, ctx->width, ctx->height,
+ mdss_mdp_get_plane_sizes(format, ctx->width, ctx->height,
&ctx->dst_planes,
ctx->opmode & MDSS_MDP_OP_BWC_EN);
- fmt = mdss_mdp_get_format_params(ctx->format);
+ fmt = mdss_mdp_get_format_params(format);
if (!fmt) {
- pr_err("wb format=%d not supported\n", ctx->format);
+ pr_err("wb format=%d not supported\n", format);
return -EINVAL;
}
+ ctx->dst_fmt = fmt;
chroma_samp = fmt->chroma_sample;
@@ -190,7 +199,7 @@
(ctx->dst_planes.ystride[1] << 16);
ystride1 = (ctx->dst_planes.ystride[2]) |
(ctx->dst_planes.ystride[3] << 16);
- outsize = (ctx->height << 16) | ctx->width;
+ outsize = (ctx->dst_rect.h << 16) | ctx->dst_rect.w;
mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_FORMAT, dst_format);
mdp_wb_write(ctx, MDSS_MDP_REG_WB_DST_OP_MODE, opmode);
@@ -217,11 +226,14 @@
pr_debug("wfd setup ctl=%d\n", ctl->num);
ctx->opmode = 0;
- ctx->format = ctl->dst_format;
ctx->width = ctl->width;
ctx->height = ctl->height;
+ ctx->dst_rect.x = 0;
+ ctx->dst_rect.y = 0;
+ ctx->dst_rect.w = ctx->width;
+ ctx->dst_rect.h = ctx->height;
- ret = mdss_mdp_writeback_format_setup(ctx);
+ ret = mdss_mdp_writeback_format_setup(ctx, ctl->dst_format);
if (ret) {
pr_err("format setup failed\n");
return ret;
@@ -237,6 +249,7 @@
struct mdss_mdp_writeback_ctx *ctx;
struct mdss_mdp_writeback_arg *wb_args;
struct mdss_mdp_rotator_session *rot;
+ u32 format;
ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
if (!ctx)
@@ -259,24 +272,26 @@
ctx->bwc_mode = rot->bwc_mode;
ctx->opmode |= ctx->bwc_mode;
- ctx->width = rot->src_rect.w;
- ctx->height = rot->src_rect.h;
-
- ctx->format = rot->format;
+ ctx->width = rot->dst.w;
+ ctx->height = rot->dst.h;
+ ctx->dst_rect.x = rot->dst.x;
+ ctx->dst_rect.y = rot->dst.y;
+ ctx->dst_rect.w = rot->src_rect.w;
+ ctx->dst_rect.h = rot->src_rect.h;
ctx->rot90 = !!(rot->flags & MDP_ROT_90);
if (ctx->bwc_mode || ctx->rot90)
- ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+ format = mdss_mdp_get_rotator_dst_format(rot->format);
else
- ctx->format = rot->format;
+ format = rot->format;
if (ctx->rot90) {
ctx->opmode |= BIT(5); /* ROT 90 */
- swap(ctx->width, ctx->height);
+ swap(ctx->dst_rect.w, ctx->dst_rect.h);
}
- return mdss_mdp_writeback_format_setup(ctx);
+ return mdss_mdp_writeback_format_setup(ctx, format);
}
static int mdss_mdp_writeback_stop(struct mdss_mdp_ctl *ctl)
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index dae3e05..3cce4f9 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -92,8 +92,7 @@
return -EOVERFLOW;
}
- if (req->dst_rect.w < min_dst_size || req->dst_rect.h < min_dst_size ||
- req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H) {
+ if (req->dst_rect.w < min_dst_size || req->dst_rect.h < min_dst_size) {
pr_err("invalid destination resolution (%dx%d)",
req->dst_rect.w, req->dst_rect.h);
return -EOVERFLOW;
@@ -227,9 +226,13 @@
rot->src_rect.h /= 2;
}
- rot->params_changed++;
-
- req->id = rot->session_id;
+ ret = mdss_mdp_rotator_setup(rot);
+ if (ret == 0) {
+ req->id = rot->session_id;
+ } else {
+ pr_err("Unable to setup rotator session\n");
+ mdss_mdp_rotator_release(rot->session_id);
+ }
return ret;
}
@@ -243,11 +246,23 @@
struct mdss_mdp_mixer *mixer = NULL;
u32 pipe_type, mixer_mux, len, src_format;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdp_histogram_start_req hist;
int ret;
if (mdp5_data->ctl == NULL)
return -ENODEV;
+ if (req->flags & MDP_ROT_90) {
+ pr_err("unsupported inline rotation\n");
+ return -ENOTSUPP;
+ }
+
+ if ((req->dst_rect.w > MAX_DST_W) || (req->dst_rect.h > MAX_DST_H)) {
+ pr_err("exceeded max mixer supported resolution %dx%d\n",
+ req->dst_rect.w, req->dst_rect.h);
+ return -EOVERFLOW;
+ }
+
if (req->flags & MDSS_MDP_RIGHT_MIXER)
mixer_mux = MDSS_MDP_MIXER_MUX_RIGHT;
else
@@ -256,11 +271,6 @@
pr_debug("pipe ctl=%u req id=%x mux=%d\n", mdp5_data->ctl->num, req->id,
mixer_mux);
- if (req->flags & MDP_ROT_90) {
- pr_err("unsupported inline rotation\n");
- return -ENOTSUPP;
- }
-
src_format = req->src.format;
if (req->flags & (MDP_SOURCE_ROTATED_90 | MDP_BWC_EN))
src_format = mdss_mdp_get_rotator_dst_format(src_format);
@@ -365,7 +375,8 @@
pipe->is_fg = req->is_fg;
pipe->alpha = req->alpha;
pipe->transp = req->transp_mask;
- pipe->overfetch_disable = fmt->is_yuv;
+ pipe->overfetch_disable = fmt->is_yuv &&
+ !(pipe->flags & MDP_SOURCE_ROTATED_90);
pipe->req_data = *req;
@@ -389,6 +400,31 @@
pipe->pp_res.igc_c0_c1;
pipe->pp_cfg.igc_cfg.c2_data = pipe->pp_res.igc_c2;
}
+ if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_CFG) {
+ if (pipe->pp_cfg.hist_cfg.ops & MDP_PP_OPS_ENABLE) {
+ hist.block = pipe->pp_cfg.hist_cfg.block;
+ hist.frame_cnt =
+ pipe->pp_cfg.hist_cfg.frame_cnt;
+ hist.bit_mask = pipe->pp_cfg.hist_cfg.bit_mask;
+ hist.num_bins = pipe->pp_cfg.hist_cfg.num_bins;
+ mdss_mdp_histogram_start(pipe->mixer->ctl,
+ &hist);
+ } else if (pipe->pp_cfg.hist_cfg.ops &
+ MDP_PP_OPS_DISABLE) {
+ mdss_mdp_histogram_stop(pipe->mixer->ctl,
+ pipe->pp_cfg.hist_cfg.block);
+ }
+ }
+ len = pipe->pp_cfg.hist_lut_cfg.len;
+ if ((pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) &&
+ (len == ENHIST_LUT_ENTRIES)) {
+ ret = copy_from_user(pipe->pp_res.hist_lut,
+ pipe->pp_cfg.hist_lut_cfg.data,
+ sizeof(uint32_t) * len);
+ if (ret)
+ return -ENOMEM;
+ pipe->pp_cfg.hist_lut_cfg.data = pipe->pp_res.hist_lut;
+ }
}
if (pipe->flags & MDP_DEINTERLACE) {
@@ -1457,7 +1493,7 @@
int ret = -ENOSYS;
struct mdp_histogram_data hist;
struct mdp_histogram_start_req hist_req;
- u32 block, hist_data_addr = 0;
+ u32 block;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
switch (cmd) {
@@ -1488,15 +1524,9 @@
if (ret)
return ret;
- ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist,
- &hist_data_addr);
- if ((ret == 0) && hist_data_addr) {
- ret = copy_to_user(hist.c0, (u32 *)hist_data_addr,
- sizeof(u32) * hist.bin_cnt);
- if (ret == 0)
- ret = copy_to_user(argp, &hist,
- sizeof(hist));
- }
+ ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist);
+ if (!ret)
+ ret = copy_to_user(argp, &hist, sizeof(hist));
break;
default:
break;
@@ -1583,10 +1613,8 @@
ret = copy_to_user(argp, &req, sizeof(req));
}
- if (ret) {
+ if (ret)
pr_debug("OVERLAY_GET failed (%d)\n", ret);
- ret = -EFAULT;
- }
break;
case MSMFB_OVERLAY_SET:
@@ -1597,10 +1625,8 @@
if (!IS_ERR_VALUE(ret))
ret = copy_to_user(argp, &req, sizeof(req));
}
- if (ret) {
+ if (ret)
pr_debug("OVERLAY_SET failed (%d)\n", ret);
- ret = -EFAULT;
- }
break;
@@ -1629,10 +1655,8 @@
mdss_fb_update_backlight(mfd);
}
- if (ret) {
+ if (ret)
pr_debug("OVERLAY_PLAY failed (%d)\n", ret);
- ret = -EFAULT;
- }
} else {
ret = 0;
}
@@ -1646,10 +1670,8 @@
if (!ret)
ret = mdss_mdp_overlay_play_wait(mfd, &data);
- if (ret) {
+ if (ret)
pr_err("OVERLAY_PLAY_WAIT failed (%d)\n", ret);
- ret = -EFAULT;
- }
} else {
ret = 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index b169c43..242972b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -27,8 +27,6 @@
static DEFINE_MUTEX(mdss_mdp_smp_lock);
static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
-static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
- u32 ndx);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
@@ -257,9 +255,11 @@
pipe = NULL;
}
- if (pipe)
- pr_debug("type=%x pnum=%d\n", pipe->type, pipe->num);
- else
+ if (pipe) {
+ pr_info("type=%x pnum=%d\n", pipe->type, pipe->num);
+ mutex_init(&pipe->pp_res.hist.hist_mutex);
+ spin_lock_init(&pipe->pp_res.hist.hist_lock);
+ } else
pr_err("no %d type pipes available\n", type);
return pipe;
@@ -318,7 +318,7 @@
return pipe;
}
-static struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
+struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
u32 ndx)
{
u32 i;
@@ -487,28 +487,6 @@
return 0;
}
-static void mdss_mdp_addr_add_offset(struct mdss_mdp_pipe *pipe,
- struct mdss_mdp_data *data)
-{
- data->p[0].addr += pipe->src.x +
- (pipe->src.y * pipe->src_planes.ystride[0]);
- if (data->num_planes > 1) {
- u8 hmap[] = { 1, 2, 1, 2 };
- u8 vmap[] = { 1, 1, 2, 2 };
- u16 xoff = pipe->src.x / hmap[pipe->src_fmt->chroma_sample];
- u16 yoff = pipe->src.y / vmap[pipe->src_fmt->chroma_sample];
-
- if (data->num_planes == 2) /* pseudo planar */
- xoff *= 2;
- data->p[1].addr += xoff + (yoff * pipe->src_planes.ystride[1]);
-
- if (data->num_planes > 2) { /* planar */
- data->p[2].addr += xoff +
- (yoff * pipe->src_planes.ystride[2]);
- }
- }
-}
-
int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
u32 *ftch_id, u32 type, u32 num_base, u32 len)
{
@@ -571,7 +549,8 @@
return ret;
if (pipe->overfetch_disable)
- mdss_mdp_addr_add_offset(pipe, data);
+ mdss_mdp_data_calc_offset(data, pipe->src.x, pipe->src.y,
+ &pipe->src_planes, pipe->src_fmt);
/* planar format expects YCbCr, swap chroma planes if YCrCb */
if (!is_rot && (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR) &&
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 2e20eb6..cf9a8b6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -78,7 +78,7 @@
#define MDSS_BLOCK_DISP_NUM (MDP_BLOCK_MAX - MDP_LOGICAL_BLOCK_DISP_0)
-#define HIST_WAIT_TIMEOUT(frame) ((60 * HZ * (frame)) / 1000)
+#define HIST_WAIT_TIMEOUT(frame) ((75 * HZ * (frame)) / 1000)
/* hist collect state */
enum {
HIST_UNKNOWN,
@@ -154,11 +154,13 @@
};
static DEFINE_MUTEX(mdss_pp_mutex);
-static DEFINE_SPINLOCK(mdss_hist_lock);
-static DEFINE_MUTEX(mdss_mdp_hist_mutex);
static struct mdss_pp_res_type *mdss_pp_res;
-static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info);
+static void pp_hist_read(char __iomem *v_base,
+ struct pp_hist_col_info *hist_info);
+static int pp_histogram_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix);
+static int pp_histogram_disable(struct pp_hist_col_info *hist_info,
+ u32 done_bit, char __iomem *ctl_base);
static void pp_update_pcc_regs(u32 offset,
struct mdp_pcc_cfg_data *cfg_ptr);
static void pp_update_igc_lut(struct mdp_igc_lut_data *cfg,
@@ -167,7 +169,8 @@
struct mdp_ar_gc_lut_data *lut_data);
static void pp_update_argc_lut(u32 offset,
struct mdp_pgc_lut_data *config);
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg);
+static void pp_update_hist_lut(char __iomem *base,
+ struct mdp_hist_lut_data *cfg);
static void pp_pa_config(unsigned long flags, u32 base,
struct pp_sts_type *pp_sts,
struct mdp_pa_cfg *pa_config);
@@ -178,7 +181,7 @@
struct pp_sts_type *pp_sts,
struct mdp_igc_lut_data *igc_config,
u32 pipe_num);
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
struct pp_sts_type *pp_sts,
struct mdp_hist_lut_data *enhist_cfg);
static void pp_sharp_config(char __iomem *offset,
@@ -379,7 +382,7 @@
}
}
-static void pp_enhist_config(unsigned long flags, u32 base,
+static void pp_enhist_config(unsigned long flags, char __iomem *base,
struct pp_sts_type *pp_sts,
struct mdp_hist_lut_data *enhist_cfg)
{
@@ -419,6 +422,7 @@
{
u32 opmode = 0, base = 0;
unsigned long flags = 0;
+ char __iomem *offset;
pr_debug("pnum=%x\n", pipe->num);
@@ -452,6 +456,8 @@
}
}
+ pp_histogram_setup(&opmode, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer);
+
if (pipe->flags & MDP_OVERLAY_PP_CFG_EN) {
if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_PA_CFG) {
flags = PP_FLAGS_DIRTY_PA;
@@ -463,6 +469,26 @@
if (pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)
opmode |= (1 << 4); /* PA_EN */
}
+
+ if (pipe->pp_cfg.config_ops & MDP_OVERLAY_PP_HIST_LUT_CFG) {
+ pp_enhist_config(PP_FLAGS_DIRTY_ENHIST,
+ pipe->base + MDSS_MDP_REG_VIG_HIST_LUT_BASE,
+ &pipe->pp_res.pp_sts,
+ &pipe->pp_cfg.hist_lut_cfg);
+ }
+ }
+
+ if (pipe->pp_res.pp_sts.enhist_sts & PP_STS_ENABLE) {
+ /* Enable HistLUT and PA */
+ opmode |= BIT(10) | BIT(4);
+ if (!(pipe->pp_res.pp_sts.pa_sts & PP_STS_ENABLE)) {
+ /* Program default value */
+ offset = pipe->base + MDSS_MDP_REG_VIG_PA_BASE;
+ writel_relaxed(0, offset);
+ writel_relaxed(0, offset + 4);
+ writel_relaxed(0, offset + 8);
+ writel_relaxed(0, offset + 12);
+ }
}
*op = opmode;
@@ -692,6 +718,17 @@
void mdss_mdp_pipe_sspp_term(struct mdss_mdp_pipe *pipe)
{
+ u32 done_bit;
+ struct pp_hist_col_info *hist_info;
+ char __iomem *ctl_base;
+
+ if (!pipe && pipe->pp_res.hist.col_en) {
+ done_bit = 3 << (pipe->num * 4);
+ hist_info = &pipe->pp_res.hist;
+ ctl_base = pipe->base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ pp_histogram_disable(hist_info, done_bit, ctl_base);
+ }
memset(&pipe->pp_cfg, 0, sizeof(struct mdp_overlay_pp_params));
memset(&pipe->pp_res, 0, sizeof(struct mdss_pipe_pp_res));
}
@@ -784,16 +821,86 @@
return 0;
}
+static char __iomem *mdss_mdp_get_dspp_addr_off(u32 dspp_num)
+{
+ struct mdss_data_type *mdata;
+ struct mdss_mdp_mixer *mixer;
+
+ mdata = mdss_mdp_get_mdata();
+ if (mdata->nmixers_intf <= dspp_num) {
+ pr_err("Invalid dspp_num=%d", dspp_num);
+ return ERR_PTR(-EINVAL);
+ }
+ mixer = mdata->mixer_intf + dspp_num;
+ return mixer->dspp_base;
+}
+
+/* Assumes that function will be called from within clock enabled space*/
+static int pp_histogram_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix)
+{
+ int ret = -EINVAL;
+ char __iomem *base;
+ u32 op_flags, kick_base, col_state;
+ struct mdss_data_type *mdata;
+ struct mdss_mdp_pipe *pipe;
+ struct pp_hist_col_info *hist_info;
+ unsigned long flag;
+
+ if (mix && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG)) {
+ /* HIST_EN & AUTO_CLEAR */
+ op_flags = BIT(16) | BIT(17);
+ hist_info = &mdss_pp_res->dspp_hist[mix->num];
+ base = mdss_mdp_get_dspp_addr_off(PP_BLOCK(block));
+ kick_base = MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+ } else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG) {
+ mdata = mdss_mdp_get_mdata();
+ pipe = mdss_mdp_pipe_get(mdata, BIT(PP_BLOCK(block)));
+ if (IS_ERR_OR_NULL(pipe)) {
+ pr_debug("pipe DNE (%d)", (u32) BIT(PP_BLOCK(block)));
+ ret = -ENODEV;
+ goto error;
+ }
+ /* HIST_EN & AUTO_CLEAR */
+ op_flags = BIT(8) + BIT(9);
+ hist_info = &pipe->pp_res.hist;
+ base = pipe->base;
+ kick_base = MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ mdss_mdp_pipe_unmap(pipe);
+ } else {
+ pr_warn("invalid histogram location (%d)", block);
+ goto error;
+ }
+
+ if (hist_info->col_en) {
+ *op |= op_flags;
+ mutex_lock(&hist_info->hist_mutex);
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ col_state = hist_info->col_state;
+ if (hist_info->is_kick_ready &&
+ ((col_state == HIST_IDLE) ||
+ ((false == hist_info->read_request) &&
+ col_state == HIST_READY))) {
+ /* Kick off collection */
+ writel_relaxed(1, base + kick_base);
+ hist_info->col_state = HIST_START;
+ }
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ mutex_unlock(&hist_info->hist_mutex);
+ }
+ ret = 0;
+error:
+ return ret;
+}
+
static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_ctl *ctl,
struct mdss_mdp_mixer *mixer)
{
u32 flags, base, offset, dspp_num, opmode = 0;
struct mdp_dither_cfg_data *dither_cfg;
- struct pp_hist_col_info *hist_info;
struct mdp_pgc_lut_data *pgc_config;
struct pp_sts_type *pp_sts;
- u32 data, col_state;
- unsigned long flag;
+ u32 data;
+ char __iomem *basel;
int i, ret = 0;
if (!mixer || !ctl)
@@ -805,28 +912,13 @@
(dspp_num >= MDSS_MDP_MAX_DSPP))
return -EINVAL;
base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num);
- hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+ basel = mdss_mdp_get_dspp_addr_off(dspp_num);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- if (hist_info->col_en) {
- /* HIST_EN & AUTO_CLEAR */
- opmode |= (1 << 16) | (1 << 17);
- mutex_lock(&mdss_mdp_hist_mutex);
- spin_lock_irqsave(&mdss_hist_lock, flag);
- col_state = hist_info->col_state;
- if (hist_info->is_kick_ready &&
- ((col_state == HIST_IDLE) ||
- ((false == hist_info->read_request) &&
- col_state == HIST_READY))) {
- /* Kick off collection */
- MDSS_MDP_REG_WRITE(base +
- MDSS_MDP_REG_DSPP_HIST_CTL_BASE, 1);
- hist_info->col_state = HIST_START;
- }
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- mutex_unlock(&mdss_mdp_hist_mutex);
- }
+ ret = pp_histogram_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer);
+ if (ret)
+ goto dspp_exit;
if (disp_num < MDSS_BLOCK_DISP_NUM)
flags = mdss_pp_res->pp_disp_flags[disp_num];
@@ -834,7 +926,7 @@
flags = 0;
/* nothing to update */
- if ((!flags) && (!(hist_info->col_en)))
+ if ((!flags) && (!(opmode)))
goto dspp_exit;
pp_sts = &mdss_pp_res->pp_dspp_sts[dspp_num];
@@ -848,7 +940,7 @@
pp_igc_config(flags, MDSS_MDP_REG_IGC_DSPP_BASE, pp_sts,
&mdss_pp_res->igc_disp_cfg[disp_num], dspp_num);
- pp_enhist_config(flags, base + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
+ pp_enhist_config(flags, basel + MDSS_MDP_REG_DSPP_HIST_LUT_BASE,
pp_sts, &mdss_pp_res->enhist_disp_cfg[disp_num]);
if (pp_sts->pa_sts & PP_STS_ENABLE)
@@ -922,7 +1014,7 @@
if (pp_sts->pgc_sts & PP_STS_ENABLE)
opmode |= (1 << 22);
- MDSS_MDP_REG_WRITE(base + MDSS_MDP_REG_DSPP_OP_MODE, opmode);
+ writel_relaxed(opmode, basel + MDSS_MDP_REG_DSPP_OP_MODE);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, BIT(13 + dspp_num));
wmb();
dspp_exit:
@@ -1056,7 +1148,9 @@
int mdss_mdp_pp_init(struct device *dev)
{
- int ret = 0;
+ int i, ret = 0;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ struct mdss_mdp_pipe *vig;
mutex_lock(&mdss_pp_mutex);
if (!mdss_pp_res) {
@@ -1066,6 +1160,18 @@
pr_err("%s mdss_pp_res allocation failed!", __func__);
ret = -ENOMEM;
}
+
+ for (i = 0; i < MDSS_MDP_MAX_DSPP; i++) {
+ mutex_init(&mdss_pp_res->dspp_hist[i].hist_mutex);
+ spin_lock_init(&mdss_pp_res->dspp_hist[i].hist_lock);
+ }
+ }
+ if (mdata) {
+ vig = mdata->vig_pipes;
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ mutex_init(&vig[i].pp_res.hist.hist_mutex);
+ spin_lock_init(&vig[i].pp_res.hist.hist_lock);
+ }
}
mutex_unlock(&mdss_pp_mutex);
return ret;
@@ -1533,13 +1639,17 @@
}
/* Note: Assumes that its inputs have been checked by calling function */
-static void pp_update_hist_lut(u32 offset, struct mdp_hist_lut_data *cfg)
+static void pp_update_hist_lut(char __iomem *offset,
+ struct mdp_hist_lut_data *cfg)
{
int i;
for (i = 0; i < ENHIST_LUT_ENTRIES; i++)
- MDSS_MDP_REG_WRITE(offset, cfg->data[i]);
+ writel_relaxed(cfg->data[i], offset);
/* swap */
- MDSS_MDP_REG_WRITE(offset + 4, 1);
+ if (PP_LOCAT(cfg->block) == MDSS_PP_DSPP_CFG)
+ writel_relaxed(1, offset + 4);
+ else
+ writel_relaxed(1, offset + 16);
}
int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
@@ -1562,7 +1672,7 @@
mutex_lock(&mdss_pp_mutex);
disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
- switch (config->block & MDSS_PP_LOCATION_MASK) {
+ switch (PP_LOCAT(config->block)) {
case MDSS_PP_LM_CFG:
argc_offset = MDSS_MDP_REG_LM_OFFSET(dspp_num) +
MDSS_MDP_REG_LM_GC_LUT_BASE;
@@ -1658,12 +1768,12 @@
if (!ctl)
return -EINVAL;
- if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
- (config->block >= MDP_BLOCK_MAX))
+ if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
return -EINVAL;
mutex_lock(&mdss_pp_mutex);
- disp_num = config->block - MDP_LOGICAL_BLOCK_DISP_0;
+ disp_num = PP_BLOCK(config->block) - MDP_LOGICAL_BLOCK_DISP_0;
if (config->ops & MDP_PP_OPS_READ) {
ret = pp_get_dspp_num(disp_num, &dspp_num);
@@ -1821,124 +1931,205 @@
mdss_mdp_pp_setup(ctl);
return ret;
}
-static void pp_hist_read(u32 v_base, struct pp_hist_col_info *hist_info)
+static void pp_hist_read(char __iomem *v_base,
+ struct pp_hist_col_info *hist_info)
{
int i, i_start;
u32 data;
- data = MDSS_MDP_REG_READ(v_base);
+ data = readl_relaxed(v_base);
i_start = data >> 24;
hist_info->data[i_start] = data & 0xFFFFFF;
for (i = i_start + 1; i < HIST_V_SIZE; i++)
- hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+ hist_info->data[i] = readl_relaxed(v_base) & 0xFFFFFF;
for (i = 0; i < i_start - 1; i++)
- hist_info->data[i] = MDSS_MDP_REG_READ(v_base) & 0xFFFFFF;
+ hist_info->data[i] = readl_relaxed(v_base) & 0xFFFFFF;
hist_info->hist_cnt_read++;
}
-int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_start_req *req)
+/* Assumes that relevant clocks are enabled */
+static int pp_histogram_enable(struct pp_hist_col_info *hist_info,
+ struct mdp_histogram_start_req *req,
+ u32 shift_bit, char __iomem *ctl_base)
{
- u32 ctl_base, done_shift_bit;
+ unsigned long flag;
+ int ret = 0;
+ mutex_lock(&hist_info->hist_mutex);
+ /* check if it is idle */
+ if (hist_info->col_en) {
+ pr_info("%s Hist collection has already been enabled %d",
+ __func__, (u32) ctl_base);
+ ret = -EINVAL;
+ goto exit;
+ }
+ hist_info->frame_cnt = req->frame_cnt;
+ init_completion(&hist_info->comp);
+ hist_info->hist_cnt_read = 0;
+ hist_info->hist_cnt_sent = 0;
+ hist_info->hist_cnt_time = 0;
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ hist_info->read_request = false;
+ hist_info->col_state = HIST_RESET;
+ hist_info->col_en = true;
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ hist_info->is_kick_ready = false;
+ mdss_mdp_hist_irq_enable(3 << shift_bit);
+ writel_relaxed(req->frame_cnt, ctl_base + 8);
+ /* Kick out reset start */
+ writel_relaxed(1, ctl_base + 4);
+exit:
+ mutex_unlock(&hist_info->hist_mutex);
+ return ret;
+}
+
+int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
+ struct mdp_histogram_start_req *req)
+{
+ u32 done_shift_bit;
+ char __iomem *ctl_base;
struct pp_hist_col_info *hist_info;
int i, ret = 0;
u32 disp_num, dspp_num = 0;
u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
- unsigned long flag;
-
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if (!ctl)
return -EINVAL;
- if ((req->block < MDP_LOGICAL_BLOCK_DISP_0) ||
- (req->block >= MDP_BLOCK_MAX))
+ if ((PP_BLOCK(req->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (PP_BLOCK(req->block) >= MDP_BLOCK_MAX))
return -EINVAL;
- mutex_lock(&mdss_mdp_hist_mutex);
- disp_num = req->block - MDP_LOGICAL_BLOCK_DISP_0;
+ disp_num = PP_BLOCK(req->block) - MDP_LOGICAL_BLOCK_DISP_0;
mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
if (!mixer_cnt) {
pr_err("%s, no dspp connects to disp %d",
__func__, disp_num);
ret = -EPERM;
- goto hist_start_exit;
+ goto hist_exit;
}
if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
pr_err("%s, Too many dspp connects to disp %d",
__func__, mixer_cnt);
ret = -EPERM;
- goto hist_start_exit;
+ goto hist_exit;
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- for (i = 0; i < mixer_cnt; i++) {
- dspp_num = mixer_id[i];
- hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- done_shift_bit = (dspp_num * 4) + 12;
- /* check if it is idle */
- if (hist_info->col_en) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- pr_info("%s Hist collection has already been enabled %d",
- __func__, dspp_num);
- goto hist_start_exit;
+
+ if (PP_LOCAT(req->block) == MDSS_PP_SSPP_CFG) {
+ i = MDSS_PP_ARG_MASK & req->block;
+ if (!i) {
+ ret = -EINVAL;
+ pr_warn("Must pass pipe arguments, %d", i);
+ goto hist_exit;
}
- spin_lock_irqsave(&mdss_hist_lock, flag);
- hist_info->frame_cnt = req->frame_cnt;
- init_completion(&hist_info->comp);
- hist_info->hist_cnt_read = 0;
- hist_info->hist_cnt_sent = 0;
- hist_info->read_request = false;
- hist_info->col_state = HIST_RESET;
- hist_info->col_en = true;
- hist_info->is_kick_ready = false;
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- mdss_pp_res->hist_col[disp_num][i] =
- &mdss_pp_res->dspp_hist[dspp_num];
- mdss_mdp_hist_irq_enable(3 << done_shift_bit);
- ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
- MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
- MDSS_MDP_REG_WRITE(ctl_base + 8, req->frame_cnt);
- /* Kick out reset start */
- MDSS_MDP_REG_WRITE(ctl_base + 4, 1);
+
+ for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+ if (!PP_ARG(i, req->block))
+ continue;
+ pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+ if (IS_ERR_OR_NULL(pipe))
+ continue;
+ if (!pipe || pipe->num > MDSS_MDP_SSPP_VIG2) {
+ ret = -EINVAL;
+ pr_warn("Invalid Hist pipe (%d)", i);
+ goto hist_exit;
+ }
+ done_shift_bit = (pipe->num * 4);
+ hist_info = &pipe->pp_res.hist;
+ ctl_base = pipe->base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ ret = pp_histogram_enable(hist_info, req,
+ done_shift_bit, ctl_base);
+ mdss_mdp_pipe_unmap(pipe);
+ }
+ } else if (PP_LOCAT(req->block) == MDSS_PP_DSPP_CFG) {
+ for (i = 0; i < mixer_cnt; i++) {
+ dspp_num = mixer_id[i];
+ done_shift_bit = (dspp_num * 4) + 12;
+ hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+ ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+ MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+ ret = pp_histogram_enable(hist_info, req,
+ done_shift_bit, ctl_base);
+ mdss_pp_res->pp_disp_flags[disp_num] |=
+ PP_FLAGS_DIRTY_HIST_COL;
+ }
}
- for (i = mixer_cnt; i < MDSS_MDP_MAX_DSPP; i++)
- mdss_pp_res->hist_col[disp_num][i] = 0;
- mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-hist_start_exit:
- mutex_unlock(&mdss_mdp_hist_mutex);
- if (!ret) {
+
+hist_exit:
+ if (!ret && (PP_LOCAT(req->block) == MDSS_PP_DSPP_CFG)) {
mdss_mdp_pp_setup(ctl);
/* wait for a frame to let histrogram enable itself */
+ /* TODO add hysteresis value to be able to remove this sleep */
usleep(41666);
for (i = 0; i < mixer_cnt; i++) {
dspp_num = mixer_id[i];
hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- mutex_lock(&mdss_mdp_hist_mutex);
- spin_lock_irqsave(&mdss_hist_lock, flag);
+ mutex_lock(&hist_info->hist_mutex);
hist_info->is_kick_ready = true;
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- mutex_unlock(&mdss_mdp_hist_mutex);
+ mutex_unlock(&hist_info->hist_mutex);
+ }
+ } else if (!ret) {
+ for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+ if (!PP_ARG(i, req->block))
+ continue;
+ pr_info("PP_ARG(%d) = %d", i, PP_ARG(i, req->block));
+ pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+ if (IS_ERR_OR_NULL(pipe))
+ continue;
+ hist_info = &pipe->pp_res.hist;
+ hist_info->is_kick_ready = true;
+ mdss_mdp_pipe_unmap(pipe);
}
}
return ret;
}
+static int pp_histogram_disable(struct pp_hist_col_info *hist_info,
+ u32 done_bit, char __iomem *ctl_base)
+{
+ int ret = 0;
+ unsigned long flag;
+ mutex_lock(&hist_info->hist_mutex);
+ if (hist_info->col_en == false) {
+ pr_debug("Histogram already disabled (%d)", (u32) ctl_base);
+ ret = -EINVAL;
+ goto exit;
+ }
+ complete_all(&hist_info->comp);
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ hist_info->col_en = false;
+ hist_info->col_state = HIST_UNKNOWN;
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ hist_info->is_kick_ready = false;
+ mdss_mdp_hist_irq_disable(done_bit);
+ writel_relaxed(BIT(1), ctl_base);/* cancel */
+ ret = 0;
+exit:
+ mutex_unlock(&hist_info->hist_mutex);
+ return ret;
+}
+
int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block)
{
int i, ret = 0;
- u32 dspp_num, disp_num, ctl_base, done_bit;
+ char __iomem *ctl_base;
+ u32 dspp_num, disp_num, done_bit;
struct pp_hist_col_info *hist_info;
u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
- unsigned long flag;
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if (!ctl)
return -EINVAL;
- if ((block < MDP_LOGICAL_BLOCK_DISP_0) ||
- (block >= MDP_BLOCK_MAX))
+ if ((PP_BLOCK(block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (PP_BLOCK(block) >= MDP_BLOCK_MAX))
return -EINVAL;
- mutex_lock(&mdss_mdp_hist_mutex);
- disp_num = block - MDP_LOGICAL_BLOCK_DISP_0;
+ disp_num = PP_BLOCK(block) - MDP_LOGICAL_BLOCK_DISP_0;
mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
if (!mixer_cnt) {
@@ -1954,162 +2145,312 @@
goto hist_stop_exit;
}
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- for (i = 0; i < mixer_cnt; i++) {
- dspp_num = mixer_id[i];
- hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- done_bit = 3 << ((dspp_num * 4) + 12);
- ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
- MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
- if (hist_info->col_en == false) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG) {
+ i = MDSS_PP_ARG_MASK & block;
+ if (!i) {
+ pr_warn("Must pass pipe arguments, %d", i);
goto hist_stop_exit;
}
- complete_all(&hist_info->comp);
- spin_lock_irqsave(&mdss_hist_lock, flag);
- hist_info->col_en = false;
- hist_info->col_state = HIST_UNKNOWN;
- hist_info->is_kick_ready = false;
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- mdss_mdp_hist_irq_disable(done_bit);
- MDSS_MDP_REG_WRITE(ctl_base, (1 << 1));/* cancel */
+
+ for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+ if (!PP_ARG(i, block))
+ continue;
+ pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+ if (IS_ERR_OR_NULL(pipe) ||
+ pipe->num > MDSS_MDP_SSPP_VIG2) {
+ pr_warn("Invalid Hist pipe (%d)", i);
+ continue;
+ }
+ done_bit = 3 << (pipe->num * 4);
+ hist_info = &pipe->pp_res.hist;
+ ctl_base = pipe->base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ ret = pp_histogram_disable(hist_info, done_bit,
+ ctl_base);
+ mdss_mdp_pipe_unmap(pipe);
+ if (ret)
+ goto hist_stop_exit;
+ }
+ } else if (PP_LOCAT(block) == MDSS_PP_DSPP_CFG) {
+ for (i = 0; i < mixer_cnt; i++) {
+ dspp_num = mixer_id[i];
+ done_bit = 3 << ((dspp_num * 4) + 12);
+ hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+ ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+ MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+ ret = pp_histogram_disable(hist_info, done_bit,
+ ctl_base);
+ if (ret)
+ goto hist_stop_exit;
+ mdss_pp_res->pp_disp_flags[disp_num] |=
+ PP_FLAGS_DIRTY_HIST_COL;
+ }
}
- for (i = 0; i < MDSS_MDP_MAX_DSPP; i++)
- mdss_pp_res->hist_col[disp_num][i] = 0;
- mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_HIST_COL;
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
hist_stop_exit:
- mutex_unlock(&mdss_mdp_hist_mutex);
- if (!ret)
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ if (!ret && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG))
mdss_mdp_pp_setup(ctl);
return ret;
}
-int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist,
- u32 *hist_data_addr)
+static int pp_hist_collect(struct mdss_mdp_ctl *ctl,
+ struct mdp_histogram_data *hist,
+ struct pp_hist_col_info *hist_info,
+ char __iomem *ctl_base)
{
- int i, j, wait_ret, ret = 0;
- u32 timeout, v_base;
- struct pp_hist_col_info *hist_info;
- u32 dspp_num, disp_num, ctl_base;
- u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+ int wait_ret, ret = 0;
+ u32 timeout;
+ char __iomem *v_base;
unsigned long flag;
+ struct mdss_pipe_pp_res *res;
+ struct mdss_mdp_pipe *pipe;
+
+ mutex_lock(&hist_info->hist_mutex);
+ if ((hist_info->col_en == 0) ||
+ (hist_info->col_state == HIST_UNKNOWN)) {
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ /* wait for hist done if cache has no data */
+ if (hist_info->col_state != HIST_READY) {
+ hist_info->read_request = true;
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
+ mutex_unlock(&hist_info->hist_mutex);
+ /* flush updates before wait*/
+ if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG)
+ mdss_mdp_pp_setup(ctl);
+ if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
+ res = container_of(hist_info, struct mdss_pipe_pp_res,
+ hist);
+ pipe = container_of(res, struct mdss_mdp_pipe, pp_res);
+ pipe->params_changed++;
+ }
+ wait_ret = wait_for_completion_killable_timeout(
+ &(hist_info->comp), timeout);
+
+ mutex_lock(&hist_info->hist_mutex);
+ if (wait_ret == 0) {
+ ret = -ETIMEDOUT;
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ pr_debug("bin collection timedout, state %d",
+ hist_info->col_state);
+ /*
+ * When the histogram has timed out (usually
+ * underrun) change the SW state back to idle
+ * since histogram hardware will have done the
+ * same. Histogram data also needs to be
+ * cleared in this case, which is done by the
+ * histogram being read (triggered by READY
+ * state, which also moves the histogram SW back
+ * to IDLE).
+ */
+ hist_info->hist_cnt_time++;
+ hist_info->col_state = HIST_READY;
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ } else if (wait_ret < 0) {
+ ret = -EINTR;
+ pr_debug("%s: bin collection interrupted",
+ __func__);
+ goto hist_collect_exit;
+ }
+ if (hist_info->col_state != HIST_READY) {
+ ret = -ENODATA;
+ pr_debug("%s: state is not ready: %d",
+ __func__, hist_info->col_state);
+ goto hist_collect_exit;
+ }
+ } else {
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ }
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ if (hist_info->col_state == HIST_READY) {
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+ v_base = ctl_base + 0x1C;
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ pp_hist_read(v_base, hist_info);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ spin_lock_irqsave(&hist_info->hist_lock, flag);
+ hist_info->read_request = false;
+ hist_info->col_state = HIST_IDLE;
+ }
+ spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+hist_collect_exit:
+ mutex_unlock(&hist_info->hist_mutex);
+ return ret;
+}
+
+int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
+ struct mdp_histogram_data *hist)
+{
+ int i, j, off, ret = 0;
+ struct pp_hist_col_info *hist_info;
+ u32 dspp_num, disp_num;
+ char __iomem *ctl_base;
+ u32 hist_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
+ u32 *hist_concat = NULL;
+ u32 *hist_data_addr;
+ u32 pipe_cnt = 0;
+ u32 pipe_num = MDSS_MDP_SSPP_VIG0;
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if (!ctl)
return -EINVAL;
- if ((hist->block < MDP_LOGICAL_BLOCK_DISP_0) ||
- (hist->block >= MDP_BLOCK_MAX))
+ if ((PP_BLOCK(hist->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
+ (PP_BLOCK(hist->block) >= MDP_BLOCK_MAX))
return -EINVAL;
- mutex_lock(&mdss_mdp_hist_mutex);
- disp_num = hist->block - MDP_LOGICAL_BLOCK_DISP_0;
- mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
+ disp_num = PP_BLOCK(hist->block) - MDP_LOGICAL_BLOCK_DISP_0;
+ hist_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id);
- if (!mixer_cnt) {
+ if (!hist_cnt) {
pr_err("%s, no dspp connects to disp %d",
__func__, disp_num);
ret = -EPERM;
goto hist_collect_exit;
}
- if (mixer_cnt >= MDSS_MDP_MAX_DSPP) {
+ if (hist_cnt >= MDSS_MDP_MAX_DSPP) {
pr_err("%s, Too many dspp connects to disp %d",
- __func__, mixer_cnt);
+ __func__, hist_cnt);
ret = -EPERM;
goto hist_collect_exit;
}
- hist_info = &mdss_pp_res->dspp_hist[0];
- for (i = 0; i < mixer_cnt; i++) {
- dspp_num = mixer_id[i];
- hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- ctl_base = MDSS_MDP_REG_DSPP_OFFSET(dspp_num) +
- MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
- if ((hist_info->col_en == 0) ||
- (hist_info->col_state == HIST_UNKNOWN)) {
- ret = -EINVAL;
- goto hist_collect_exit;
- }
- spin_lock_irqsave(&mdss_hist_lock, flag);
- /* wait for hist done if cache has no data */
- if (hist_info->col_state != HIST_READY) {
- hist_info->read_request = true;
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
- mutex_unlock(&mdss_mdp_hist_mutex);
- /* flush updates before wait*/
- mdss_mdp_pp_setup(ctl);
- wait_ret = wait_for_completion_killable_timeout(
- &(hist_info->comp), timeout);
-
- mutex_lock(&mdss_mdp_hist_mutex);
- if (wait_ret == 0) {
- ret = -ETIMEDOUT;
- spin_lock_irqsave(&mdss_hist_lock, flag);
- pr_debug("bin collection timedout, state %d",
- hist_info->col_state);
- /*
- * When the histogram has timed out (usually
- * underrun) change the SW state back to idle
- * since histogram hardware will have done the
- * same. Histogram data also needs to be
- * cleared in this case, which is done by the
- * histogram being read (triggered by READY
- * state, which also moves the histogram SW back
- * to IDLE).
- */
- hist_info->col_state = HIST_READY;
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- } else if (wait_ret < 0) {
- ret = -EINTR;
- pr_debug("%s: bin collection interrupted",
- __func__);
- goto hist_collect_exit;
- }
- if (hist_info->col_state != HIST_READY) {
- ret = -ENODATA;
- pr_debug("%s: state is not ready: %d",
- __func__, hist_info->col_state);
- goto hist_collect_exit;
- }
- } else {
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- }
- spin_lock_irqsave(&mdss_hist_lock, flag);
- if (hist_info->col_state == HIST_READY) {
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- v_base = ctl_base + 0x1C;
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- pp_hist_read(v_base, hist_info);
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
- spin_lock_irqsave(&mdss_hist_lock, flag);
- hist_info->read_request = false;
- hist_info->col_state = HIST_IDLE;
- }
- spin_unlock_irqrestore(&mdss_hist_lock, flag);
- }
- if (mixer_cnt > 1) {
- memset(&mdss_pp_res->hist_data[disp_num][0],
- 0, HIST_V_SIZE * sizeof(u32));
- for (i = 0; i < mixer_cnt; i++) {
+ if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG) {
+ hist_info = &mdss_pp_res->dspp_hist[disp_num];
+ for (i = 0; i < hist_cnt; i++) {
dspp_num = mixer_id[i];
hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- for (j = 0; j < HIST_V_SIZE; j++)
- mdss_pp_res->hist_data[disp_num][i] +=
- hist_info->data[i];
+ ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
+ MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
+ ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+ if (ret)
+ goto hist_collect_exit;
}
- *hist_data_addr = (u32)&mdss_pp_res->hist_data[disp_num][0];
+ if (hist_cnt > 1) {
+ if (hist->bin_cnt != HIST_V_SIZE) {
+ pr_err("User not expecting size %d output",
+ HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
+ hist_concat = kmalloc(HIST_V_SIZE * sizeof(u32),
+ GFP_KERNEL);
+ if (!hist_concat) {
+ ret = -ENOMEM;
+ goto hist_collect_exit;
+ }
+ memset(hist_concat, 0, HIST_V_SIZE * sizeof(u32));
+ for (i = 0; i < hist_cnt; i++) {
+ dspp_num = mixer_id[i];
+ hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+ mutex_lock(&hist_info->hist_mutex);
+ for (j = 0; j < HIST_V_SIZE; j++)
+ hist_concat[i] += hist_info->data[i];
+ mutex_unlock(&hist_info->hist_mutex);
+ }
+ hist_data_addr = hist_concat;
+ } else {
+ hist_data_addr = hist_info->data;
+ }
+ hist_info = &mdss_pp_res->dspp_hist[disp_num];
+ hist_info->hist_cnt_sent++;
+ } else if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
+
+ hist_cnt = MDSS_PP_ARG_MASK & hist->block;
+ if (!hist_cnt) {
+ pr_warn("Must pass pipe arguments, %d", hist_cnt);
+ goto hist_collect_exit;
+ }
+
+ /* Find the first pipe requested */
+ for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
+ if (PP_ARG(i, hist_cnt)) {
+ pipe_num = i;
+ break;
+ }
+ }
+
+ pipe = mdss_mdp_pipe_get(mdata, BIT(pipe_num));
+ if (IS_ERR_OR_NULL(pipe)) {
+ pr_warn("Invalid starting hist pipe, %d", pipe_num);
+ ret = -ENODEV;
+ goto hist_collect_exit;
+ }
+ hist_info = &pipe->pp_res.hist;
+ mdss_mdp_pipe_unmap(pipe);
+ for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+ if (!PP_ARG(i, hist->block))
+ continue;
+ pipe_cnt++;
+ pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+ if (IS_ERR_OR_NULL(pipe) ||
+ pipe->num > MDSS_MDP_SSPP_VIG2) {
+ pr_warn("Invalid Hist pipe (%d)", i);
+ continue;
+ }
+ hist_info = &pipe->pp_res.hist;
+ ctl_base = pipe->base +
+ MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+ ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+ mdss_mdp_pipe_unmap(pipe);
+ if (ret)
+ goto hist_collect_exit;
+ }
+ if (pipe_cnt > 1) {
+ if (hist->bin_cnt != (HIST_V_SIZE * pipe_cnt)) {
+ pr_err("User not expecting size %d output",
+ pipe_cnt * HIST_V_SIZE);
+ ret = -EINVAL;
+ goto hist_collect_exit;
+ }
+ hist_concat = kmalloc(HIST_V_SIZE * pipe_cnt *
+ sizeof(u32), GFP_KERNEL);
+ if (!hist_concat) {
+ ret = -ENOMEM;
+ goto hist_collect_exit;
+ }
+
+ memset(hist_concat, 0, pipe_cnt * HIST_V_SIZE *
+ sizeof(u32));
+ for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+ if (!PP_ARG(i, hist->block))
+ continue;
+ pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+ hist_info = &pipe->pp_res.hist;
+ off = HIST_V_SIZE * i;
+ mutex_lock(&hist_info->hist_mutex);
+ for (j = off; j < off + HIST_V_SIZE; j++)
+ hist_concat[j] =
+ hist_info->data[j - off];
+ hist_info->hist_cnt_sent++;
+ mutex_unlock(&hist_info->hist_mutex);
+ mdss_mdp_pipe_unmap(pipe);
+ }
+
+ hist_data_addr = hist_concat;
+ } else {
+ hist_data_addr = hist_info->data;
+ }
} else {
- *hist_data_addr = (u32)hist_info->data;
+ pr_info("No Histogram at location %d", PP_LOCAT(hist->block));
+ goto hist_collect_exit;
}
- hist_info->hist_cnt_sent++;
+ ret = copy_to_user(hist->c0, hist_data_addr, sizeof(u32) *
+ hist->bin_cnt);
hist_collect_exit:
- mutex_unlock(&mdss_mdp_hist_mutex);
+ kfree(hist_concat);
+
return ret;
}
void mdss_mdp_hist_intr_done(u32 isr)
{
u32 isr_blk, blk_idx;
- struct pp_hist_col_info *hist_info;
+ struct pp_hist_col_info *hist_info = NULL;
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
isr &= 0x333333;
while (isr != 0) {
if (isr & 0xFFF000) {
@@ -2129,36 +2470,40 @@
hist_info = &mdss_pp_res->dspp_hist[blk_idx];
} else {
if (isr & 0x3) {
- blk_idx = 0;
+ blk_idx = MDSS_MDP_SSPP_VIG0;
isr_blk = isr & 0x3;
isr &= ~0x3;
} else if (isr & 0x30) {
- blk_idx = 1;
+ blk_idx = MDSS_MDP_SSPP_VIG1;
isr_blk = (isr >> 4) & 0x3;
isr &= ~0x30;
} else {
- blk_idx = 2;
+ blk_idx = MDSS_MDP_SSPP_VIG2;
isr_blk = (isr >> 8) & 0x3;
isr &= ~0x300;
}
- /* SSPP block, not support yet*/
- continue;
+ pipe = mdss_mdp_pipe_search(mdata, BIT(blk_idx));
+ if (IS_ERR_OR_NULL(pipe)) {
+ pr_debug("pipe DNE, %d", blk_idx);
+ continue;
+ }
+ hist_info = &pipe->pp_res.hist;
}
/* Histogram Done Interrupt */
- if ((isr_blk & 0x1) &&
+ if (hist_info && (isr_blk & 0x1) &&
(hist_info->col_en)) {
- spin_lock(&mdss_hist_lock);
+ spin_lock(&hist_info->hist_lock);
hist_info->col_state = HIST_READY;
- spin_unlock(&mdss_hist_lock);
+ spin_unlock(&hist_info->hist_lock);
if (hist_info->read_request)
complete(&hist_info->comp);
}
/* Histogram Reset Done Interrupt */
if ((isr_blk & 0x2) &&
(hist_info->col_en)) {
- spin_lock(&mdss_hist_lock);
+ spin_lock(&hist_info->hist_lock);
hist_info->col_state = HIST_IDLE;
- spin_unlock(&mdss_hist_lock);
+ spin_unlock(&hist_info->hist_lock);
}
};
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 5711653..ce4c28f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -27,6 +27,8 @@
static struct mdss_mdp_rotator_session rotator_session[MAX_ROTATOR_SESSIONS];
static LIST_HEAD(rotator_queue);
+static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot);
+
struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
{
struct mdss_mdp_rotator_session *rot;
@@ -166,27 +168,21 @@
return 0;
}
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
+static int mdss_mdp_rotator_queue_sub(struct mdss_mdp_rotator_session *rot,
struct mdss_mdp_data *src_data,
struct mdss_mdp_data *dst_data)
{
struct mdss_mdp_pipe *rot_pipe = NULL;
struct mdss_mdp_ctl *ctl;
- int ret, need_wait = false;
+ int ret;
- ret = mutex_lock_interruptible(&rotator_lock);
- if (ret)
- return ret;
-
- if (!rot || !rot->ref_cnt) {
- mutex_unlock(&rotator_lock);
- return -ENODEV;
- }
+ if (!rot || !rot->ref_cnt)
+ return -ENOENT;
ret = mdss_mdp_rotator_pipe_dequeue(rot);
if (ret) {
pr_err("unable to acquire rotator\n");
- goto done;
+ return ret;
}
rot_pipe = rot->pipe;
@@ -203,31 +199,141 @@
rot_pipe->img_height = rot->img_height;
rot_pipe->src = rot->src_rect;
rot_pipe->dst = rot->src_rect;
+ rot_pipe->dst.x = 0;
+ rot_pipe->dst.y = 0;
rot_pipe->params_changed++;
}
ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
if (ret) {
pr_err("unable to queue rot data\n");
- goto done;
+ return ret;
}
ret = mdss_mdp_rotator_kickoff(ctl, rot, dst_data);
- if (ret == 0 && !rot->no_wait)
- need_wait = true;
-done:
+ return ret;
+}
+
+int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
+ struct mdss_mdp_data *src_data,
+ struct mdss_mdp_data *dst_data)
+{
+ int ret;
+ struct mdss_mdp_rotator_session *tmp = rot;
+
+ ret = mutex_lock_interruptible(&rotator_lock);
+ if (ret)
+ return ret;
+
+ pr_debug("rotator session=%x start\n", rot->session_id);
+
+ for (ret = 0, tmp = rot; ret == 0 && tmp; tmp = tmp->next)
+ ret = mdss_mdp_rotator_queue_sub(tmp, src_data, dst_data);
+
mutex_unlock(&rotator_lock);
- if (need_wait)
- mdss_mdp_rotator_busy_wait(rot);
+ if (ret) {
+ pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id);
+ return ret;
+ }
- if (rot_pipe)
- pr_debug("end of rotator pnum=%d enqueue\n", rot_pipe->num);
+ for (tmp = rot; tmp; tmp = tmp->next)
+ mdss_mdp_rotator_busy_wait(tmp);
+
+ pr_debug("rotator session=%x queue done\n", rot->session_id);
return ret;
}
+int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)
+{
+
+ rot->dst = rot->src_rect;
+ /*
+ * by default, rotator output should be placed directly on
+ * output buffer address without any offset.
+ */
+ rot->dst.x = 0;
+ rot->dst.y = 0;
+
+ if (rot->flags & MDP_ROT_90)
+ swap(rot->dst.w, rot->dst.h);
+
+ if (rot->src_rect.w > MAX_MIXER_WIDTH) {
+ struct mdss_mdp_rotator_session *tmp;
+ u32 width;
+
+ if (rot->bwc_mode) {
+ pr_err("Unable to do split rotation with bwc set\n");
+ return -EINVAL;
+ }
+
+ width = rot->src_rect.w;
+
+ pr_debug("setting up split rotation src=%dx%d\n",
+ rot->src_rect.w, rot->src_rect.h);
+
+ if (width > (MAX_MIXER_WIDTH * 2)) {
+ pr_err("unsupported source width %d\n", width);
+ return -EOVERFLOW;
+ }
+
+ if (!rot->next) {
+ tmp = mdss_mdp_rotator_session_alloc();
+ if (!tmp) {
+ pr_err("unable to allocate rot dual session\n");
+ return -ENOMEM;
+ }
+ rot->next = tmp;
+ }
+ tmp = rot->next;
+
+ tmp->session_id = rot->session_id & ~MDSS_MDP_ROT_SESSION_MASK;
+ tmp->flags = rot->flags;
+ tmp->format = rot->format;
+ tmp->img_width = rot->img_width;
+ tmp->img_height = rot->img_height;
+ tmp->src_rect = rot->src_rect;
+
+ tmp->src_rect.w = width / 2;
+ width -= tmp->src_rect.w;
+ tmp->src_rect.x += width;
+
+ tmp->dst = rot->dst;
+ rot->src_rect.w = width;
+
+ if (rot->flags & MDP_ROT_90) {
+ /*
+ * If rotated by 90 first half should be on top.
+ * But if horizontally flipped should be on bottom.
+ */
+ if (rot->flags & MDP_FLIP_LR)
+ rot->dst.y = tmp->src_rect.w;
+ else
+ tmp->dst.y = rot->src_rect.w;
+ } else {
+ /*
+ * If not rotated, first half should be the left part
+ * of the frame, unless horizontally flipped
+ */
+ if (rot->flags & MDP_FLIP_LR)
+ rot->dst.x = tmp->src_rect.w;
+ else
+ tmp->dst.x = rot->src_rect.w;
+ }
+
+ tmp->params_changed++;
+ } else if (rot->next) {
+ mdss_mdp_rotator_finish(rot->next);
+ rot->next = NULL;
+ }
+
+ rot->params_changed++;
+
+ return 0;
+}
+
static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
{
struct mdss_mdp_pipe *rot_pipe;
@@ -237,6 +343,9 @@
pr_debug("finish rot id=%x\n", rot->session_id);
+ if (rot->next)
+ mdss_mdp_rotator_finish(rot->next);
+
rot_pipe = rot->pipe;
if (rot_pipe) {
mdss_mdp_rotator_busy_wait(rot);
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index 21ee9bb..c50d710 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -30,6 +30,7 @@
u16 img_width;
u16 img_height;
struct mdss_mdp_img_rect src_rect;
+ struct mdss_mdp_img_rect dst;
u32 bwc_mode;
struct mdss_mdp_pipe *pipe;
@@ -40,6 +41,7 @@
u8 no_wait;
struct list_head head;
+ struct mdss_mdp_rotator_session *next;
};
static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
@@ -61,6 +63,7 @@
struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
+int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
struct mdss_mdp_data *src_data,
struct mdss_mdp_data *dst_data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index 5915f61..4de6d03 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -387,6 +387,31 @@
return 0;
}
+void mdss_mdp_data_calc_offset(struct mdss_mdp_data *data, u16 x, u16 y,
+ struct mdss_mdp_plane_sizes *ps, struct mdss_mdp_format_params *fmt)
+{
+ if ((x == 0) && (y == 0))
+ return;
+
+ data->p[0].addr += y * ps->ystride[0];
+
+ if (data->num_planes == 1) {
+ data->p[0].addr += x * fmt->bpp;
+ } else {
+ u8 hmap[] = { 1, 2, 1, 2 };
+ u8 vmap[] = { 1, 1, 2, 2 };
+ u16 xoff = x / hmap[fmt->chroma_sample];
+ u16 yoff = y / vmap[fmt->chroma_sample];
+
+ data->p[0].addr += x;
+ data->p[1].addr += xoff + (yoff * ps->ystride[1]);
+ if (data->num_planes == 2) /* pseudo planar */
+ data->p[1].addr += xoff;
+ else /* planar */
+ data->p[2].addr += xoff + (yoff * ps->ystride[2]);
+ }
+}
+
int mdss_mdp_put_img(struct mdss_mdp_img_data *data)
{
struct ion_client *iclient = mdss_get_ionclient();
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 37a12fb..3a9b1b9 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -150,6 +150,17 @@
#define WCD9XXX_CH(xport, xshift) \
{.port = xport, .shift = xshift}
+struct wcd9xxx_codec_type {
+ u16 id_major;
+ u16 id_minor;
+ struct mfd_cell *dev;
+ int size;
+ int num_irqs;
+ int version; /* -1 to retrive version from chip version register */
+ enum wcd9xxx_slim_slave_addr_type slim_slave_type;
+ u16 i2c_chip_status;
+};
+
struct wcd9xxx {
struct device *dev;
struct slim_device *slim;
@@ -181,14 +192,14 @@
struct pm_qos_request pm_qos_req;
int wlock_holders;
- u8 idbyte[4];
+ u16 id_minor;
+ u16 id_major;
unsigned int irq_base;
unsigned int irq;
u8 irq_masks_cur[WCD9XXX_NUM_IRQ_REGS];
u8 irq_masks_cache[WCD9XXX_NUM_IRQ_REGS];
bool irq_level_high[WCD9XXX_MAX_NUM_IRQS];
- int num_irqs;
/* Slimbus or I2S port */
u32 num_rx_port;
u32 num_tx_port;
@@ -196,7 +207,7 @@
struct wcd9xxx_ch *tx_chs;
u32 mclk_rate;
- enum wcd9xxx_slim_slave_addr_type slim_slave_type;
+ const struct wcd9xxx_codec_type *codec_type;
};
int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg);
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 813cac3..c6e4ab3 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -136,7 +136,7 @@
unsigned int hph_ocp_limit:3; /* Headphone OCP current limit */
};
-#define MAX_REGULATOR 7
+#define WCD9XXX_MAX_REGULATOR 8
/*
* format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
*
@@ -151,11 +151,14 @@
#define WCD9XXX_VDDD_CDC_D_CUR_MAX 5000
#define WCD9XXX_VDDD_CDC_A_CUR_MAX 5000
+#define WCD9XXX_VDD_SPKDRV_NAME "cdc-vdd-spkdrv"
+
struct wcd9xxx_regulator {
const char *name;
int min_uV;
int max_uV;
int optimum_uA;
+ bool ondemand;
struct regulator *regulator;
};
@@ -168,7 +171,7 @@
struct slim_device slimbus_slave_device;
struct wcd9xxx_micbias_setting micbias;
struct wcd9xxx_ocp_setting ocp;
- struct wcd9xxx_regulator regulator[MAX_REGULATOR];
+ struct wcd9xxx_regulator regulator[WCD9XXX_MAX_REGULATOR];
u32 mclk_rate;
u32 dmic_sample_rate;
};
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 60567fa..b9d4a6f 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -296,7 +296,7 @@
#define MDSS_PP_ARG_MASK 0x3C00
#define MDSS_PP_ARG_NUM 4
-#define MDSS_PP_ARG_SHIFT 8
+#define MDSS_PP_ARG_SHIFT 10
#define MDSS_PP_LOCATION_MASK 0x0300
#define MDSS_PP_LOGICAL_MASK 0x00FF
@@ -332,6 +332,7 @@
#define MDP_OVERLAY_PP_IGC_CFG 0x8
#define MDP_OVERLAY_PP_SHARP_CFG 0x10
#define MDP_OVERLAY_PP_HIST_CFG 0x20
+#define MDP_OVERLAY_PP_HIST_LUT_CFG 0x40
#define MDP_CSC_FLAG_ENABLE 0x1
#define MDP_CSC_FLAG_YUV_IN 0x2
@@ -375,6 +376,13 @@
uint16_t num_bins;
};
+struct mdp_hist_lut_data {
+ uint32_t block;
+ uint32_t ops;
+ uint32_t len;
+ uint32_t *data;
+};
+
struct mdp_overlay_pp_params {
uint32_t config_ops;
struct mdp_csc_cfg csc_cfg;
@@ -383,6 +391,7 @@
struct mdp_igc_lut_data igc_cfg;
struct mdp_sharp_cfg sharp_cfg;
struct mdp_histogram_cfg hist_cfg;
+ struct mdp_hist_lut_data hist_lut_cfg;
};
struct mdp_overlay {
@@ -517,13 +526,6 @@
};
-struct mdp_hist_lut_data {
- uint32_t block;
- uint32_t ops;
- uint32_t len;
- uint32_t *data;
-};
-
struct mdp_lut_cfg_data {
uint32_t lut_type;
union {
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index c399b81..294c881 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -138,6 +138,25 @@
enum qseecom_key_management_usage_type usage;
};
+#define SHA256_DIGEST_LENGTH (256/8)
+/*
+ * struct qseecom_save_partition_hash_req
+ * @partition_id - partition id.
+ * @hash[SHA256_DIGEST_LENGTH] - sha256 digest.
+ */
+struct qseecom_save_partition_hash_req {
+ int partition_id; /* in */
+ char digest[SHA256_DIGEST_LENGTH]; /* in */
+};
+
+/*
+ * struct qseecom_is_es_activated_req
+ * @is_activated - 1=true , 0=false
+ */
+struct qseecom_is_es_activated_req {
+ int is_activated; /* out */
+};
+
#define QSEECOM_IOC_MAGIC 0x97
@@ -195,5 +214,10 @@
#define QSEECOM_IOCTL_WIPE_KEY_REQ \
_IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req)
+#define QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 19, struct qseecom_save_partition_hash_req)
+
+#define QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 20, struct qseecom_is_es_activated_req)
#endif /* __QSEECOM_H_ */
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index cc1e8eb..fef7100 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -24,6 +24,7 @@
#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
#include <linux/mfd/wcd9xxx/wcd9320_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>
@@ -394,6 +395,7 @@
u8 aux_r_gain;
bool spkr_pa_widget_on;
+ struct regulator *spkdrv_reg;
struct afe_param_cdc_slimbus_slave_cfg slimbus_slave_cfg;
@@ -404,7 +406,6 @@
/* class h specific data */
struct wcd9xxx_clsh_cdc_data clsh_d;
-
};
static const u32 comp_shift[] = {
@@ -1082,13 +1083,6 @@
40, digital_gain),
SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
40, digital_gain),
- SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
- SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
-
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
taiko_put_anc_slot),
@@ -2707,10 +2701,20 @@
int ret = 0;
struct snd_soc_codec *codec = w->codec;
struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+ struct taiko_priv *priv = snd_soc_codec_get_drvdata(codec);
pr_debug("%s: %d %s\n", __func__, event, w->name);
+
+ WARN_ONCE(!priv->spkdrv_reg, "SPKDRV supply %s isn't defined\n",
+ WCD9XXX_VDD_SPKDRV_NAME);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if (priv->spkdrv_reg) {
+ ret = regulator_enable(priv->spkdrv_reg);
+ if (ret)
+ pr_err("%s: Failed to enable spkdrv_reg %s\n",
+ __func__, WCD9XXX_VDD_SPKDRV_NAME);
+ }
if (spkr_drv_wrnd > 0) {
WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
0x80));
@@ -2731,6 +2735,12 @@
snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
0x80);
}
+ if (priv->spkdrv_reg) {
+ ret = regulator_disable(priv->spkdrv_reg);
+ if (ret)
+ pr_err("%s: Failed to disable spkdrv_reg %s\n",
+ __func__, WCD9XXX_VDD_SPKDRV_NAME);
+ }
break;
}
@@ -5378,7 +5388,8 @@
}
for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
- if (!strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
+ if (pdata->regulator[i].name &&
+ !strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
if (pdata->regulator[i].min_uV == 1800000 &&
pdata->regulator[i].max_uV == 1800000) {
snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
@@ -5945,6 +5956,21 @@
SND_SOC_DAPM_POST_PMU),
};
+static struct regulator *taiko_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 int taiko_codec_probe(struct snd_soc_codec *codec)
{
struct wcd9xxx *control;
@@ -6023,6 +6049,9 @@
goto err_pdata;
}
+ taiko->spkdrv_reg = taiko_codec_find_regulator(codec,
+ WCD9XXX_VDD_SPKDRV_NAME);
+
if (spkr_drv_wrnd > 0) {
WCD9XXX_BCL_LOCK(&taiko->resmgr);
wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
@@ -6127,6 +6156,8 @@
/* cleanup resmgr */
wcd9xxx_resmgr_deinit(&taiko->resmgr);
+ taiko->spkdrv_reg = NULL;
+
kfree(taiko);
return 0;
}
diff --git a/sound/soc/msm/mdm9625.c b/sound/soc/msm/mdm9625.c
index 2bef1b7..f3ccb33 100644
--- a/sound/soc/msm/mdm9625.c
+++ b/sound/soc/msm/mdm9625.c
@@ -761,6 +761,21 @@
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
},
{
+ .name = "MDM9625 Media2",
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {
.name = "MSM VoIP",
.stream_name = "VoIP",
.cpu_dai_name = "VoIP",
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index e79a0cf..63af271 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -947,7 +947,7 @@
int i;
i = port_id - SLIMBUS_0_RX;
- if (i < 0 || i > ARRAY_SIZE(afe_ports_mad_type)) {
+ if (i < 0 || i >= ARRAY_SIZE(afe_ports_mad_type)) {
pr_debug("%s: Non Slimbus port_id 0x%x\n", __func__, port_id);
return MAD_HW_NONE;
}