diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2016-10-14 13:24:16 -0600 |
|---|---|---|
| committer | Linux Build Service Account <lnxbuild@localhost> | 2016-10-14 13:24:17 -0600 |
| commit | b54fb1cc4df7349076c2456b0bc6f1c8bea4e17d (patch) | |
| tree | 9be499b25c07d603dbf1c85766676bad68afea39 | |
| parent | 2bddc21c9c64e791fb2dffe60bb7b9e2857da0b3 (diff) | |
| parent | e657410985b5d33b0b4e76f08587345e9fb195ce (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
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__ */ |
