summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-10-14 13:24:16 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-10-14 13:24:17 -0600
commitb54fb1cc4df7349076c2456b0bc6f1c8bea4e17d (patch)
tree9be499b25c07d603dbf1c85766676bad68afea39
parent2bddc21c9c64e791fb2dffe60bb7b9e2857da0b3 (diff)
parente657410985b5d33b0b4e76f08587345e9fb195ce (diff)
Promotion of kernel.lnx.4.4-161014.1.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1073291 I7aa23eabdf963146ae628eb159eee13a3e2bb935 msm: ipa3: fix benign prints on ipa3_usb_init 1071271 I35d8cbbd5914f82bef80c8f3d874fedb0b7c74c0 fbdev: use unsigned integers to prevent overflow 1075219 Icc9536f17eedc3559c9f70dc2a8b73127c78c98a qpnp-fg-gen3: Add support to hold soc at 100 when charge 1076216 Id9a3487c8469fe7921148ac8c8cc16afa66593d5 ARM: dts: msm: Fix clock for 720p@240fps usecase 1067981 Ib91bae1c6605e8727081c7acb248192ecf1b170a soc: qcom: qsee_ipc_irq_bridge: Fix null pointer derefer 1075319 I618cc3603df6af18409613209e0373d7e36202fd icnss: Remove msm_bus bandwidth vote 1048291 I9ee694d56dac11c315b45c8fc1e8be9426d06719 usb: pd: Fix PR_SWAP handling 1075481 Ia6b28a3b35a4093aea7af1cffea2a5e093d33ccd soc: qcom: glink: Fix ctx initialization with magic numb 1075659 Ib8211a85543b659b7b19a6ebb85382dbbbecfec6 ASoC: codecs: Add teardown() call in shutdown 1074292 I51af3d4f0e5dd1c9df6375cce4bb933f67f1022e sched/cgroup: Fix/cleanup cgroup teardown/init 1074292 Ice7cbd71d9e545da84d61686aa46c7213607bb9d sched/cgroup: Fix cgroup entity load tracking tear-down 1077644 Icebf88641a5ebb82bb4b7577d1ab402580b1460c iommu/io-pgtable-arm: Use outer shareable for all config 1046094 Iee74c206b28fea9b75df2d234609a7939bc3d93c usb: pd: Improve sink hard reset handling 1066768 I71d520a5a800a3e612dc4d57e7baffa93fad61b3 usb: gadget: f_midi: Use 1024 bytes as MIDI buffer size 1077133 I2ae0fe35e9a207b33f88077ca6ec49d593d43b68 ASoC: wcd934x-dsp-cntl: Make sure memories can enter dee 1075447 Iebc3767e9dbcf10a541b8b02f8696da84312447a input: pat9125: add support of sending rotating switch e 1076632 I9916354c04e24708aced5fc63bc12ddfe87b49f2 ASoC: wcd934x-dsp-cntl: add support for codec restart 1075220 I0a76e9e2f74c40b55e01f9dc106d31a148edefdf qpnp-fg-gen3: add support to configure ki coefficients d 1067981 I7cad7a724666f34bce73d40e4975373604fb1e87 soc: qcom: glink: Fix uninitialzed return value 1063047 I3ea14c8c76c4496eeeb11caf63c3ee62f031b157 leds: qpnp-flash-v2: Add support for configuring hardwar 1021026 Id829f07123963584f6c7fe0174e34006d2697aa9 msm: vidc: Update plane count in get-format 1071809 1072166 1073136 I436ead23c93384961b38ca99b9312a40c50ad03a ASoC: msm: lock read/write when add/free audio ion memor 1077384 I24d3809450bf63cbc6b930575c310cee116910f7 soc: qcom: smem: Update CDSP processor ID 1066768 I969ae3a99f2987abeca51823fe346f383cb23b55 defconfig: Enable USB MIDI Function driver for msmcobalt 1075925 I587b39bc302449591cc0c71ff15b740374a8af4d ARM: dts: msm: Add support for Lpass PIL on msmfalcon 1076097 Ifb8ff50d0eab96eca6f9ca45beb6d1dff9cd3292 msm: ipa: update wan pool size on napi enable Change-Id: I72b22a0088850e157ee5b0d3ddf64f10468c1db2 CRs-Fixed: 1066768, 1077644, 1077133, 1073291, 1076632, 1075219, 1075319, 1075447, 1071809, 1067981, 1075659, 1046094, 1021026, 1077384, 1071271, 1063047, 1072166, 1074292, 1076216, 1075481, 1076097, 1075220, 1073136, 1075925, 1048291
-rw-r--r--Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt21
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt4
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt39
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi15
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi32
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig1
-rw-r--r--drivers/input/misc/ots_pat9125/pat9125_linux_driver.c94
-rw-r--r--drivers/input/misc/ots_pat9125/pixart_ots.h3
-rw-r--r--drivers/iommu/io-pgtable-arm.c8
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c28
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c105
-rw-r--r--drivers/misc/qcom/qdsp6v2/audio_utils_aio.c20
-rw-r--r--drivers/platform/msm/ipa/ipa_api.c12
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/ipa_usb.c16
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c26
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c12
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c24
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c18
-rw-r--r--drivers/power/qcom-charger/fg-core.h19
-rw-r--r--drivers/power/qcom-charger/fg-util.c38
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c376
-rw-r--r--drivers/soc/qcom/glink.c4
-rw-r--r--drivers/soc/qcom/icnss.c69
-rw-r--r--drivers/soc/qcom/qsee_ipc_irq_bridge.c12
-rw-r--r--drivers/usb/gadget/function/f_midi.c2
-rw-r--r--drivers/usb/pd/policy_engine.c174
-rw-r--r--drivers/video/fbdev/core/fbcmap.c8
-rw-r--r--include/soc/qcom/smem.h2
-rw-r--r--kernel/sched/core.c39
-rw-r--r--kernel/sched/fair.c37
-rw-r--r--kernel/sched/sched.h2
-rw-r--r--sound/soc/codecs/msm_hdmi_codec_rx.c7
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c104
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h7
37 files changed, 1028 insertions, 379 deletions
diff --git a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
index 02f21835f870..1b68c695d2c5 100644
--- a/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
+++ b/Documentation/devicetree/bindings/input/pixart-pat9125-switch.txt
@@ -6,5 +6,24 @@ to the Host processor. The host processor reads the direction and number of
steps over I2C and passes the data to the rest of the system.
Required properties:
+ - compatible : should be "pixart,pat9125".
+ - reg : i2c slave address of the device.
+ - interrupt-parent : parent of interrupt.
+ - interrupts : interrupt to indicate motion of the rotating switch.
- - compatible : should be "pixart,pat9125".
+Optional properties:
+ - pixart,inverse-x : boolean, use this to invert the x data before sending it to input framework
+ - pixart,inverse-y : boolean, use this to invert the y data before sending it to input framework
+ - pixart,press-enabled : boolean, use this to enable detection of pressing the button
+
+Required properties if 'pixart,press-enabled' DT property is defined:
+ - pixart,press-keycode : keycode to be sent when press is detected by the driver.
+
+Example:
+ pixart_pat9125@75 {
+ compatible = "pixart,pat9125";
+ reg = <0x75>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <98 0x2008>;
+ pixart,irq-gpio = <&msm_gpio 98 0x2008>;
+ };
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index bd05c8bebfc8..f67fefbfcb0b 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -50,6 +50,10 @@ Optional properties:
Default value is 2.
- qcom,lmh-level : Optional property to configure flash current preemptive mitigation.
Accepted values are 0, 1, and 3. Default value is 0.
+- qcom,iled-thrsh-ma : Optional property to configure the led current threshold at which HW
+ preemptive mitigation is triggered. Unit is mA. Default value is 1000.
+ Accepted values are in the range 0 - 3100, with steps of 100.
+ 0 disables autonomous HW mitigation.
- qcom,thermal-derate-en : Boolean property to enable flash current thermal mitigation.
- qcom,thermal-derate-current : Array of currrent limits for thermal mitigation. Required if
qcom,thermal-derate-en is specified. Unit is mA. Format is
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
index 7841251c67fe..caabcd347a72 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
@@ -216,6 +216,42 @@ First Level Node - FG Gen3 device
Definition: Battery temperature delta interrupt threshold. Possible
values are: 2, 4, 6 and 10. Unit is in Kelvin.
+- qcom,hold-soc-while-full:
+ Usage: optional
+ Value type: <bool>
+ Definition: A boolean property that when defined holds SOC at 100% when
+ the battery is full.
+
+- qcom,ki-coeff-soc-dischg:
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Array of monotonic SOC threshold values to change the ki
+ coefficient for medium discharge current during discharge.
+ This should be defined in the ascending order and in the
+ range of 0-100. Array limit is set to 3.
+
+- qcom,ki-coeff-med-dischg:
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Array of ki coefficient values for medium discharge current
+ during discharge. These values will be applied when the
+ monotonic SOC goes below the SOC threshold specified under
+ qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
+ property should be specified if qcom,ki-coeff-soc-dischg
+ is specified to make it fully functional. Value has no
+ unit. Allowed range is 0 to 62200 in micro units.
+
+- qcom,ki-coeff-hi-dischg:
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Array of ki coefficient values for high discharge current
+ during discharge. These values will be applied when the
+ monotonic SOC goes below the SOC threshold specified under
+ qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
+ property should be specified if qcom,ki-coeff-soc-dischg
+ is specified to make it fully functional. Value has no
+ unit. Allowed range is 0 to 62200 in micro units.
+
==========================================================
Second Level Nodes - Peripherals managed by FG Gen3 driver
==========================================================
@@ -246,6 +282,9 @@ pmicobalt_fg: qpnp,fg {
qcom,pmic-revid = <&pmicobalt_revid>;
io-channels = <&pmicobalt_rradc 3>;
io-channel-names = "rradc_batt_id";
+ qcom,ki-coeff-soc-dischg = <30 60 90>;
+ qcom,ki-coeff-med-dischg = <800 1000 1400>;
+ qcom,ki-coeff-hi-dischg = <1200 1500 2100>;
status = "okay";
qcom,fg-batt-soc@4000 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index 9b791d6b7fb0..8016a3822a7f 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -669,11 +669,10 @@
qcom,load-freq-tbl =
/* Encoders */
<1105920 533000000 0x55555555>, /* 4kx2304@30 */ /*TURBO*/
- < 979200 444000000 0x55555555>, /* 1080p@120,1440p@60,
+ <1036800 444000000 0x55555555>, /* 720p@240, 1080p@120,1440p@60,
* UHD@30 */ /*NOMINAL*/
- < 939700 355200000 0x55555555>, /* 4kx2304@24 */ /*SVSL1*/
- < 489600 269330000 0x55555555>, /* 1080p@60, 2560x1440@30 */
- /* SVS */
+ < 829440 355200000 0x55555555>, /* UHD/4096x2160@30 SVSL1 */
+ < 489600 269330000 0x55555555>, /* 1080p@60 SVS */
< 432000 200000000 0x55555555>, /* 720p@120, 1080p@30 */
/* SVS2 */
@@ -685,7 +684,7 @@
<1675472 355200000 0xffffffff>, /* 4kx2304@44 */ /*SVSL1*/
<1105920 269330000 0xffffffff>, /* UHD/4k2304@30, 1080p@120 */
/* SVS */
- < 864000 200000000 0xffffffff>; /* 720p@240, 1080p@60 */
+ < 829440 200000000 0xffffffff>; /* 720p@120, 1080p@60 */
/* SVS2 */
qcom,imem-ab-tbl =
@@ -701,11 +700,11 @@
<1728000 1728000 2211840 0x3f00000c>,
/* Encoder */
/* Load > Nominal, Nominal <-> Turbo Eg. 4kx2304@30 */
- <972000 972000 1105920 0x04000004>,
+ <1036800 1036800 1105920 0x04000004>,
/* Load > SVSL1, SVSL1<-> Nominal Eg. 3840x2160@30 */
- <939700 939700 972000 0x04000004>,
+ < 829440 829440 1036800 0x04000004>,
/* Load > SVS , SVS <-> SVSL1 Eg. 4kx2304@24 */
- <489600 489600 939700 0x04000004>;
+ < 489600 489600 829440 0x04000004>;
qcom,dcvs-limit = /* Min Frame size, Min MBs/sec */
<32400 30>, /* Encoder 3840x2160@30 */
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 818b213f355d..26822da607de 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -2889,11 +2889,6 @@
vdd-3.3-ch0-supply = <&pmcobalt_l25_pin_ctrl>;
qcom,vdd-0.8-cx-mx-config = <800000 800000>;
qcom,vdd-3.3-ch0-config = <3104000 3312000>;
- qcom,msm-bus,name = "msm-icnss";
- qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,num-paths = <1>;
- qcom,msm-bus,vectors-KBps = <81 10065 0 0>,
- <81 10065 0 16000>;
qcom,icnss-vadc = <&pmcobalt_vadc>;
qcom,icnss-adc_tm = <&pmcobalt_adc_tm>;
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi
index bdbcd9d7b6f9..e5db2766c553 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-smp2p.dtsi
@@ -172,4 +172,27 @@
compatible = "qcom,smp2pgpio_test_smp2p_5_out";
gpios = <&smp2pgpio_smp2p_5_out 0 0>;
};
+
+ /* ssr - inbound entry from lpass */
+ smp2pgpio_ssr_smp2p_2_in: qcom,smp2pgpio-ssr-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ssr - outbound entry to lpass */
+ smp2pgpio_ssr_smp2p_2_out: qcom,smp2pgpio-ssr-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 9d80acd73ea4..2b2a201db8bc 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -670,6 +670,38 @@
<0 425 0>; /* CE11 */
qcom,wlan-msa-memory = <0x100000>;
};
+
+ qcom,lpass@15700000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0x15700000 0x00100>;
+ interrupts = <0 162 1>;
+
+ vdd_cx-supply = <&pmfalcon_s3b_level>;
+ qcom,proxy-reg-names = "vdd_cx";
+ qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+ clocks = <&clock_rpmcc CXO_PIL_LPASS_CLK>;
+ clock-names = "xo";
+ qcom,proxy-clock-names = "xo";
+
+ qcom,pas-id = <1>;
+ qcom,proxy-timeout-ms = <10000>;
+ qcom,smem-id = <423>;
+ qcom,sysmon-id = <1>;
+ qcom,ssctl-instance-id = <0x14>;
+ qcom,firmware-name = "adsp";
+ memory-region = <&adsp_fw_mem>;
+
+ /* GPIO inputs from lpass */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>;
+
+ /* GPIO output to lpass */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
+ status = "ok";
+ };
};
#include "msmfalcon-ion.dtsi"
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 098f9edcc0cf..799e43f09a11 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -437,6 +437,7 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_USB_CONFIGFS_F_GSI=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 3fc8dd7796a9..dfd658d815fe 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -439,6 +439,7 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_USB_CONFIGFS_F_GSI=y
diff --git a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
index e5edaf5f908d..fa44b7d866f8 100644
--- a/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
+++ b/drivers/input/misc/ots_pat9125/pat9125_linux_driver.c
@@ -11,6 +11,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of_gpio.h>
+#include <linux/delay.h>
#include "pixart_ots.h"
struct pixart_pat9125_data {
@@ -18,6 +19,10 @@ struct pixart_pat9125_data {
struct input_dev *input;
int irq_gpio;
u32 irq_flags;
+ u32 press_keycode;
+ bool press_en;
+ bool inverse_x;
+ bool inverse_y;
};
static int pat9125_i2c_write(struct i2c_client *client, u8 reg, u8 *data,
@@ -70,7 +75,7 @@ static int pat9125_i2c_read(struct i2c_client *client, u8 reg, u8 *data)
return ret;
}
-unsigned char read_data(struct i2c_client *client, u8 addr)
+u8 read_data(struct i2c_client *client, u8 addr)
{
u8 data = 0xff;
@@ -83,8 +88,55 @@ void write_data(struct i2c_client *client, u8 addr, u8 data)
pat9125_i2c_write(client, addr, &data, 1);
}
-static irqreturn_t pixart_pat9125_irq(int irq, void *data)
+static irqreturn_t pat9125_irq(int irq, void *dev_data)
{
+ u8 delta_x = 0, delta_y = 0, motion;
+ struct pixart_pat9125_data *data = dev_data;
+ struct input_dev *ipdev = data->input;
+ struct device *dev = &data->client->dev;
+
+ motion = read_data(data->client, PIXART_PAT9125_MOTION_STATUS_REG);
+ do {
+ /* check if MOTION bit is set or not */
+ if (motion & PIXART_PAT9125_VALID_MOTION_DATA) {
+ delta_x = read_data(data->client,
+ PIXART_PAT9125_DELTA_X_LO_REG);
+ delta_y = read_data(data->client,
+ PIXART_PAT9125_DELTA_Y_LO_REG);
+
+ /* Inverse x depending upon the device orientation */
+ delta_x = (data->inverse_x) ? -delta_x : delta_x;
+ /* Inverse y depending upon the device orientation */
+ delta_y = (data->inverse_y) ? -delta_y : delta_y;
+ }
+
+ dev_dbg(dev, "motion = %x, delta_x = %x, delta_y = %x\n",
+ motion, delta_x, delta_y);
+
+ if (delta_x != 0) {
+ /* Send delta_x as REL_WHEEL for rotation */
+ input_report_rel(ipdev, REL_WHEEL, (s8) delta_x);
+ input_sync(ipdev);
+ }
+
+ if (data->press_en && delta_y != 0) {
+ if ((s8) delta_y > 0) {
+ /* Send DOWN event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 1);
+ input_sync(ipdev);
+ } else {
+ /* Send UP event for press keycode */
+ input_report_key(ipdev, data->press_keycode, 0);
+ input_sync(ipdev);
+ }
+ }
+ usleep_range(PIXART_SAMPLING_PERIOD_US_MIN,
+ PIXART_SAMPLING_PERIOD_US_MAX);
+
+ motion = read_data(data->client,
+ PIXART_PAT9125_MOTION_STATUS_REG);
+ } while (motion & PIXART_PAT9125_VALID_MOTION_DATA);
+
return IRQ_HANDLED;
}
@@ -145,13 +197,36 @@ static struct attribute_group pat9125_attr_grp = {
.attrs = pat9125_attr_list,
};
+static int pat9125_parse_dt(struct device *dev,
+ struct pixart_pat9125_data *data)
+{
+ struct device_node *np = dev->of_node;
+ u32 temp_val;
+ int ret;
+
+ data->inverse_x = of_property_read_bool(np, "pixart,inverse-x");
+ data->inverse_y = of_property_read_bool(np, "pixart,inverse-y");
+ data->press_en = of_property_read_bool(np, "pixart,press-enabled");
+ if (data->press_en) {
+ ret = of_property_read_u32(np, "pixart,press-keycode",
+ &temp_val);
+ if (!ret) {
+ data->press_keycode = temp_val;
+ } else {
+ dev_err(dev, "Unable to parse press-keycode\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int pat9125_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err = 0;
struct pixart_pat9125_data *data;
struct input_dev *input;
- struct device_node *np;
struct device *dev = &client->dev;
err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
@@ -165,6 +240,11 @@ static int pat9125_i2c_probe(struct i2c_client *client,
GFP_KERNEL);
if (!data)
return -ENOMEM;
+ err = pat9125_parse_dt(dev, data);
+ if (err) {
+ dev_err(dev, "DT parsing failed, errno:%d\n", err);
+ return err;
+ }
} else {
data = client->dev.platform_data;
if (!data) {
@@ -180,6 +260,10 @@ static int pat9125_i2c_probe(struct i2c_client *client,
return -ENOMEM;
}
+ input_set_capability(input, EV_REL, REL_WHEEL);
+ if (data->press_en)
+ input_set_capability(input, EV_KEY, data->press_keycode);
+
i2c_set_clientdata(client, data);
input_set_drvdata(input, data);
input->name = PAT9125_DEV_NAME;
@@ -213,8 +297,8 @@ static int pat9125_i2c_probe(struct i2c_client *client,
goto err_sensor_init;
}
- err = devm_request_threaded_irq(dev, client->irq, NULL,
- pixart_pat9125_irq, (unsigned long)data->irq_flags,
+ err = devm_request_threaded_irq(dev, client->irq, NULL, pat9125_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW,
"pixart_pat9125_irq", data);
if (err) {
dev_err(dev, "Req irq %d failed, errno:%d\n", client->irq, err);
diff --git a/drivers/input/misc/ots_pat9125/pixart_ots.h b/drivers/input/misc/ots_pat9125/pixart_ots.h
index a66ded5c9d08..91813929d811 100644
--- a/drivers/input/misc/ots_pat9125/pixart_ots.h
+++ b/drivers/input/misc/ots_pat9125/pixart_ots.h
@@ -39,6 +39,9 @@
#define PIXART_PAT9125_LOW_VOLTAGE_SEGMENT 0x04
#define PIXART_PAT9125_VALID_MOTION_DATA 0x80
+#define PIXART_SAMPLING_PERIOD_US_MIN 4000
+#define PIXART_SAMPLING_PERIOD_US_MAX 8000
+
/* Export functions */
bool ots_sensor_init(struct i2c_client *);
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 5e47e2481300..3333f15f7f16 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -363,7 +363,7 @@ static int arm_lpae_init_pte(struct arm_lpae_io_pgtable *data,
else
pte |= ARM_LPAE_PTE_TYPE_BLOCK;
- pte |= ARM_LPAE_PTE_AF | ARM_LPAE_PTE_SH_IS;
+ pte |= ARM_LPAE_PTE_AF | ARM_LPAE_PTE_SH_OS;
pte |= pfn_to_iopte(paddr >> data->pg_shift, data);
*ptep = pte;
@@ -481,11 +481,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
pte |= (prot & IOMMU_PRIV) ? ARM_LPAE_PTE_AP_PRIV_RO
: ARM_LPAE_PTE_AP_RO;
- if (prot & IOMMU_CACHE) {
+ if (prot & IOMMU_CACHE)
pte |= (ARM_LPAE_MAIR_ATTR_IDX_CACHE
<< ARM_LPAE_PTE_ATTRINDX_SHIFT);
- pte |= ARM_LPAE_PTE_SH_OS;
- }
if (prot & IOMMU_DEVICE)
pte |= (ARM_LPAE_MAIR_ATTR_IDX_DEV <<
@@ -942,7 +940,7 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
(ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_IRGN0_SHIFT) |
(ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
else
- reg = (ARM_LPAE_TCR_SH_IS << ARM_LPAE_TCR_SH0_SHIFT) |
+ reg = (ARM_LPAE_TCR_SH_OS << ARM_LPAE_TCR_SH0_SHIFT) |
(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_IRGN0_SHIFT) |
(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_ORGN0_SHIFT);
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 0cae5d2e5263..164dac4c7c2f 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -48,6 +48,7 @@
#define FLASH_LED_REG_THERMAL_THRSH3(base) (base + 0x58)
#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
+#define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67)
#define FLASH_LED_REG_MITIGATION_SEL(base) (base + 0x6E)
#define FLASH_LED_REG_MITIGATION_SW(base) (base + 0x6F)
#define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70)
@@ -63,6 +64,7 @@
#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
#define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0)
#define FLASH_LED_LMH_MITIGATION_SEL_MASK GENMASK(1, 0)
+#define FLASH_LED_ILED_GRT_THRSH_MASK GENMASK(5, 0)
#define FLASH_LED_LMH_LEVEL_MASK GENMASK(1, 0)
#define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4)
#define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0)
@@ -78,6 +80,7 @@
#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
#define VPH_DROOP_THRESH_MV_TO_VAL(val_mv) ((val_mv / 100) - 25)
#define VPH_DROOP_THRESH_VAL_TO_UV(val) ((val + 25) * 100000)
+#define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100)
#define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6
#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
@@ -101,6 +104,8 @@
#define FLASH_LED_LMH_MITIGATION_DISABLE 0
#define FLASH_LED_LMH_MITIGATION_SEL_DEFAULT 2
#define FLASH_LED_LMH_MITIGATION_SEL_MAX 2
+#define FLASH_LED_MITIGATION_THRSH_DEFAULT 0xA
+#define FLASH_LED_MITIGATION_THRSH_MAX 0x1F
#define FLASH_LED_LMH_OCV_THRESH_DEFAULT_UV 3700000
#define FLASH_LED_LMH_RBATT_THRESH_DEFAULT_UOHM 400000
#define FLASH_LED_IRES_BASE 3
@@ -200,6 +205,7 @@ struct flash_led_platform_data {
u8 vph_droop_debounce;
u8 lmh_mitigation_sel;
u8 lmh_level;
+ u8 iled_thrsh_val;
u8 hw_strobe_option;
bool hdrm_auto_mode_en;
bool thermal_derate_en;
@@ -358,6 +364,13 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
if (rc < 0)
return rc;
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_ILED_GRT_THRSH(led->base),
+ FLASH_LED_ILED_GRT_THRSH_MASK,
+ led->pdata->iled_thrsh_val);
+ if (rc < 0)
+ return rc;
+
return 0;
}
@@ -1664,6 +1677,21 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
return -EINVAL;
}
+ led->pdata->iled_thrsh_val = FLASH_LED_MITIGATION_THRSH_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,iled-thrsh-ma", &val);
+ if (!rc) {
+ led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
+ } else if (rc != -EINVAL) {
+ dev_err(&led->pdev->dev, "Unable to parse iled_thrsh_val, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ if (led->pdata->iled_thrsh_val > FLASH_LED_MITIGATION_THRSH_MAX) {
+ dev_err(&led->pdev->dev, "Invalid iled_thrsh_val specified\n");
+ return -EINVAL;
+ }
+
led->pdata->all_ramp_up_done_irq =
of_irq_get_byname(node, "all-ramp-up-done-irq");
if (led->pdata->all_ramp_up_done_irq < 0)
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index 9c855e89e3ff..f071aae3ccab 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1400,6 +1400,49 @@ static struct msm_vidc_format venc_formats[] = {
},
};
+static void msm_venc_update_plane_count(struct msm_vidc_inst *inst, int type)
+{
+ struct v4l2_ctrl *ctrl = NULL;
+ u32 extradata = 0;
+
+ if (!inst)
+ return;
+
+ inst->fmts[type].num_planes = 1;
+
+ ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
+ V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
+
+ if (ctrl)
+ extradata = v4l2_ctrl_g_ctrl(ctrl);
+
+ if (type == CAPTURE_PORT) {
+ switch (extradata) {
+ case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
+ case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
+ case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
+ case V4L2_MPEG_VIDC_EXTRADATA_LTR:
+ case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
+ inst->fmts[CAPTURE_PORT].num_planes = 2;
+ default:
+ break;
+ }
+ } else if (type == OUTPUT_PORT) {
+ switch (extradata) {
+ case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
+ case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
+ case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
+ case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS:
+ case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP:
+ case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
+ inst->fmts[OUTPUT_PORT].num_planes = 2;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
static int msm_venc_set_csc(struct msm_vidc_inst *inst);
static int msm_venc_queue_setup(struct vb2_queue *q,
@@ -1414,8 +1457,7 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
enum hal_property property_id;
struct hfi_device *hdev;
struct hal_buffer_requirements *buff_req;
- struct v4l2_ctrl *ctrl = NULL;
- u32 extradata = 0, extra_idx = 0;
+ u32 extra_idx = 0;
struct hal_buffer_requirements *buff_req_buffer = NULL;
if (!q || !q->drv_priv) {
@@ -1471,21 +1513,8 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
temp, *num_buffers);
}
- ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
- V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
- if (ctrl)
- extradata = v4l2_ctrl_g_ctrl(ctrl);
- switch (extradata) {
- case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO:
- case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB:
- case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER:
- case V4L2_MPEG_VIDC_EXTRADATA_LTR:
- case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
- *num_planes = *num_planes + 1;
- default:
- break;
- }
- inst->fmts[CAPTURE_PORT].num_planes = *num_planes;
+ msm_venc_update_plane_count(inst, CAPTURE_PORT);
+ *num_planes = inst->fmts[CAPTURE_PORT].num_planes;
for (i = 0; i < *num_planes; i++) {
int extra_idx = EXTRADATA_IDX(*num_planes);
@@ -1543,24 +1572,9 @@ static int msm_venc_queue_setup(struct vb2_queue *q,
dprintk(VIDC_DBG, "actual input buffer count set to fw = %d\n",
*num_buffers);
- ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
- V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
- if (ctrl)
- extradata = v4l2_ctrl_g_ctrl(ctrl);
- switch (extradata) {
- case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP:
- case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM:
- case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO:
- case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS:
- case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP:
- case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO:
- *num_planes = *num_planes + 1;
- break;
- default:
- break;
- }
+ msm_venc_update_plane_count(inst, OUTPUT_PORT);
+ *num_planes = inst->fmts[OUTPUT_PORT].num_planes;
- inst->fmts[OUTPUT_PORT].num_planes = *num_planes;
rc = call_hfi_op(hdev, session_set_property, inst->session,
property_id, &new_buf_count);
if (rc)
@@ -3629,6 +3643,9 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
memcpy(&inst->fmts[fmt->type], fmt,
sizeof(struct msm_vidc_format));
+ msm_venc_update_plane_count(inst, CAPTURE_PORT);
+ fmt->num_planes = inst->fmts[CAPTURE_PORT].num_planes;
+
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
dprintk(VIDC_ERR, "Failed to open instance\n");
@@ -3682,6 +3699,9 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
memcpy(&inst->fmts[fmt->type], fmt,
sizeof(struct msm_vidc_format));
+ msm_venc_update_plane_count(inst, OUTPUT_PORT);
+ fmt->num_planes = inst->fmts[OUTPUT_PORT].num_planes;
+
msm_comm_set_color_format(inst, HAL_BUFFER_INPUT, fmt->fourcc);
} else {
dprintk(VIDC_ERR, "%s - Unsupported buf type: %d\n",
@@ -3690,7 +3710,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
goto exit;
}
- f->fmt.pix_mp.num_planes = inst->fmts[fmt->type].num_planes;
+ f->fmt.pix_mp.num_planes = fmt->num_planes;
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
struct hal_frame_size frame_sz = {0};
@@ -3743,7 +3763,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
const struct msm_vidc_format *fmt = NULL;
int rc = 0;
int i;
- u32 height, width;
+ u32 height, width, num_planes;
unsigned int extra_idx = 0;
struct hal_buffer_requirements *bufreq = NULL;
@@ -3764,10 +3784,14 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
fmt = &inst->fmts[CAPTURE_PORT];
height = inst->prop.height[CAPTURE_PORT];
width = inst->prop.width[CAPTURE_PORT];
+ msm_venc_update_plane_count(inst, CAPTURE_PORT);
+ num_planes = inst->fmts[CAPTURE_PORT].num_planes;
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
fmt = &inst->fmts[OUTPUT_PORT];
height = inst->prop.height[OUTPUT_PORT];
width = inst->prop.width[OUTPUT_PORT];
+ msm_venc_update_plane_count(inst, OUTPUT_PORT);
+ num_planes = inst->fmts[OUTPUT_PORT].num_planes;
} else {
dprintk(VIDC_ERR, "Invalid type: %x\n", f->type);
return -ENOTSUPP;
@@ -3776,10 +3800,10 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
f->fmt.pix_mp.pixelformat = fmt->fourcc;
f->fmt.pix_mp.height = height;
f->fmt.pix_mp.width = width;
- f->fmt.pix_mp.num_planes = fmt->num_planes;
+ f->fmt.pix_mp.num_planes = num_planes;
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- for (i = 0; i < fmt->num_planes; ++i) {
+ for (i = 0; i < num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
fmt->get_frame_size(i, height, width);
}
@@ -3790,7 +3814,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
f->fmt.pix_mp.plane_fmt[0].sizeimage =
bufreq ? bufreq->buffer_size : 0;
}
- extra_idx = EXTRADATA_IDX(fmt->num_planes);
+ extra_idx = EXTRADATA_IDX(num_planes);
if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
bufreq = get_buff_req_buffer(inst,
@@ -3803,7 +3827,7 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
bufreq ? bufreq->buffer_size : 0;
}
- for (i = 0; i < fmt->num_planes; ++i) {
+ for (i = 0; i < num_planes; ++i) {
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i] =
f->fmt.pix_mp.plane_fmt[i].sizeimage;
@@ -4057,4 +4081,3 @@ int msm_venc_ctrl_init(struct msm_vidc_inst *inst)
return msm_comm_ctrl_init(inst, msm_venc_ctrls,
ARRAY_SIZE(msm_venc_ctrls), &msm_venc_ctrl_ops);
}
-
diff --git a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
index 0c44f79549d4..567c948b0efe 100644
--- a/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
+++ b/drivers/misc/qcom/qdsp6v2/audio_utils_aio.c
@@ -570,6 +570,8 @@ int audio_aio_release(struct inode *inode, struct file *file)
struct q6audio_aio *audio = file->private_data;
pr_debug("%s[%p]\n", __func__, audio);
mutex_lock(&audio->lock);
+ mutex_lock(&audio->read_lock);
+ mutex_lock(&audio->write_lock);
audio->wflush = 1;
if (audio->wakelock_voted &&
(audio->audio_ws_mgr != NULL) &&
@@ -595,6 +597,8 @@ int audio_aio_release(struct inode *inode, struct file *file)
wake_up(&audio->event_wait);
audio_aio_reset_event_queue(audio);
q6asm_audio_client_free(audio->ac);
+ mutex_unlock(&audio->write_lock);
+ mutex_unlock(&audio->read_lock);
mutex_unlock(&audio->lock);
mutex_destroy(&audio->lock);
mutex_destroy(&audio->read_lock);
@@ -1745,7 +1749,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd,
__func__);
rc = -EFAULT;
} else {
+ mutex_lock(&audio->read_lock);
+ mutex_lock(&audio->write_lock);
rc = audio_aio_ion_add(audio, &info);
+ mutex_unlock(&audio->write_lock);
+ mutex_unlock(&audio->read_lock);
}
mutex_unlock(&audio->lock);
break;
@@ -1760,7 +1768,11 @@ static long audio_aio_ioctl(struct file *file, unsigned int cmd,
__func__);
rc = -EFAULT;
} else {
+ mutex_lock(&audio->read_lock);
+ mutex_lock(&audio->write_lock);
rc = audio_aio_ion_remove(audio, &info);
+ mutex_unlock(&audio->write_lock);
+ mutex_unlock(&audio->read_lock);
}
mutex_unlock(&audio->lock);
break;
@@ -2064,7 +2076,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd,
} else {
info.fd = info_32.fd;
info.vaddr = compat_ptr(info_32.vaddr);
+ mutex_lock(&audio->read_lock);
+ mutex_lock(&audio->write_lock);
rc = audio_aio_ion_add(audio, &info);
+ mutex_unlock(&audio->write_lock);
+ mutex_unlock(&audio->read_lock);
}
mutex_unlock(&audio->lock);
break;
@@ -2081,7 +2097,11 @@ static long audio_aio_compat_ioctl(struct file *file, unsigned int cmd,
} else {
info.fd = info_32.fd;
info.vaddr = compat_ptr(info_32.vaddr);
+ mutex_lock(&audio->read_lock);
+ mutex_lock(&audio->write_lock);
rc = audio_aio_ion_remove(audio, &info);
+ mutex_unlock(&audio->write_lock);
+ mutex_unlock(&audio->read_lock);
}
mutex_unlock(&audio->lock);
break;
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 05ce3969a5c7..75b193def36e 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -26,7 +26,8 @@
#define IPA_API_DISPATCH_RETURN(api, p...) \
do { \
if (!ipa_api_ctrl) { \
- pr_err("IPA HW is not supported on this target\n"); \
+ pr_err("%s:%d IPA HW is not supported\n", \
+ __func__, __LINE__); \
ret = -EPERM; \
} \
else { \
@@ -44,7 +45,8 @@
#define IPA_API_DISPATCH(api, p...) \
do { \
if (!ipa_api_ctrl) \
- pr_err("IPA HW is not supported on this target\n"); \
+ pr_err("%s:%d IPA HW is not supported\n", \
+ __func__, __LINE__); \
else { \
if (ipa_api_ctrl->api) { \
ipa_api_ctrl->api(p); \
@@ -59,7 +61,8 @@
#define IPA_API_DISPATCH_RETURN_PTR(api, p...) \
do { \
if (!ipa_api_ctrl) { \
- pr_err("IPA HW is not supported on this target\n"); \
+ pr_err("%s:%d IPA HW is not supported\n", \
+ __func__, __LINE__); \
ret = NULL; \
} \
else { \
@@ -77,7 +80,8 @@
#define IPA_API_DISPATCH_RETURN_BOOL(api, p...) \
do { \
if (!ipa_api_ctrl) { \
- pr_err("IPA HW is not supported on this target\n"); \
+ pr_err("%s:%d IPA HW is not supported\n", \
+ __func__, __LINE__); \
ret = false; \
} \
else { \
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index 838b78c1934d..d18308344431 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -2034,7 +2034,7 @@ static void ipa_usb_debugfs_init(void)
ipa3_usb_ctx->dent = debugfs_create_dir("ipa_usb", 0);
if (IS_ERR(ipa3_usb_ctx->dent)) {
- IPA_USB_ERR("fail to create folder in debug_fs.\n");
+ pr_err("fail to create folder in debug_fs.\n");
return;
}
@@ -2043,7 +2043,7 @@ static void ipa_usb_debugfs_init(void)
&ipa3_ipa_usb_ops);
if (!ipa3_usb_ctx->dfile_state_info ||
IS_ERR(ipa3_usb_ctx->dfile_state_info)) {
- IPA_USB_ERR("failed to create file for state_info\n");
+ pr_err("failed to create file for state_info\n");
goto fail;
}
@@ -2644,11 +2644,11 @@ static int __init ipa3_usb_init(void)
unsigned long flags;
int res;
- IPA_USB_DBG("entry\n");
+ pr_debug("entry\n");
ipa3_usb_ctx = kzalloc(sizeof(struct ipa3_usb_context), GFP_KERNEL);
if (ipa3_usb_ctx == NULL) {
- IPA_USB_ERR("failed to allocate memory\n");
- IPA_USB_ERR(":ipa_usb init failed\n");
+ pr_err("failed to allocate memory\n");
+ pr_err(":ipa_usb init failed\n");
return -EFAULT;
}
memset(ipa3_usb_ctx, 0, sizeof(struct ipa3_usb_context));
@@ -2680,19 +2680,19 @@ static int __init ipa3_usb_init(void)
ipa3_usb_ctx->wq = create_singlethread_workqueue("ipa_usb_wq");
if (!ipa3_usb_ctx->wq) {
- IPA_USB_ERR("failed to create workqueue\n");
+ pr_err("failed to create workqueue\n");
res = -EFAULT;
goto ipa_usb_workqueue_fail;
}
ipa_usb_debugfs_init();
- IPA_USB_INFO("exit: IPA_USB init success!\n");
+ pr_info("exit: IPA_USB init success!\n");
return 0;
ipa_usb_workqueue_fail:
- IPA_USB_ERR(":init failed (%d)\n", -res);
+ pr_err(":init failed (%d)\n", -res);
kfree(ipa3_usb_ctx);
return res;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 16f50030b960..3c2a6d4620ba 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -3152,23 +3152,23 @@ static int ipa_assign_policy_v2(struct ipa_sys_connect_params *in,
} else if (in->client ==
IPA_CLIENT_APPS_WAN_CONS) {
sys->pyld_hdlr = ipa_wan_rx_pyld_hdlr;
- if (in->recycle_enabled) {
+ sys->rx_pool_sz = ipa_ctx->wan_rx_ring_size;
+ if (nr_cpu_ids > 1) {
sys->repl_hdlr =
- ipa_replenish_rx_cache_recycle;
- sys->rx_pool_sz =
- IPA_WAN_NAPI_CONS_RX_POOL_SZ;
+ ipa_fast_replenish_rx_cache;
+ sys->repl_trig_thresh =
+ sys->rx_pool_sz / 8;
} else {
- if (nr_cpu_ids > 1) {
- sys->repl_hdlr =
- ipa_fast_replenish_rx_cache;
- sys->repl_trig_thresh =
- sys->rx_pool_sz / 8;
- } else {
+ sys->repl_hdlr =
+ ipa_replenish_rx_cache;
+ }
+ if (in->napi_enabled) {
+ sys->rx_pool_sz =
+ IPA_WAN_NAPI_CONS_RX_POOL_SZ;
+ if (in->recycle_enabled) {
sys->repl_hdlr =
- ipa_replenish_rx_cache;
+ ipa_replenish_rx_cache_recycle;
}
- sys->rx_pool_sz =
- ipa_ctx->wan_rx_ring_size;
}
sys->ep->wakelock_client =
IPA_WAKELOCK_REF_CLIENT_WAN_RX;
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index ebb93e246048..96003d7a16a0 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -1259,11 +1259,13 @@ static int handle_ingress_format(struct net_device *dev,
ipa_to_apps_ep_cfg.ipa_ep_cfg.aggr.aggr_pkt_limit =
in->u.ingress_format.agg_count;
- ipa_to_apps_ep_cfg.recycle_enabled = true;
- ep_cfg = (struct rmnet_phys_ep_conf_s *)
- rcu_dereference(dev->rx_handler_data);
- ep_cfg->recycle = ipa_recycle_wan_skb;
- pr_info("Wan Recycle Enabled\n");
+ if (ipa_rmnet_res.ipa_napi_enable) {
+ ipa_to_apps_ep_cfg.recycle_enabled = true;
+ ep_cfg = (struct rmnet_phys_ep_conf_s *)
+ rcu_dereference(dev->rx_handler_data);
+ ep_cfg->recycle = ipa_recycle_wan_skb;
+ pr_info("Wan Recycle Enabled\n");
+ }
}
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 643e40402499..94e8bba1fe01 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -3180,22 +3180,20 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in,
IPA_CLIENT_APPS_WAN_CONS) {
sys->pyld_hdlr = ipa3_wan_rx_pyld_hdlr;
sys->free_rx_wrapper = ipa3_free_rx_wrapper;
- if (in->recycle_enabled) {
+ sys->rx_pool_sz = ipa3_ctx->wan_rx_ring_size;
+ if (nr_cpu_ids > 1) {
sys->repl_hdlr =
- ipa3_replenish_rx_cache_recycle;
- sys->rx_pool_sz =
- IPA_WAN_NAPI_CONS_RX_POOL_SZ;
+ ipa3_fast_replenish_rx_cache;
} else {
- if (nr_cpu_ids > 1) {
- sys->repl_hdlr =
- ipa3_fast_replenish_rx_cache;
- } else {
- sys->repl_hdlr =
- ipa3_replenish_rx_cache;
- }
- sys->rx_pool_sz =
- ipa3_ctx->wan_rx_ring_size;
+ sys->repl_hdlr =
+ ipa3_replenish_rx_cache;
}
+ if (in->napi_enabled)
+ sys->rx_pool_sz =
+ IPA_WAN_NAPI_CONS_RX_POOL_SZ;
+ if (in->napi_enabled && in->recycle_enabled)
+ sys->repl_hdlr =
+ ipa3_replenish_rx_cache_recycle;
in->ipa_ep_cfg.aggr.aggr_sw_eof_active
= true;
if (ipa3_ctx->
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index a2fef45cc55f..f134852e046e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1271,11 +1271,13 @@ static int handle3_ingress_format(struct net_device *dev,
ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit =
in->u.ingress_format.agg_count;
- ipa_wan_ep_cfg->recycle_enabled = true;
- ep_cfg = (struct rmnet_phys_ep_conf_s *)
- rcu_dereference(dev->rx_handler_data);
- ep_cfg->recycle = ipa_recycle_wan_skb;
- pr_info("Wan Recycle Enabled\n");
+ if (ipa_wan_ep_cfg->napi_enabled) {
+ ipa_wan_ep_cfg->recycle_enabled = true;
+ ep_cfg = (struct rmnet_phys_ep_conf_s *)
+ rcu_dereference(dev->rx_handler_data);
+ ep_cfg->recycle = ipa_recycle_wan_skb;
+ pr_info("Wan Recycle Enabled\n");
+ }
}
}
@@ -1969,9 +1971,9 @@ static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev,
ipa_rmnet_drv_res->ipa_advertise_sg_support ? "True" : "False");
ipa_rmnet_drv_res->ipa_napi_enable =
- of_property_read_bool(pdev->dev.of_node,
- "qcom,napi");
- pr_info("IPA napi = %s\n",
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,ipa-napi-enable");
+ pr_info("IPA Napi Enable = %s\n",
ipa_rmnet_drv_res->ipa_napi_enable ? "True" : "False");
return 0;
}
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index 7e08b71e3b6a..adc640c7afe1 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
@@ -38,6 +39,7 @@
pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
+/* Awake votable reasons */
#define SRAM_READ "fg_sram_read"
#define SRAM_WRITE "fg_sram_write"
#define PROFILE_LOAD "fg_profile_load"
@@ -59,6 +61,9 @@
#define BUCKET_COUNT 8
#define BUCKET_SOC_PCT (256 / BUCKET_COUNT)
+#define KI_COEFF_MAX 62200
+#define KI_COEFF_SOC_LEVELS 3
+
/* Debug flag definitions */
enum fg_debug_flag {
FG_IRQ = BIT(0), /* Show interrupts */
@@ -137,6 +142,8 @@ enum fg_sram_param_id {
FG_SRAM_CHG_TERM_CURR,
FG_SRAM_DELTA_SOC_THR,
FG_SRAM_RECHARGE_SOC_THR,
+ FG_SRAM_KI_COEFF_MED_DISCHG,
+ FG_SRAM_KI_COEFF_HI_DISCHG,
FG_SRAM_MAX,
};
@@ -173,6 +180,8 @@ struct fg_alg_flag {
/* DT parameters for FG device */
struct fg_dt_props {
+ bool force_load_profile;
+ bool hold_soc_while_full;
int cutoff_volt_mv;
int empty_volt_mv;
int vbatt_low_thr_mv;
@@ -185,7 +194,6 @@ struct fg_dt_props {
int esr_timer_charging;
int esr_timer_awake;
int esr_timer_asleep;
- bool force_load_profile;
int cl_start_soc;
int cl_max_temp;
int cl_min_temp;
@@ -195,6 +203,9 @@ struct fg_dt_props {
int cl_min_cap_limit;
int jeita_hyst_temp;
int batt_temp_delta;
+ int ki_coeff_soc[KI_COEFF_SOC_LEVELS];
+ int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
+ int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS];
};
/* parameters from battery profile */
@@ -240,6 +251,8 @@ struct fg_chip {
struct dentry *dfs_root;
struct power_supply *fg_psy;
struct power_supply *batt_psy;
+ struct power_supply *usb_psy;
+ struct power_supply *dc_psy;
struct iio_channel *batt_id_chan;
struct fg_memif *sram;
struct fg_irq_info *irqs;
@@ -268,6 +281,9 @@ struct fg_chip {
bool profile_loaded;
bool battery_missing;
bool fg_restarting;
+ bool charge_full;
+ bool recharge_soc_adjusted;
+ bool ki_coeff_dischg_en;
struct completion soc_update;
struct completion soc_ready;
struct delayed_work profile_load_work;
@@ -321,4 +337,5 @@ extern int fg_debugfs_create(struct fg_chip *chip);
extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len);
extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
extern s64 fg_float_decode(u16 val);
+extern bool is_input_present(struct fg_chip *chip);
#endif
diff --git a/drivers/power/qcom-charger/fg-util.c b/drivers/power/qcom-charger/fg-util.c
index 790e56bd3dae..bbdbe48896d7 100644
--- a/drivers/power/qcom-charger/fg-util.c
+++ b/drivers/power/qcom-charger/fg-util.c
@@ -29,6 +29,43 @@ static struct fg_dbgfs dbgfs_data = {
},
};
+static bool is_usb_present(struct fg_chip *chip)
+{
+ union power_supply_propval pval = {0, };
+
+ if (!chip->usb_psy)
+ chip->usb_psy = power_supply_get_by_name("usb");
+
+ if (chip->usb_psy)
+ power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ else
+ return false;
+
+ return pval.intval != 0;
+}
+
+static bool is_dc_present(struct fg_chip *chip)
+{
+ union power_supply_propval pval = {0, };
+
+ if (!chip->dc_psy)
+ chip->dc_psy = power_supply_get_by_name("dc");
+
+ if (chip->dc_psy)
+ power_supply_get_property(chip->dc_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ else
+ return false;
+
+ return pval.intval != 0;
+}
+
+bool is_input_present(struct fg_chip *chip)
+{
+ return is_usb_present(chip) || is_dc_present(chip);
+}
+
#define EXPONENT_SHIFT 11
#define EXPONENT_OFFSET -9
#define MANTISSA_SIGN_BIT 10
@@ -98,6 +135,7 @@ int fg_sram_write(struct fg_chip *chip, u16 address, u8 offset,
* This interrupt need to be enabled only when it is
* required. It will be kept disabled other times.
*/
+ reinit_completion(&chip->soc_update);
enable_irq(chip->irqs[SOC_UPDATE_IRQ].irq);
atomic_access = true;
} else {
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index f8c1ad5963af..30408218b7e7 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -17,7 +17,6 @@
#include <linux/of_platform.h>
#include <linux/of_batterydata.h>
#include <linux/platform_device.h>
-#include <linux/power_supply.h>
#include <linux/iio/consumer.h>
#include <linux/qpnp/qpnp-revid.h>
#include "fg-core.h"
@@ -37,6 +36,12 @@
#define SYS_TERM_CURR_OFFSET 0
#define VBATT_FULL_WORD 7
#define VBATT_FULL_OFFSET 0
+#define KI_COEFF_MED_DISCHG_WORD 9
+#define KI_COEFF_MED_DISCHG_OFFSET 3
+#define KI_COEFF_HI_DISCHG_WORD 10
+#define KI_COEFF_HI_DISCHG_OFFSET 0
+#define KI_COEFF_LOW_DISCHG_WORD 10
+#define KI_COEFF_LOW_DISCHG_OFFSET 2
#define DELTA_SOC_THR_WORD 12
#define DELTA_SOC_THR_OFFSET 3
#define RECHARGE_SOC_THR_WORD 14
@@ -65,6 +70,8 @@
#define PROFILE_INTEGRITY_OFFSET 3
#define BATT_SOC_WORD 91
#define BATT_SOC_OFFSET 0
+#define FULL_SOC_WORD 93
+#define FULL_SOC_OFFSET 2
#define MONOTONIC_SOC_WORD 94
#define MONOTONIC_SOC_OFFSET 2
#define CC_SOC_WORD 95
@@ -87,6 +94,12 @@
#define ALG_FLAGS_OFFSET 1
/* v2 SRAM address and offset in ascending order */
+#define KI_COEFF_LOW_DISCHG_v2_WORD 9
+#define KI_COEFF_LOW_DISCHG_v2_OFFSET 3
+#define KI_COEFF_MED_DISCHG_v2_WORD 10
+#define KI_COEFF_MED_DISCHG_v2_OFFSET 0
+#define KI_COEFF_HI_DISCHG_v2_WORD 10
+#define KI_COEFF_HI_DISCHG_v2_OFFSET 1
#define DELTA_SOC_THR_v2_WORD 13
#define DELTA_SOC_THR_v2_OFFSET 0
#define RECHARGE_SOC_THR_v2_WORD 14
@@ -106,8 +119,6 @@ static int fg_decode_value_16b(struct fg_sram_param *sp,
enum fg_sram_param_id id, int val);
static int fg_decode_default(struct fg_sram_param *sp,
enum fg_sram_param_id id, int val);
-static int fg_decode_batt_soc(struct fg_sram_param *sp,
- enum fg_sram_param_id id, int val);
static int fg_decode_cc_soc(struct fg_sram_param *sp,
enum fg_sram_param_id id, int value);
static void fg_encode_voltage(struct fg_sram_param *sp,
@@ -132,7 +143,7 @@ static void fg_encode_default(struct fg_sram_param *sp,
static struct fg_sram_param pmicobalt_v1_sram_params[] = {
PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
- fg_decode_batt_soc),
+ fg_decode_default),
PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
1000, 0, NULL, fg_decode_voltage_15b),
PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
@@ -174,11 +185,17 @@ static struct fg_sram_param pmicobalt_v1_sram_params[] = {
ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
+ PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_WORD,
+ KI_COEFF_MED_DISCHG_OFFSET, 1, 1000, 244141, 0,
+ fg_encode_default, NULL),
+ PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_WORD,
+ KI_COEFF_HI_DISCHG_OFFSET, 1, 1000, 244141, 0,
+ fg_encode_default, NULL),
};
static struct fg_sram_param pmicobalt_v2_sram_params[] = {
PARAM(BATT_SOC, BATT_SOC_WORD, BATT_SOC_OFFSET, 4, 1, 1, 0, NULL,
- fg_decode_batt_soc),
+ fg_decode_default),
PARAM(VOLTAGE_PRED, VOLTAGE_PRED_WORD, VOLTAGE_PRED_OFFSET, 2, 244141,
1000, 0, NULL, fg_decode_voltage_15b),
PARAM(OCV, OCV_WORD, OCV_OFFSET, 2, 244141, 1000, 0, NULL,
@@ -223,6 +240,12 @@ static struct fg_sram_param pmicobalt_v2_sram_params[] = {
ESR_TIMER_CHG_MAX_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
PARAM(ESR_TIMER_CHG_INIT, ESR_TIMER_CHG_INIT_WORD,
ESR_TIMER_CHG_INIT_OFFSET, 2, 1, 1, 0, fg_encode_default, NULL),
+ PARAM(KI_COEFF_MED_DISCHG, KI_COEFF_MED_DISCHG_v2_WORD,
+ KI_COEFF_MED_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
+ fg_encode_default, NULL),
+ PARAM(KI_COEFF_HI_DISCHG, KI_COEFF_HI_DISCHG_v2_WORD,
+ KI_COEFF_HI_DISCHG_v2_OFFSET, 1, 1000, 244141, 0,
+ fg_encode_default, NULL),
};
static struct fg_alg_flag pmicobalt_v1_alg_flags[] = {
@@ -335,19 +358,11 @@ static int fg_decode_value_16b(struct fg_sram_param *sp,
return sp[id].value;
}
-static int fg_decode_batt_soc(struct fg_sram_param *sp,
- enum fg_sram_param_id id, int value)
-{
- sp[id].value = (u32)value >> 24;
- pr_debug("id: %d raw value: %x decoded value: %x\n", id, value,
- sp[id].value);
- return sp[id].value;
-}
-
static int fg_decode_default(struct fg_sram_param *sp, enum fg_sram_param_id id,
int value)
{
- return value;
+ sp[id].value = value;
+ return sp[id].value;
}
static int fg_decode(struct fg_sram_param *sp, enum fg_sram_param_id id,
@@ -645,6 +660,11 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
{
int rc, msoc;
+ if (chip->charge_full) {
+ *val = FULL_CAPACITY;
+ return 0;
+ }
+
rc = fg_get_msoc_raw(chip, &msoc);
if (rc < 0)
return rc;
@@ -1059,7 +1079,7 @@ static int fg_cap_learning_done(struct fg_chip *chip)
cc_soc_sw = CC_SOC_30BIT;
rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
- chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_DEFAULT);
+ chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
if (rc < 0) {
pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
goto out;
@@ -1092,6 +1112,9 @@ static void fg_cap_learning_update(struct fg_chip *chip)
goto out;
}
+ /* We need only the most significant byte here */
+ batt_soc = (u32)batt_soc >> 24;
+
fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n",
chip->status, chip->cl.active, batt_soc);
@@ -1103,8 +1126,7 @@ static void fg_cap_learning_update(struct fg_chip *chip)
}
} else {
- if (chip->status == POWER_SUPPLY_STATUS_FULL &&
- chip->charge_done) {
+ if (chip->charge_done) {
rc = fg_cap_learning_done(chip);
if (rc < 0)
pr_err("Error in completing capacity learning, rc=%d\n",
@@ -1126,19 +1148,211 @@ out:
mutex_unlock(&chip->cl.lock);
}
+#define KI_COEFF_MED_DISCHG_DEFAULT 1500
+#define KI_COEFF_HI_DISCHG_DEFAULT 2200
+static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
+{
+ int rc, i, msoc;
+ int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
+ int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
+ u8 val;
+
+ if (!chip->ki_coeff_dischg_en)
+ return 0;
+
+ rc = fg_get_prop_capacity(chip, &msoc);
+ if (rc < 0) {
+ pr_err("Error in getting capacity, rc=%d\n", rc);
+ return rc;
+ }
+
+ if (chip->status == POWER_SUPPLY_STATUS_DISCHARGING) {
+ for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
+ if (msoc < chip->dt.ki_coeff_soc[i]) {
+ ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
+ ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
+ }
+ }
+ }
+
+ fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
+ rc = fg_sram_write(chip,
+ chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
+ chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_byte, &val,
+ chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].len,
+ FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing ki_coeff_med, rc=%d\n", rc);
+ return rc;
+ }
+
+ fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_DISCHG, ki_coeff_hi, &val);
+ rc = fg_sram_write(chip,
+ chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_word,
+ chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].addr_byte, &val,
+ chip->sp[FG_SRAM_KI_COEFF_HI_DISCHG].len,
+ FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing ki_coeff_hi, rc=%d\n", rc);
+ return rc;
+ }
+
+ fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
+ ki_coeff_med, ki_coeff_hi);
+ return 0;
+}
+
+static int fg_charge_full_update(struct fg_chip *chip)
+{
+ union power_supply_propval prop = {0, };
+ int rc, msoc, bsoc, recharge_soc;
+ u8 full_soc[2] = {0xFF, 0xFF};
+
+ if (!chip->dt.hold_soc_while_full)
+ return 0;
+
+ if (!is_charger_available(chip))
+ return 0;
+
+ rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH,
+ &prop);
+ if (rc < 0) {
+ pr_err("Error in getting battery health, rc=%d\n", rc);
+ return rc;
+ }
+
+ chip->health = prop.intval;
+ recharge_soc = chip->dt.recharge_soc_thr;
+ recharge_soc = DIV_ROUND_CLOSEST(recharge_soc * FULL_SOC_RAW,
+ FULL_CAPACITY);
+ rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &bsoc);
+ if (rc < 0) {
+ pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* We need 2 most significant bytes here */
+ bsoc = (u32)bsoc >> 16;
+ rc = fg_get_prop_capacity(chip, &msoc);
+ if (rc < 0) {
+ pr_err("Error in getting capacity, rc=%d\n", rc);
+ return rc;
+ }
+
+ fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc,
+ chip->health, chip->status);
+ if (chip->charge_done) {
+ if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD)
+ chip->charge_full = true;
+ else
+ fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
+ msoc);
+ } else if ((bsoc >> 8) <= recharge_soc) {
+ fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d\n",
+ bsoc >> 8, recharge_soc);
+ chip->charge_full = false;
+ }
+
+ if (!chip->charge_full)
+ return 0;
+
+ /*
+ * During JEITA conditions, charge_full can happen early. FULL_SOC
+ * and MONOTONIC_SOC needs to be updated to reflect the same. Write
+ * battery SOC to FULL_SOC and write a full value to MONOTONIC_SOC.
+ */
+ rc = fg_sram_write(chip, FULL_SOC_WORD, FULL_SOC_OFFSET, (u8 *)&bsoc, 2,
+ FG_IMA_ATOMIC);
+ if (rc < 0) {
+ pr_err("failed to write full_soc rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = fg_sram_write(chip, MONOTONIC_SOC_WORD, MONOTONIC_SOC_OFFSET,
+ full_soc, 2, FG_IMA_ATOMIC);
+ if (rc < 0) {
+ pr_err("failed to write monotonic_soc rc=%d\n", rc);
+ return rc;
+ }
+
+ fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc);
+ return 0;
+}
+
+static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc)
+{
+ u8 buf[4];
+ int rc;
+
+ fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf);
+ rc = fg_sram_write(chip,
+ chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
+ chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte, buf,
+ chip->sp[FG_SRAM_RECHARGE_SOC_THR].len, FG_IMA_DEFAULT);
+ if (rc < 0) {
+ pr_err("Error in writing recharge_soc_thr, rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int fg_adjust_recharge_soc(struct fg_chip *chip)
+{
+ int rc, msoc, recharge_soc, new_recharge_soc = 0;
+
+ recharge_soc = chip->dt.recharge_soc_thr;
+ /*
+ * If the input is present and charging had been terminated, adjust
+ * the recharge SOC threshold based on the monotonic SOC at which
+ * the charge termination had happened.
+ */
+ if (is_input_present(chip) && !chip->recharge_soc_adjusted
+ && chip->charge_done) {
+ /* Get raw monotonic SOC for calculation */
+ rc = fg_get_msoc_raw(chip, &msoc);
+ if (rc < 0) {
+ pr_err("Error in getting msoc, rc=%d\n", rc);
+ return rc;
+ }
+
+ msoc = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW);
+ /* Adjust the recharge_soc threshold */
+ new_recharge_soc = msoc - (FULL_CAPACITY - recharge_soc);
+ } else if (chip->recharge_soc_adjusted && (!is_input_present(chip)
+ || chip->health == POWER_SUPPLY_HEALTH_GOOD)) {
+ /* Restore the default value */
+ new_recharge_soc = recharge_soc;
+ }
+
+ if (new_recharge_soc > 0 && new_recharge_soc < FULL_CAPACITY) {
+ rc = fg_set_recharge_soc(chip, new_recharge_soc);
+ if (rc) {
+ pr_err("Couldn't set resume SOC for FG, rc=%d\n", rc);
+ return rc;
+ }
+
+ chip->recharge_soc_adjusted = (new_recharge_soc !=
+ recharge_soc);
+ fg_dbg(chip, FG_STATUS, "resume soc set to %d\n",
+ new_recharge_soc);
+ }
+
+ return 0;
+}
+
static void status_change_work(struct work_struct *work)
{
struct fg_chip *chip = container_of(work,
struct fg_chip, status_change_work);
union power_supply_propval prop = {0, };
- int prev_status, rc;
+ int rc;
if (!is_charger_available(chip)) {
fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
goto out;
}
- prev_status = chip->status;
rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_STATUS,
&prop);
if (rc < 0) {
@@ -1155,14 +1369,25 @@ static void status_change_work(struct work_struct *work)
}
chip->charge_done = prop.intval;
- fg_dbg(chip, FG_POWER_SUPPLY, "prev_status: %d curr_status:%d charge_done: %d\n",
- prev_status, chip->status, chip->charge_done);
- if (prev_status != chip->status) {
- if (chip->cyc_ctr.en)
- schedule_work(&chip->cycle_count_work);
- fg_cap_learning_update(chip);
- }
+ fg_dbg(chip, FG_POWER_SUPPLY, "curr_status:%d charge_done: %d\n",
+ chip->status, chip->charge_done);
+ if (chip->cyc_ctr.en)
+ schedule_work(&chip->cycle_count_work);
+
+ fg_cap_learning_update(chip);
+
+ rc = fg_charge_full_update(chip);
+ if (rc < 0)
+ pr_err("Error in charge_full_update, rc=%d\n", rc);
+
+ rc = fg_adjust_recharge_soc(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting recharge_soc, rc=%d\n", rc);
+
+ rc = fg_adjust_ki_coeff_dischg(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
out:
pm_relax(chip->dev);
}
@@ -1247,6 +1472,9 @@ static void cycle_count_work(struct work_struct *work)
goto out;
}
+ /* We need only the most significant byte here */
+ batt_soc = (u32)batt_soc >> 24;
+
if (chip->status == POWER_SUPPLY_STATUS_CHARGING) {
/* Find out which bucket the SOC falls in */
bucket = batt_soc / BUCKET_SOC_PCT;
@@ -1787,16 +2015,9 @@ static int fg_hw_init(struct fg_chip *chip)
}
if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) {
- fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR,
- chip->dt.recharge_soc_thr, buf);
- rc = fg_sram_write(chip,
- chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_word,
- chip->sp[FG_SRAM_RECHARGE_SOC_THR].addr_byte,
- buf, chip->sp[FG_SRAM_RECHARGE_SOC_THR].len,
- FG_IMA_DEFAULT);
+ rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr);
if (rc < 0) {
- pr_err("Error in writing recharge_soc_thr, rc=%d\n",
- rc);
+ pr_err("Error in setting recharge_soc, rc=%d\n", rc);
return rc;
}
}
@@ -1982,6 +2203,7 @@ static irqreturn_t fg_soc_update_irq_handler(int irq, void *data)
static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
{
struct fg_chip *chip = data;
+ int rc;
if (chip->cyc_ctr.en)
schedule_work(&chip->cycle_count_work);
@@ -1994,6 +2216,14 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
if (chip->cl.active)
fg_cap_learning_update(chip);
+ rc = fg_charge_full_update(chip);
+ if (rc < 0)
+ pr_err("Error in charge_full_update, rc=%d\n", rc);
+
+ rc = fg_adjust_ki_coeff_dischg(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
+
return IRQ_HANDLED;
}
@@ -2154,6 +2384,73 @@ static int fg_register_interrupts(struct fg_chip *chip)
return 0;
}
+static int fg_parse_ki_coefficients(struct fg_chip *chip)
+{
+ struct device_node *node = chip->dev->of_node;
+ int rc, i;
+
+ rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-soc-dischg",
+ sizeof(u32));
+ if (rc != KI_COEFF_SOC_LEVELS)
+ return 0;
+
+ rc = of_property_read_u32_array(node, "qcom,ki-coeff-soc-dischg",
+ chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
+ if (rc < 0) {
+ pr_err("Error in reading ki-coeff-soc-dischg, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-med-dischg",
+ sizeof(u32));
+ if (rc != KI_COEFF_SOC_LEVELS)
+ return 0;
+
+ rc = of_property_read_u32_array(node, "qcom,ki-coeff-med-dischg",
+ chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
+ if (rc < 0) {
+ pr_err("Error in reading ki-coeff-med-dischg, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = of_property_count_elems_of_size(node, "qcom,ki-coeff-hi-dischg",
+ sizeof(u32));
+ if (rc != KI_COEFF_SOC_LEVELS)
+ return 0;
+
+ rc = of_property_read_u32_array(node, "qcom,ki-coeff-hi-dischg",
+ chip->dt.ki_coeff_hi_dischg, KI_COEFF_SOC_LEVELS);
+ if (rc < 0) {
+ pr_err("Error in reading ki-coeff-hi-dischg, rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ for (i = 0; i < KI_COEFF_SOC_LEVELS; i++) {
+ if (chip->dt.ki_coeff_soc[i] < 0 ||
+ chip->dt.ki_coeff_soc[i] > FULL_CAPACITY) {
+ pr_err("Error in ki_coeff_soc_dischg values\n");
+ return -EINVAL;
+ }
+
+ if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
+ chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
+ pr_err("Error in ki_coeff_med_dischg values\n");
+ return -EINVAL;
+ }
+
+ if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
+ chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
+ pr_err("Error in ki_coeff_med_dischg values\n");
+ return -EINVAL;
+ }
+ }
+ chip->ki_coeff_dischg_en = true;
+ return 0;
+}
+
#define DEFAULT_CUTOFF_VOLT_MV 3200
#define DEFAULT_EMPTY_VOLT_MV 3100
#define DEFAULT_CHG_TERM_CURR_MA 100
@@ -2416,6 +2713,13 @@ static int fg_parse_dt(struct fg_chip *chip)
else if (temp > BTEMP_DELTA_LOW && temp <= BTEMP_DELTA_HIGH)
chip->dt.batt_temp_delta = temp;
+ chip->dt.hold_soc_while_full = of_property_read_bool(node,
+ "qcom,hold-soc-while-full");
+
+ rc = fg_parse_ki_coefficients(chip);
+ if (rc < 0)
+ pr_err("Error in parsing Ki coefficients, rc=%d\n", rc);
+
return 0;
}
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index b7fa71dd0695..9cfca014c8ad 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -2583,6 +2583,7 @@ void *glink_open(const struct glink_open_config *cfg)
ctx->notify_tx_abort = cfg->notify_tx_abort;
ctx->notify_rx_tracer_pkt = cfg->notify_rx_tracer_pkt;
ctx->notify_remote_rx_intent = cfg->notify_remote_rx_intent;
+ ctx->magic_number = GLINK_CTX_CANARY;
if (!ctx->notify_rx_intent_req)
ctx->notify_rx_intent_req = glink_dummy_notify_rx_intent_req;
@@ -2618,7 +2619,6 @@ void *glink_open(const struct glink_open_config *cfg)
GLINK_INFO_CH(ctx, "%s: Created channel, sent OPEN command. ctx %p\n",
__func__, ctx);
- ctx->magic_number = GLINK_CTX_CANARY;
return ctx;
}
EXPORT_SYMBOL(glink_open);
@@ -5380,7 +5380,7 @@ static int glink_scheduler_tx(struct channel_ctx *ctx,
size_t txd_len = 0;
size_t tx_len = 0;
uint32_t num_pkts = 0;
- int ret;
+ int ret = 0;
spin_lock_irqsave(&ctx->tx_lists_lock_lhc3, flags);
while (txd_len < xprt_ctx->mtu &&
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 2aa588ba610b..f47d4a51fccd 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -33,7 +33,6 @@
#include <linux/dma-mapping.h>
#include <linux/qmi_encdec.h>
#include <linux/ipc_logging.h>
-#include <linux/msm-bus.h>
#include <linux/thread_info.h>
#include <linux/uaccess.h>
#include <linux/qpnp/qpnp-adc.h>
@@ -411,8 +410,6 @@ static struct icnss_priv {
size_t smmu_iova_len;
dma_addr_t smmu_iova_ipa_start;
size_t smmu_iova_ipa_len;
- struct msm_bus_scale_pdata *bus_scale_table;
- uint32_t bus_client;
struct qmi_handle *wlfw_clnt;
struct list_head event_list;
spinlock_t event_lock;
@@ -3410,62 +3407,6 @@ unsigned int icnss_socinfo_get_serial_number(struct device *dev)
}
EXPORT_SYMBOL(icnss_socinfo_get_serial_number);
-static int icnss_bw_vote(struct icnss_priv *priv, int index)
-{
- int ret = 0;
-
- icnss_pr_dbg("Vote %d for msm_bus, state 0x%lx\n",
- index, priv->state);
- ret = msm_bus_scale_client_update_request(priv->bus_client, index);
- if (ret)
- icnss_pr_err("Fail to vote %d: ret %d, state 0x%lx\n",
- index, ret, priv->state);
-
- return ret;
-}
-
-static int icnss_bw_init(struct icnss_priv *priv)
-{
- int ret = 0;
-
- priv->bus_scale_table = msm_bus_cl_get_pdata(priv->pdev);
- if (!priv->bus_scale_table) {
- icnss_pr_err("Missing entry for msm_bus scale table\n");
- return -EINVAL;
- }
-
- priv->bus_client = msm_bus_scale_register_client(priv->bus_scale_table);
- if (!priv->bus_client) {
- icnss_pr_err("Fail to register with bus_scale client\n");
- ret = -EINVAL;
- goto out;
- }
-
- ret = icnss_bw_vote(priv, 1);
- if (ret)
- goto out;
-
- return 0;
-
-out:
- msm_bus_cl_clear_pdata(priv->bus_scale_table);
- return ret;
-}
-
-static void icnss_bw_deinit(struct icnss_priv *priv)
-{
- if (!priv)
- return;
-
- if (priv->bus_client) {
- icnss_bw_vote(priv, 0);
- msm_bus_scale_unregister_client(priv->bus_client);
- }
-
- if (priv->bus_scale_table)
- msm_bus_cl_clear_pdata(priv->bus_scale_table);
-}
-
static int icnss_smmu_init(struct icnss_priv *priv)
{
struct dma_iommu_mapping *mapping;
@@ -4419,10 +4360,6 @@ static int icnss_probe(struct platform_device *pdev)
priv->smmu_iova_len);
goto out;
}
-
- ret = icnss_bw_init(priv);
- if (ret)
- goto out_smmu_deinit;
}
spin_lock_init(&priv->event_lock);
@@ -4432,7 +4369,7 @@ static int icnss_probe(struct platform_device *pdev)
if (!priv->event_wq) {
icnss_pr_err("Workqueue creation failed\n");
ret = -EFAULT;
- goto out_bw_deinit;
+ goto out_smmu_deinit;
}
INIT_WORK(&priv->event_work, icnss_driver_event_work);
@@ -4460,8 +4397,6 @@ static int icnss_probe(struct platform_device *pdev)
out_destroy_wq:
destroy_workqueue(priv->event_wq);
-out_bw_deinit:
- icnss_bw_deinit(priv);
out_smmu_deinit:
icnss_smmu_deinit(priv);
out:
@@ -4487,8 +4422,6 @@ static int icnss_remove(struct platform_device *pdev)
if (penv->event_wq)
destroy_workqueue(penv->event_wq);
- icnss_bw_deinit(penv);
-
icnss_hw_power_off(penv);
dev_set_drvdata(&pdev->dev, NULL);
diff --git a/drivers/soc/qcom/qsee_ipc_irq_bridge.c b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
index ab43bbb7e86a..eee42d7ba314 100644
--- a/drivers/soc/qcom/qsee_ipc_irq_bridge.c
+++ b/drivers/soc/qcom/qsee_ipc_irq_bridge.c
@@ -115,10 +115,8 @@ static struct qiib_driver_data *qiib_info;
static int qiib_driver_data_init(void)
{
qiib_info = kzalloc(sizeof(*qiib_info), GFP_KERNEL);
- if (!qiib_info) {
- QIIB_ERR("Unable to allocate info pointer\n");
+ if (!qiib_info)
return -ENOMEM;
- }
INIT_LIST_HEAD(&qiib_info->list);
mutex_init(&qiib_info->list_lock);
@@ -356,6 +354,7 @@ static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
const char *dev_name;
uint32_t irqtype;
uint32_t irq_clear[2];
+ struct irq_data *irqtype_data;
int ret = -ENODEV;
key = "qcom,dev-name";
@@ -374,7 +373,12 @@ static int qiib_parse_node(struct device_node *node, struct qiib_dev *devp)
}
QIIB_DBG("%s: %s = %d\n", __func__, key, devp->irq_line);
- irqtype = irqd_get_trigger_type(irq_get_irq_data(devp->irq_line));
+ irqtype_data = irq_get_irq_data(devp->irq_line);
+ if (!irqtype_data) {
+ QIIB_ERR("%s: get irqdata fail:%d\n", __func__, devp->irq_line);
+ goto missing_key;
+ }
+ irqtype = irqd_get_trigger_type(irqtype_data);
QIIB_DBG("%s: irqtype = %d\n", __func__, irqtype);
key = "label";
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 8a0e7f988d25..0121bf7ca4ac 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -1111,7 +1111,7 @@ static struct usb_function_instance *f_midi_alloc_inst(void)
opts->func_inst.free_func_inst = f_midi_free_inst;
opts->index = SNDRV_DEFAULT_IDX1;
opts->id = SNDRV_DEFAULT_STR1;
- opts->buflen = 256;
+ opts->buflen = 1024;
opts->qlen = 32;
opts->in_ports = 1;
opts->out_ports = 1;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 12b98017beb2..915080a5b817 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -168,8 +168,12 @@ static void *usbpd_ipc_log;
#define PS_HARD_RESET_TIME 25
#define PS_SOURCE_ON 400
#define PS_SOURCE_OFF 750
+#define SWAP_SOURCE_START_TIME 20
#define VDM_BUSY_TIME 50
+/* tPSHardReset + tSafe0V + tSrcRecover + tSrcTurnOn */
+#define SNK_HARD_RESET_RECOVER_TIME (35 + 650 + 1000 + 275)
+
#define PD_CAPS_COUNT 50
#define PD_MAX_MSG_ID 7
@@ -593,6 +597,11 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
/* Defer starting USB host mode until after PD */
}
+ /* Set CC back to DRP toggle for the next disconnect */
+ val.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &val);
+
pd->rx_msg_len = 0;
pd->rx_msg_type = 0;
pd->rx_msgid = -1;
@@ -622,10 +631,15 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
- pd->in_pr_swap = false;
pd->current_state = PE_SRC_SEND_CAPABILITIES;
- usbpd_dbg(&pd->dev, "Enter %s\n",
- usbpd_state_strings[pd->current_state]);
+ if (pd->in_pr_swap) {
+ pd->in_pr_swap = false;
+ hrtimer_start(&pd->timer,
+ ms_to_ktime(SWAP_SOURCE_START_TIME),
+ HRTIMER_MODE_REL);
+ break;
+ }
+
/* fall-through */
case PE_SRC_SEND_CAPABILITIES:
@@ -800,18 +814,6 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
pd->in_pr_swap = false;
pd->current_voltage = 5000000;
- if (!pd->vbus_present) {
- /* can get here during a hard reset and we lost vbus */
- pd->current_state = PE_SNK_DISCOVERY;
- hrtimer_start(&pd->timer, ms_to_ktime(2000),
- HRTIMER_MODE_REL);
- break;
- }
-
- /*
- * If VBUS is already present go and skip ahead to
- * PE_SNK_WAIT_FOR_CAPABILITIES.
- */
pd->current_state = PE_SNK_WAIT_FOR_CAPABILITIES;
/* fall-through */
@@ -882,8 +884,28 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
pd->current_voltage = pd->requested_voltage;
- /* recursive call; go back to beginning state */
- usbpd_set_state(pd, PE_SNK_STARTUP);
+ /* max time for hard reset to toggle vbus off/on */
+ hrtimer_start(&pd->timer,
+ ms_to_ktime(SNK_HARD_RESET_RECOVER_TIME),
+ HRTIMER_MODE_REL);
+ break;
+
+ case PE_PRS_SNK_SRC_TRANSITION_TO_OFF:
+ val.intval = pd->requested_current = 0; /* suspend charging */
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+
+ pd->in_explicit_contract = false;
+
+ /*
+ * need to update PR bit in message header so that
+ * proper GoodCRC is sent when receiving next PS_RDY
+ */
+ pd_phy_update_roles(pd->current_dr, PR_SRC);
+
+ /* wait for PS_RDY */
+ hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF),
+ HRTIMER_MODE_REL);
break;
default:
@@ -1276,12 +1298,12 @@ static void usbpd_sm(struct work_struct *w)
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
- if (pd->current_pr == PR_SRC) {
+ if (pd->current_pr == PR_SRC)
regulator_disable(pd->vbus);
- if (pd->vconn_enabled) {
- regulator_disable(pd->vconn);
- pd->vconn_enabled = false;
- }
+
+ if (pd->vconn_enabled) {
+ regulator_disable(pd->vconn);
+ pd->vconn_enabled = false;
}
if (pd->current_dr == DR_UFP)
@@ -1388,7 +1410,7 @@ static void usbpd_sm(struct work_struct *w)
pd->hard_reset_count = 0;
pd->pd_connected = true; /* we know peer is PD capable */
- val.intval = POWER_SUPPLY_TYPE_USB_PD;
+ val.intval = pd->psy_type = POWER_SUPPLY_TYPE_USB_PD;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPE, &val);
@@ -1436,6 +1458,9 @@ static void usbpd_sm(struct work_struct *w)
dr_swap(pd);
kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
} else if (ctrl_recvd == MSG_PR_SWAP) {
+ /* lock in current mode */
+ set_power_role(pd, pd->current_pr);
+
/* we'll happily accept Src->Sink requests anytime */
ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG);
if (ret) {
@@ -1445,7 +1470,9 @@ static void usbpd_sm(struct work_struct *w)
}
pd->current_state = PE_PRS_SRC_SNK_TRANSITION_TO_OFF;
- queue_work(pd->wq, &pd->sm_work);
+ hrtimer_start(&pd->timer,
+ ms_to_ktime(SRC_TRANSITION_TIME),
+ HRTIMER_MODE_REL);
break;
} else {
if (data_recvd == MSG_VDM)
@@ -1465,28 +1492,13 @@ static void usbpd_sm(struct work_struct *w)
usbpd_set_state(pd, PE_SRC_TRANSITION_TO_DEFAULT);
break;
- case PE_SNK_DISCOVERY:
- if (!pd->vbus_present) {
- /* Hard reset and VBUS didn't come back? */
- power_supply_get_property(pd->usb_psy,
- POWER_SUPPLY_PROP_TYPE, &val);
- if (val.intval == POWER_SUPPLY_TYPEC_NONE) {
- pd->typec_mode = POWER_SUPPLY_TYPEC_NONE;
- queue_work(pd->wq, &pd->sm_work);
- }
- break;
- }
-
- usbpd_set_state(pd, PE_SNK_WAIT_FOR_CAPABILITIES);
- break;
-
case PE_SNK_WAIT_FOR_CAPABILITIES:
if (data_recvd == MSG_SOURCE_CAPABILITIES) {
val.intval = 1;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
- val.intval = POWER_SUPPLY_TYPE_USB_PD;
+ val.intval = pd->psy_type = POWER_SUPPLY_TYPE_USB_PD;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_TYPE, &val);
@@ -1580,6 +1592,9 @@ static void usbpd_sm(struct work_struct *w)
dr_swap(pd);
kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
} else if (ctrl_recvd == MSG_PR_SWAP) {
+ /* lock in current mode */
+ set_power_role(pd, pd->current_pr);
+
/* TODO: should we Reject in certain circumstances? */
ret = pd_send_msg(pd, MSG_ACCEPT, NULL, 0, SOP_MSG);
if (ret) {
@@ -1589,19 +1604,7 @@ static void usbpd_sm(struct work_struct *w)
}
pd->in_pr_swap = true;
- pd->current_state = PE_PRS_SNK_SRC_TRANSITION_TO_OFF;
- /* turn off sink */
- pd->in_explicit_contract = false;
-
- /*
- * need to update PR bit in message header so that
- * proper GoodCRC is sent when receiving next PS_RDY
- */
- pd->current_pr = PR_SRC;
- pd_phy_update_roles(pd->current_dr, pd->current_pr);
-
- hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF),
- HRTIMER_MODE_REL);
+ usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
break;
} else {
if (data_recvd == MSG_VDM)
@@ -1611,6 +1614,20 @@ static void usbpd_sm(struct work_struct *w)
}
break;
+ case PE_SNK_TRANSITION_TO_DEFAULT:
+ if (pd->vbus_present) {
+ usbpd_set_state(pd, PE_SNK_STARTUP);
+ } else {
+ /* Hard reset and VBUS didn't come back? */
+ power_supply_get_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_TYPEC_MODE, &val);
+ if (val.intval == POWER_SUPPLY_TYPEC_NONE) {
+ pd->typec_mode = POWER_SUPPLY_TYPEC_NONE;
+ queue_work(pd->wq, &pd->sm_work);
+ }
+ }
+ break;
+
case PE_SRC_SOFT_RESET:
case PE_SNK_SOFT_RESET:
/* Reset protocol layer */
@@ -1684,16 +1701,24 @@ static void usbpd_sm(struct work_struct *w)
}
pd->current_state = PE_PRS_SRC_SNK_TRANSITION_TO_OFF;
- /* fall-through */
+ hrtimer_start(&pd->timer, ms_to_ktime(SRC_TRANSITION_TIME),
+ HRTIMER_MODE_REL);
+ break;
+
case PE_PRS_SRC_SNK_TRANSITION_TO_OFF:
pd->in_pr_swap = true;
pd->in_explicit_contract = false;
regulator_disable(pd->vbus);
- set_power_role(pd, PR_SINK); /* switch Rp->Rd */
+
+ /* PE_PRS_SRC_SNK_Assert_Rd */
pd->current_pr = PR_SINK;
+ set_power_role(pd, pd->current_pr);
pd_phy_update_roles(pd->current_dr, pd->current_pr);
+ /* allow time for Vbus discharge, must be < tSrcSwapStdby */
+ msleep(500);
+
ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG);
if (ret) {
usbpd_err(&pd->dev, "Error sending PS_RDY\n");
@@ -1720,19 +1745,7 @@ static void usbpd_sm(struct work_struct *w)
}
pd->in_pr_swap = true;
- pd->current_state = PE_PRS_SNK_SRC_TRANSITION_TO_OFF;
- /* turn off sink */
- pd->in_explicit_contract = false;
-
- /*
- * need to update PR bit in message header so that
- * proper GoodCRC is sent when receiving next PS_RDY
- */
- pd->current_pr = PR_SRC;
- pd_phy_update_roles(pd->current_dr, pd->current_pr);
-
- hrtimer_start(&pd->timer, ms_to_ktime(PS_SOURCE_OFF),
- HRTIMER_MODE_REL);
+ usbpd_set_state(pd, PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
break;
case PE_PRS_SNK_SRC_TRANSITION_TO_OFF:
@@ -1741,14 +1754,20 @@ static void usbpd_sm(struct work_struct *w)
break;
}
+ /* PE_PRS_SNK_SRC_Assert_Rp */
+ pd->current_pr = PR_SRC;
+ set_power_role(pd, pd->current_pr);
pd->current_state = PE_PRS_SNK_SRC_SOURCE_ON;
+
/* fall-through */
+
case PE_PRS_SNK_SRC_SOURCE_ON:
- set_power_role(pd, PR_SRC);
ret = regulator_enable(pd->vbus);
if (ret)
usbpd_err(&pd->dev, "Unable to enable vbus\n");
+ msleep(200); /* allow time VBUS ramp-up, must be < tNewSrc */
+
ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG);
if (ret) {
usbpd_err(&pd->dev, "Error sending PS_RDY\n");
@@ -1846,11 +1865,12 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
* until the HW bug is fixed: in which disconnection won't be reported
* on VBUS loss alone unless pullup is also removed from CC.
*/
- if ((pd->hard_reset || pd->in_pr_swap) &&
- typec_mode == POWER_SUPPLY_TYPEC_NONE &&
- pd->psy_type != POWER_SUPPLY_TYPE_USB) {
+ if (typec_mode == POWER_SUPPLY_TYPEC_NONE &&
+ (pd->in_pr_swap ||
+ (pd->psy_type != POWER_SUPPLY_TYPE_USB &&
+ pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT))) {
usbpd_dbg(&pd->dev, "Ignoring disconnect due to %s\n",
- pd->hard_reset ? "hard reset" : "PR swap");
+ pd->in_pr_swap ? "PR swap" : "hard reset");
return 0;
}
@@ -1863,8 +1883,9 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
psy_type = val.intval;
- usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d\n", typec_mode,
- pd->vbus_present, psy_type);
+ usbpd_dbg(&pd->dev, "typec mode:%d present:%d type:%d orientation:%d\n",
+ typec_mode, pd->vbus_present, psy_type,
+ usbpd_get_plug_orientation(pd));
/* any change? */
if (pd->typec_mode == typec_mode && pd->psy_type == psy_type)
@@ -1885,7 +1906,8 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
usbpd_info(&pd->dev, "Type-C Source (%s) connected\n",
src_current(typec_mode));
- if (pd->current_pr != PR_SINK) {
+ if (pd->current_pr != PR_SINK ||
+ pd->current_state == PE_SNK_TRANSITION_TO_DEFAULT) {
pd->current_pr = PR_SINK;
queue_work(pd->wq, &pd->sm_work);
}
diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c
index 6bf80e43cac5..021755f7f32d 100644
--- a/drivers/video/fbdev/core/fbcmap.c
+++ b/drivers/video/fbdev/core/fbcmap.c
@@ -187,8 +187,8 @@ int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to)
int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
{
- int tooff = 0, fromoff = 0;
- int size;
+ u32 tooff = 0, fromoff = 0;
+ u32 size;
if (to->start > from->start)
fromoff = to->start - from->start;
@@ -198,10 +198,10 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to)
return -EINVAL;
size = to->len - tooff;
- if (size > (int) (from->len - fromoff))
+ if (size > (from->len - fromoff))
size = from->len - fromoff;
size *= sizeof(u16);
- if (!size)
+ if (size == 0)
return -EINVAL;
if (copy_to_user(to->red+tooff, from->red+fromoff, size))
diff --git a/include/soc/qcom/smem.h b/include/soc/qcom/smem.h
index b5425dd7eaea..4117b0d47b0d 100644
--- a/include/soc/qcom/smem.h
+++ b/include/soc/qcom/smem.h
@@ -22,11 +22,11 @@ enum {
SMEM_DSPS,
SMEM_WCNSS,
SMEM_MODEM_Q6_FW,
+ SMEM_CDSP = SMEM_MODEM_Q6_FW,
SMEM_RPM,
SMEM_TZ,
SMEM_SPSS,
SMEM_HYP,
- SMEM_CDSP,
NUM_SMEM_SUBSYSTEMS,
};
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ff7f6f35fc8f..024fb1007c78 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -8239,7 +8239,7 @@ void set_curr_task(int cpu, struct task_struct *p)
/* task_group_lock serializes the addition/removal of task groups */
static DEFINE_SPINLOCK(task_group_lock);
-static void free_sched_group(struct task_group *tg)
+static void sched_free_group(struct task_group *tg)
{
free_fair_sched_group(tg);
free_rt_sched_group(tg);
@@ -8265,7 +8265,7 @@ struct task_group *sched_create_group(struct task_group *parent)
return tg;
err:
- free_sched_group(tg);
+ sched_free_group(tg);
return ERR_PTR(-ENOMEM);
}
@@ -8285,27 +8285,24 @@ void sched_online_group(struct task_group *tg, struct task_group *parent)
}
/* rcu callback to free various structures associated with a task group */
-static void free_sched_group_rcu(struct rcu_head *rhp)
+static void sched_free_group_rcu(struct rcu_head *rhp)
{
/* now it should be safe to free those cfs_rqs */
- free_sched_group(container_of(rhp, struct task_group, rcu));
+ sched_free_group(container_of(rhp, struct task_group, rcu));
}
-/* Destroy runqueue etc associated with a task group */
void sched_destroy_group(struct task_group *tg)
{
/* wait for possible concurrent references to cfs_rqs complete */
- call_rcu(&tg->rcu, free_sched_group_rcu);
+ call_rcu(&tg->rcu, sched_free_group_rcu);
}
void sched_offline_group(struct task_group *tg)
{
unsigned long flags;
- int i;
/* end participation in shares distribution */
- for_each_possible_cpu(i)
- unregister_fair_sched_group(tg, i);
+ unregister_fair_sched_group(tg);
spin_lock_irqsave(&task_group_lock, flags);
list_del_rcu(&tg->list);
@@ -8756,31 +8753,26 @@ cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
if (IS_ERR(tg))
return ERR_PTR(-ENOMEM);
+ sched_online_group(tg, parent);
+
return &tg->css;
}
-static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
+static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
{
struct task_group *tg = css_tg(css);
- struct task_group *parent = css_tg(css->parent);
- if (parent)
- sched_online_group(tg, parent);
- return 0;
+ sched_offline_group(tg);
}
static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
{
struct task_group *tg = css_tg(css);
- sched_destroy_group(tg);
-}
-
-static void cpu_cgroup_css_offline(struct cgroup_subsys_state *css)
-{
- struct task_group *tg = css_tg(css);
-
- sched_offline_group(tg);
+ /*
+ * Relies on the RCU grace period between css_released() and this.
+ */
+ sched_free_group(tg);
}
static void cpu_cgroup_fork(struct task_struct *task, void *private)
@@ -9147,9 +9139,8 @@ static struct cftype cpu_files[] = {
struct cgroup_subsys cpu_cgrp_subsys = {
.css_alloc = cpu_cgroup_css_alloc,
+ .css_released = cpu_cgroup_css_released,
.css_free = cpu_cgroup_css_free,
- .css_online = cpu_cgroup_css_online,
- .css_offline = cpu_cgroup_css_offline,
.fork = cpu_cgroup_fork,
.can_attach = cpu_cgroup_can_attach,
.attach = cpu_cgroup_attach,
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7fdf1efa9086..6362b864e2b1 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -9653,11 +9653,8 @@ void free_fair_sched_group(struct task_group *tg)
for_each_possible_cpu(i) {
if (tg->cfs_rq)
kfree(tg->cfs_rq[i]);
- if (tg->se) {
- if (tg->se[i])
- remove_entity_load_avg(tg->se[i]);
+ if (tg->se)
kfree(tg->se[i]);
- }
}
kfree(tg->cfs_rq);
@@ -9705,21 +9702,29 @@ err:
return 0;
}
-void unregister_fair_sched_group(struct task_group *tg, int cpu)
+void unregister_fair_sched_group(struct task_group *tg)
{
- struct rq *rq = cpu_rq(cpu);
unsigned long flags;
+ struct rq *rq;
+ int cpu;
- /*
- * Only empty task groups can be destroyed; so we can speculatively
- * check on_list without danger of it being re-added.
- */
- if (!tg->cfs_rq[cpu]->on_list)
- return;
+ for_each_possible_cpu(cpu) {
+ if (tg->se[cpu])
+ remove_entity_load_avg(tg->se[cpu]);
- raw_spin_lock_irqsave(&rq->lock, flags);
- list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
- raw_spin_unlock_irqrestore(&rq->lock, flags);
+ /*
+ * Only empty task groups can be destroyed; so we can speculatively
+ * check on_list without danger of it being re-added.
+ */
+ if (!tg->cfs_rq[cpu]->on_list)
+ continue;
+
+ rq = cpu_rq(cpu);
+
+ raw_spin_lock_irqsave(&rq->lock, flags);
+ list_del_leaf_cfs_rq(tg->cfs_rq[cpu]);
+ raw_spin_unlock_irqrestore(&rq->lock, flags);
+ }
}
void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
@@ -9801,7 +9806,7 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
return 1;
}
-void unregister_fair_sched_group(struct task_group *tg, int cpu) { }
+void unregister_fair_sched_group(struct task_group *tg) { }
#endif /* CONFIG_FAIR_GROUP_SCHED */
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index ada5e580e968..27b28369440d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -313,7 +313,7 @@ extern int tg_nop(struct task_group *tg, void *data);
extern void free_fair_sched_group(struct task_group *tg);
extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent);
-extern void unregister_fair_sched_group(struct task_group *tg, int cpu);
+extern void unregister_fair_sched_group(struct task_group *tg);
extern void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
struct sched_entity *se, int cpu,
struct sched_entity *parent);
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index dee66f231ceb..7d649ba2b505 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -318,8 +318,9 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
struct msm_ext_disp_audio_codec_rx_data *codec_data =
dev_get_drvdata(dai->codec->dev);
- if (!codec_data || !codec_data->ext_disp_ops.cable_status) {
- dev_err(dai->dev, "%s: codec data or cable_status is null\n",
+ if (!codec_data || !codec_data->ext_disp_ops.teardown_done ||
+ !codec_data->ext_disp_ops.cable_status) {
+ dev_err(dai->dev, "%s: codec data or teardown_done or cable_status is null\n",
__func__);
return;
}
@@ -332,6 +333,8 @@ static void msm_ext_disp_audio_codec_rx_dai_shutdown(
__func__);
}
+ codec_data->ext_disp_ops.teardown_done(
+ codec_data->ext_disp_core_pdev);
return;
}
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
index c3758620177d..8d2247176607 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
+++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
@@ -523,7 +523,9 @@ static int wcd_cntl_enable_memory(struct wcd_dsp_cntl *cntl)
ARRAY_SIZE(mem_enable_values),
mem_enable_values);
- snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0x05);
+ /* Make sure Deep sleep of memories is enabled for all banks */
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
done:
return ret;
}
@@ -533,6 +535,7 @@ static void wcd_cntl_disable_memory(struct wcd_dsp_cntl *cntl)
struct snd_soc_codec *codec = cntl->codec;
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_0, 0xFF);
+ snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_DEEPSLP_1, 0x0F);
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_3, 0xFF);
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_SYSMEM_SHUTDOWN_2, 0xFF);
snd_soc_write(codec, WCD934X_CPE_SS_PWR_CPE_DRAM1_SHUTDOWN, 0x07);
@@ -833,8 +836,7 @@ static int wcd_control_init(struct device *dev, void *priv_data)
struct snd_soc_codec *codec = cntl->codec;
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
- char wcd_cntl_dir_name[WCD_CNTL_DIR_NAME_LEN_MAX];
- int ret, ret1;
+ int ret;
bool err_irq_requested = false;
ret = wcd9xxx_request_irq(core_res,
@@ -876,25 +878,8 @@ static int wcd_control_init(struct device *dev, void *priv_data)
}
wcd_cntl_cpar_ctrl(cntl, true);
- snprintf(wcd_cntl_dir_name, WCD_CNTL_DIR_NAME_LEN_MAX,
- "%s%d", "wdsp", cntl->dsp_instance);
- wcd_cntl_debugfs_init(wcd_cntl_dir_name, cntl);
- ret = wcd_cntl_sysfs_init(wcd_cntl_dir_name, cntl);
- if (IS_ERR_VALUE(ret)) {
- dev_err(codec->dev,
- "%s: Failed to init sysfs %d\n",
- __func__, ret);
- goto err_sysfs_init;
- }
-
return 0;
-err_sysfs_init:
- wcd_cntl_cpar_ctrl(cntl, false);
- ret1 = wcd_cntl_clocks_disable(cntl);
- if (IS_ERR_VALUE(ret1))
- dev_err(codec->dev, "%s: Failed to disable clocks, err = %d\n",
- __func__, ret1);
err_clk_enable:
/* Mask all error interrupts */
snd_soc_write(codec, WCD934X_CPE_SS_SS_ERROR_INT_MASK_0A, 0xFF);
@@ -916,12 +901,6 @@ static int wcd_control_deinit(struct device *dev, void *priv_data)
struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
- /* Remove the sysfs entries */
- wcd_cntl_sysfs_remove(cntl);
-
- /* Remove the debugfs entries */
- wcd_cntl_debugfs_remove(cntl);
-
wcd_cntl_clocks_disable(cntl);
wcd_cntl_cpar_ctrl(cntl, false);
@@ -951,6 +930,7 @@ static int wcd_ctrl_component_bind(struct device *dev,
struct snd_card *card;
struct snd_info_entry *entry;
char proc_name[WCD_PROCFS_ENTRY_MAX_LEN];
+ char wcd_cntl_dir_name[WCD_CNTL_DIR_NAME_LEN_MAX];
int ret = 0;
if (!dev || !master || !data) {
@@ -982,6 +962,17 @@ static int wcd_ctrl_component_bind(struct device *dev,
goto done;
}
+ snprintf(wcd_cntl_dir_name, WCD_CNTL_DIR_NAME_LEN_MAX,
+ "%s%d", "wdsp", cntl->dsp_instance);
+ ret = wcd_cntl_sysfs_init(wcd_cntl_dir_name, cntl);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(dev, "%s: sysfs_init failed, err = %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ wcd_cntl_debugfs_init(wcd_cntl_dir_name, cntl);
+
codec = cntl->codec;
card = codec->component.card->snd_card;
snprintf(proc_name, WCD_PROCFS_ENTRY_MAX_LEN, "%s%d%s", "cpe",
@@ -1032,6 +1023,13 @@ static void wcd_ctrl_component_unbind(struct device *dev,
cntl->m_dev = NULL;
cntl->m_ops = NULL;
+
+ /* Remove the sysfs entries */
+ wcd_cntl_sysfs_remove(cntl);
+
+ /* Remove the debugfs entries */
+ wcd_cntl_debugfs_remove(cntl);
+
}
static const struct component_ops wcd_ctrl_component_ops = {
@@ -1040,6 +1038,60 @@ static const struct component_ops wcd_ctrl_component_ops = {
};
/*
+ * wcd_dsp_ssr_event: handle the SSR event raised by caller.
+ * @cntl: Handle to the wcd_dsp_cntl structure
+ * @event: The SSR event to be handled
+ *
+ * Notifies the manager driver about the SSR event.
+ * Returns 0 on success and negative error code on error.
+ */
+int wcd_dsp_ssr_event(struct wcd_dsp_cntl *cntl, enum cdc_ssr_event event)
+{
+ int ret = 0;
+
+ if (!cntl) {
+ pr_err("%s: Invalid handle to control\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!cntl->m_dev || !cntl->m_ops || !cntl->m_ops->signal_handler) {
+ dev_err(cntl->codec->dev,
+ "%s: Invalid signal_handler callback\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case WCD_CDC_DOWN_EVENT:
+ ret = cntl->m_ops->signal_handler(cntl->m_dev,
+ WDSP_CDC_DOWN_SIGNAL,
+ NULL);
+ if (IS_ERR_VALUE(ret))
+ dev_err(cntl->codec->dev,
+ "%s: WDSP_CDC_DOWN_SIGNAL failed, err = %d\n",
+ __func__, ret);
+ wcd_cntl_change_online_state(cntl, 0);
+ break;
+ case WCD_CDC_UP_EVENT:
+ ret = cntl->m_ops->signal_handler(cntl->m_dev,
+ WDSP_CDC_UP_SIGNAL,
+ NULL);
+ if (IS_ERR_VALUE(ret))
+ dev_err(cntl->codec->dev,
+ "%s: WDSP_CDC_UP_SIGNAL failed, err = %d\n",
+ __func__, ret);
+ break;
+ default:
+ dev_err(cntl->codec->dev, "%s: Invalid event %d\n",
+ __func__, event);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(wcd_dsp_ssr_event);
+
+/*
* wcd_dsp_cntl_init: Initialize the wcd-dsp control
* @codec: pointer to the codec handle
* @params: Parameters required to initialize wcd-dsp control
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h
index cd6697b3d641..83c59ed7b676 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h
+++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.h
@@ -17,6 +17,11 @@
#include <sound/soc.h>
#include <sound/wcd-dsp-mgr.h>
+enum cdc_ssr_event {
+ WCD_CDC_DOWN_EVENT,
+ WCD_CDC_UP_EVENT,
+};
+
struct wcd_dsp_cdc_cb {
/* Callback to enable codec clock */
int (*cdc_clk_en)(struct snd_soc_codec *, bool);
@@ -106,5 +111,5 @@ void wcd_dsp_cntl_init(struct snd_soc_codec *codec,
struct wcd_dsp_params *params,
struct wcd_dsp_cntl **cntl);
void wcd_dsp_cntl_deinit(struct wcd_dsp_cntl **cntl);
-
+int wcd_dsp_ssr_event(struct wcd_dsp_cntl *cntl, enum cdc_ssr_event event);
#endif /* end __WCD_DSP_CONTROL_H__ */