diff options
229 files changed, 9443 insertions, 3558 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt index 7cf6871894dc..38c9fe749abb 100644 --- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt +++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt @@ -282,6 +282,16 @@ Properties: performance mode with a total of 4 tuples corresponding to each supported performance mode. +- qcom,pwrcl-apcs-mem-acc-threshold-voltage + Usage: optional + Value type: <u32> + Definition: Specifies the highest MEM ACC threshold voltage in + microvolts for the Power cluster. This voltage is + used to determine which MEM ACC setting is used for the + highest frequencies. If specified, the voltage must match + the MEM ACC threshold voltage specified for the + corresponding CPRh device. + - qcom,perfcl-apcs-mem-acc-val Usage: required if qcom,osm-no-tz is specified Value type: <prop-encoded-array> diff --git a/Documentation/devicetree/bindings/fb/mdss-dp.txt b/Documentation/devicetree/bindings/fb/mdss-dp.txt index 27516d3b54a5..7bf7b9bacb60 100644 --- a/Documentation/devicetree/bindings/fb/mdss-dp.txt +++ b/Documentation/devicetree/bindings/fb/mdss-dp.txt @@ -27,6 +27,7 @@ Required properties - qcom,aux-en-gpio: Specifies the aux-channel enable gpio. - qcom,aux-sel-gpio: Specifies the aux-channel select gpio. - qcom,usbplug-cc-gpio: Specifies the usbplug orientation gpio. +- qcom,aux-cfg-settings: An array that specifies the DP AUX configuration settings. Optional properties: - qcom,<type>-supply-entries: A node that lists the elements of the supply used by the @@ -51,6 +52,8 @@ Optional properties: - pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin controller. These pin configurations are installed in the pinctrl device node. Refer to pinctrl-bindings.txt +- qcom,logical2physical-lane-map: An array that specifies the DP logical to physical lane map setting. +- qcom,phy-register-offset: An integer specifying the offset value of DP PHY register space. Example: mdss_dp_ctrl: qcom,dp_ctrl@c990000 { @@ -83,6 +86,10 @@ Example: "core_aux_clk", "core_cfg_ahb_clk", "ctrl_link_clk", "ctrl_link_iface_clk", "ctrl_crypto_clk", "ctrl_pixel_clk"; + qcom,aux-cfg-settings = [00 13 00 10 0a 26 0a 03 8b 03]; + qcom,logical2physical-lane-map = [02 03 01 00]; + qcom,phy-register-offset = <0x4>; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt index 4564bfff3996..85e097586466 100644 --- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt +++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt @@ -1,10 +1,10 @@ -Qualcomm QPNP Leds +Qualcomm Technologies, Inc. QPNP LEDs -QPNP (Qualcomm Plug N Play) LEDs driver is used for -controlling LEDs that are part of PMIC on Qualcomm reference -platforms. The PMIC is connected to Host processor via -SPMI bus. This driver supports various LED modules such as -Keypad backlight, WLED (white LED), RGB LED and flash LED. +Qualcomm Technologies, Inc. Plug N Play (QPNP) LED modules +are used for controlling LEDs that are connected to a QPNP PMIC. +The PMIC is connected to a host processor via the SPMI bus. Various +LED modules are supported such as Keypad backlight, WLED (white LED), +RGB LED and flash LED. Each LED module is represented as a node of "leds-qpnp". This node will further contain the type of LED supported and its @@ -83,7 +83,7 @@ Optional properties for RGB led: - qcom,turn-off-delay-ms: delay in millisecond for turning off the led when its default-state is "on". Value is being ignored in case default-state is "off". - qcom,use-blink: Use blink sysfs entry for switching into lpg mode. For optimal use, set default mode to pwm. All required lpg parameters must be supplied. -MPP LED is an LED controled through a Multi Purpose Pin. +MPP LED is an LED controlled through a Multi Purpose Pin. Optional properties for MPP LED: - linux,default-trigger: trigger the led from external modules such as display diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt index 50b9b1ac8704..6ca0ac31a581 100644 --- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt +++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt @@ -132,6 +132,9 @@ value is typically max(latencies of every cluster at all power levels) + 1 memory, performance etc. - qcom,debug-timeout = A bool indicating that FW errors such as SYS_ERROR, SESSION_ERROR and timeouts will be treated as Fatal. +- qcom,power-conf = Indicates the value at which or beyond, a video session + is configured in low power mode to have power benefits. Value is defined + interms of HxW of the video session beyond which power benefit is desired. [Second level nodes] Context Banks @@ -226,6 +229,7 @@ Example: qcom,qdss-presets = <0xFC307000 0x1000>, <0xFC322000 0x1000>; qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,never-unload-fw; clock-names = "foo_clk", "bar_clk", "baz_clk"; qcom,clock-configs = <0x3 0x1 0x0>; diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt index 10c1bbf3c604..4d55f0cecefe 100644 --- a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt +++ b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt @@ -1,4 +1,4 @@ -Qualcomm QPNP Coincell - coincell battery charger devices +Qualcomm Technologies, Inc. QPNP Coincell - coincell battery charger devices Required properties: - compatible: Must be "qcom,qpnp-coincell". diff --git a/Documentation/devicetree/bindings/power/apm.txt b/Documentation/devicetree/bindings/power/apm.txt index 6cc53df11d02..fa03edfbb83c 100644 --- a/Documentation/devicetree/bindings/power/apm.txt +++ b/Documentation/devicetree/bindings/power/apm.txt @@ -7,7 +7,7 @@ SRAM minimum operating voltage, the APM controller can be used to request a switch to a power supply that will guarantee logic state retention. Required properties -- compatible: "qcom,msm-apm", "qcom,msm8996pro-apm", "qcom,msmtitanium-apm" +- compatible: "qcom,msm-apm", "qcom,msm8996pro-apm", "qcom,msm8953-apm" - reg: Specifies physical base address and size of memory mapped regions containing the APM controller, APCS CSR, APC PLL controller, and SPM event registers. @@ -23,16 +23,16 @@ Optional properties completes. - qcom,apm-post-halt-delay: The APM controller post halt delay counter value that SW needs to program one time before starting the APM HW controller for - msmtitanium target. + msm8953 target. - qcom,apm-halt-clk-delay: The APM controller halt clock delay counter value that SW needs to program one time before starting the APM HW controller - for msmtitanium target. + for msm8953 target. - qcom,apm-resume-clk-delay: The APM controller resume clock delay counter value that SW needs to program one time before starting the APM HW controller - for msmtitanium target. + for msm8953 target. - qcom,apm-sel-switch-delay: The APM controller switch selection delay counter value that SW needs to program one time before starting the APM HW controller - for msmtitanium target. + for msm8953 target. MSM APM Users diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt index 221657780178..8adfeebb1580 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt @@ -99,10 +99,10 @@ First Level Node - FG Gen3 device - qcom,fg-delta-soc-thr Usage: optional Value type: <u32> - Definition: Percentage of monotonic SOC increase upon which the delta - SOC interrupt will be triggered. If this property is not - specified, then the default value will be 1. Possible - values are in the range of 0 to 12. + Definition: Percentage of SOC increase upon which the delta monotonic & + battery SOC interrupts will be triggered. If this property + is not specified, then the default value will be 1. + Possible values are in the range of 0 to 12. - qcom,fg-recharge-soc-thr Usage: optional @@ -156,12 +156,12 @@ First Level Node - FG Gen3 device - qcom,cycle-counter-en Usage: optional - Value type: <bool> + Value type: <empty> Definition: Enables the cycle counter feature. - qcom,fg-force-load-profile Usage: optional - Value type: <bool> + Value type: <empty> Definition: If set, battery profile will be force loaded if the profile loaded earlier by bootloader doesn't match with the profile available in the device tree. @@ -229,13 +229,13 @@ 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: +- qcom,hold-soc-while-full Usage: optional - Value type: <bool> + Value type: <empty> Definition: A boolean property that when defined holds SOC at 100% when the battery is full. -- qcom,ki-coeff-soc-dischg: +- qcom,ki-coeff-soc-dischg Usage: optional Value type: <prop-encoded-array> Definition: Array of monotonic SOC threshold values to change the ki @@ -243,7 +243,7 @@ First Level Node - FG Gen3 device 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: +- qcom,ki-coeff-med-dischg Usage: optional Value type: <prop-encoded-array> Definition: Array of ki coefficient values for medium discharge current @@ -254,7 +254,7 @@ First Level Node - FG Gen3 device 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: +- qcom,ki-coeff-hi-dischg Usage: optional Value type: <prop-encoded-array> Definition: Array of ki coefficient values for high discharge current @@ -311,6 +311,15 @@ First Level Node - FG Gen3 device 148438 (14.84 %) will be used. Lowest possible value is 1954 (0.19 %). +- qcom,fg-auto-recharge-soc + Usage: optional + Value type: <empty> + Definition: A boolean property when defined will configure automatic + recharge SOC threshold. If not specified, automatic + recharge voltage threshold will be configured. This has + to be configured in conjunction with the charger side + configuration for proper functionality. + ========================================================== Second Level Nodes - Peripherals managed by FG Gen3 driver ========================================================== diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt index 0244f910017a..c8f2a5a8e496 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt @@ -52,6 +52,18 @@ Charger specific properties: Value type: <u32> Definition: Specifies the DC input current limit in micro-amps. +- qcom,charger-temp-max-mdegc + Usage: optional + Value type: <u32> + Definition: Specifies the maximum charger temperature in milli-degrees + Celsius. If unspecified a default of 80000 will be used. + +- qcom,connector-temp-max-mdegc + Usage: optional + Value type: <u32> + Definition: Specifies the maximum connector temperature in milli-degrees + Celsius. If unspecified a default value of 105000 will be used. + - io-channels Usage: optional Value type: List of <phandle u32> diff --git a/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt b/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt index d217a4ea9fc8..55154579840a 100644 --- a/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/mem-acc-regulator.txt @@ -1,4 +1,4 @@ -Qualcomm Technologies Memory Accelerator +Qualcomm Technologies, Inc. Memory Accelerator Memory accelerator configures the power-mode (corner) for the accelerator. diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt index e1ebaf636ec3..601903bc60de 100644 --- a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt @@ -1,4 +1,4 @@ -Qualcomm QPNP Regulators +Qualcomm Technologies, Inc. QPNP Regulators qpnp-regulator is a regulator driver which supports regulators inside of PMICs that utilize the MSM SPMI implementation. diff --git a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt index 545cdedeca4c..bb20644afde6 100644 --- a/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt +++ b/Documentation/devicetree/bindings/thermal/qpnp-temp-alarm.txt @@ -1,8 +1,9 @@ -Qualcomm QPNP Temperature Alarm +Qualcomm Technologies, Inc. QPNP Temperature Alarm -QPNP temperature alarm peripherals are found inside of Qualcomm PMIC chips that -utilize the MSM SPMI implementation. These peripherals provide an interrupt -signal and status register to identify high PMIC die temperature. +QPNP temperature alarm peripherals are found inside of Qualcomm Technologies, +Inc. PMIC chips that utilize the MSM SPMI implementation. These peripherals +provide an interrupt signal and status register to identify high PMIC die +temperature. Required properties: - compatible: Must be "qcom,qpnp-temp-alarm". diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 3136687adb57..ddca4c39e2de 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -60,6 +60,7 @@ Optional properties: - snps,num-normal-evt-buffs: If present, specifies number of normal event buffers. Default is 1. - snps,num-gsi-evt-buffs: If present, specifies number of GSI based hardware accelerated event buffers. 1 event buffer is needed per h/w accelerated endpoint. + - xhci-imod-value: Interrupt moderation interval for host mode (in increments of 250nsec). This is usually a subnode to DWC3 glue to which it is connected. @@ -74,4 +75,5 @@ dwc3@4a030000 { tx-fifo-resize; snps,usb3-u1u2-disable; snps,num-gsi-evt-buffs = <0x2>; + xhci-imod-value = <4000>; }; diff --git a/Documentation/devicetree/bindings/usb/qpnp-pdphy.txt b/Documentation/devicetree/bindings/usb/qpnp-pdphy.txt index f3c3163f0a3f..cf0628a26c5a 100644 --- a/Documentation/devicetree/bindings/usb/qpnp-pdphy.txt +++ b/Documentation/devicetree/bindings/usb/qpnp-pdphy.txt @@ -43,6 +43,9 @@ Optional properties: - qcom,vconn-uses-external-source: Indicates whether VCONN supply is sourced from an external regulator. If omitted, then it is assumed it is connected to VBUS. +- qcom,default-sink-caps: List of 32-bit values representing the nominal sink + capabilities in voltage (millivolts) and current + (milliamps) pairs. Example: qcom,qpnp-pdphy@1700 { @@ -64,4 +67,8 @@ Example: "msg-tx-failed", "msg-tx-discarded", "msg-rx-discarded"; + + qcom,default-sink-caps = <5000 3000>, /* 5V @ 3A */ + <9000 3000>, /* 9V @ 3A */ + <12000 2250>; /* 12V @ 2.25A */ }; diff --git a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts index bc18fb54400f..78fdba4fdb9b 100644 --- a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts +++ b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,6 +25,10 @@ status = "disabled"; }; +&msm_ath10k_wlan { + status = "enabled"; +}; + &mdss_mdp { qcom,mdss-pref-prim-intf = "hdmi"; }; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-video.dtsi index f7122d34d8a9..5971a3d1025e 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-video.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,7 +27,7 @@ qcom,mdss-dsi-v-front-porch = <8>; qcom,mdss-dsi-v-pulse-width = <1>; qcom,mdss-dsi-bpp = <24>; - qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-underflow-color = <0x3ff>; qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-panel-hdr-enabled; qcom,mdss-dsi-panel-hdr-color-primaries = <14500 15500 32000 diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi index 89bf222231fb..39d3db3067e6 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi @@ -37,162 +37,162 @@ qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 ff 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1e - 15 01 00 00 10 00 02 0b 73 - 15 01 00 00 10 00 02 0c 73 - 15 01 00 00 10 00 02 0e b0 - 15 01 00 00 10 00 02 0f ae - 15 01 00 00 10 00 02 11 b8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5a 00 - 15 01 00 00 10 00 02 5b 01 - 15 01 00 00 10 00 02 5c 80 - 15 01 00 00 10 00 02 5d 81 - 15 01 00 00 10 00 02 5e 00 - 15 01 00 00 10 00 02 5f 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 ff 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1e + 15 01 00 00 00 00 02 0b 73 + 15 01 00 00 00 00 02 0c 73 + 15 01 00 00 00 00 02 0e b0 + 15 01 00 00 00 00 02 0f ae + 15 01 00 00 00 00 02 11 b8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5a 00 + 15 01 00 00 00 00 02 5b 01 + 15 01 00 00 00 00 02 5c 80 + 15 01 00 00 00 00 02 5d 81 + 15 01 00 00 00 00 02 5e 00 + 15 01 00 00 00 00 02 5f 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1c - 15 01 00 00 10 00 02 01 0b - 15 01 00 00 10 00 02 02 0c - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0f - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8a - 15 01 00 00 10 00 02 0a 13 - 15 01 00 00 10 00 02 0b 13 - 15 01 00 00 10 00 02 0c 15 - 15 01 00 00 10 00 02 0d 15 - 15 01 00 00 10 00 02 0e 17 - 15 01 00 00 10 00 02 0f 17 - 15 01 00 00 10 00 02 10 1c - 15 01 00 00 10 00 02 11 0b - 15 01 00 00 10 00 02 12 0c - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0f - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8a - 15 01 00 00 10 00 02 1a 13 - 15 01 00 00 10 00 02 1b 13 - 15 01 00 00 10 00 02 1c 15 - 15 01 00 00 10 00 02 1d 15 - 15 01 00 00 10 00 02 1e 17 - 15 01 00 00 10 00 02 1f 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1c + 15 01 00 00 00 00 02 01 0b + 15 01 00 00 00 00 02 02 0c + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0f + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8a + 15 01 00 00 00 00 02 0a 13 + 15 01 00 00 00 00 02 0b 13 + 15 01 00 00 00 00 02 0c 15 + 15 01 00 00 00 00 02 0d 15 + 15 01 00 00 00 00 02 0e 17 + 15 01 00 00 00 00 02 0f 17 + 15 01 00 00 00 00 02 10 1c + 15 01 00 00 00 00 02 11 0b + 15 01 00 00 00 00 02 12 0c + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0f + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8a + 15 01 00 00 00 00 02 1a 13 + 15 01 00 00 00 00 02 1b 13 + 15 01 00 00 00 00 02 1c 15 + 15 01 00 00 00 00 02 1d 15 + 15 01 00 00 00 00 02 1e 17 + 15 01 00 00 00 00 02 1f 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6d - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6d + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 e0 00 - 15 01 00 00 10 00 02 dc 21 - 15 01 00 00 10 00 02 dd 22 - 15 01 00 00 10 00 02 de 07 - 15 01 00 00 10 00 02 df 07 - 15 01 00 00 10 00 02 e3 6D - 15 01 00 00 10 00 02 e1 07 - 15 01 00 00 10 00 02 e2 07 + 15 01 00 00 00 00 02 e0 00 + 15 01 00 00 00 00 02 dc 21 + 15 01 00 00 00 00 02 dd 22 + 15 01 00 00 00 00 02 de 07 + 15 01 00 00 00 00 02 df 07 + 15 01 00 00 00 00 02 e3 6D + 15 01 00 00 00 00 02 e1 07 + 15 01 00 00 00 00 02 e2 07 /* UD */ - 15 01 00 00 10 00 02 29 d8 - 15 01 00 00 10 00 02 2a 2a + 15 01 00 00 00 00 02 29 d8 + 15 01 00 00 00 00 02 2a 2a /* CLK */ - 15 01 00 00 10 00 02 4b 03 - 15 01 00 00 10 00 02 4c 11 - 15 01 00 00 10 00 02 4d 10 - 15 01 00 00 10 00 02 4e 01 - 15 01 00 00 10 00 02 4f 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4b 03 + 15 01 00 00 00 00 02 4c 11 + 15 01 00 00 00 00 02 4d 10 + 15 01 00 00 00 00 02 4e 01 + 15 01 00 00 00 00 02 4f 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5b 43 - 15 01 00 00 10 00 02 5c 00 - 15 01 00 00 10 00 02 5f 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5b 43 + 15 01 00 00 00 00 02 5c 00 + 15 01 00 00 00 00 02 5f 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7a 80 - 15 01 00 00 10 00 02 7b 91 - 15 01 00 00 10 00 02 7c D8 - 15 01 00 00 10 00 02 7d 60 - 15 01 00 00 10 00 02 7f 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7a 80 + 15 01 00 00 00 00 02 7b 91 + 15 01 00 00 00 00 02 7c D8 + 15 01 00 00 00 00 02 7d 60 + 15 01 00 00 00 00 02 7f 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 b3 C0 - 15 01 00 00 10 00 02 b4 00 - 15 01 00 00 10 00 02 b5 00 + 15 01 00 00 00 00 02 b3 C0 + 15 01 00 00 00 00 02 b4 00 + 15 01 00 00 00 00 02 b5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0a - 15 01 00 00 10 00 02 94 0a + 15 01 00 00 00 00 02 93 0a + 15 01 00 00 00 00 02 94 0a /* Inversion Type */ - 15 01 00 00 10 00 02 8a 00 - 15 01 00 00 10 00 02 9b ff + 15 01 00 00 00 00 02 8a 00 + 15 01 00 00 00 00 02 9b ff /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9d b0 - 15 01 00 00 10 00 02 9f 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9d b0 + 15 01 00 00 00 00 02 9f 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 ec 00 + 15 01 00 00 00 00 02 ec 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VESA DSC PPS settings(1440x2560 slide 16H) */ - 39 01 00 00 10 00 11 c1 09 20 00 10 02 00 02 68 + 39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68 01 bb 00 0a 06 67 04 c5 - 39 01 00 00 10 00 03 c2 10 f0 + 39 01 00 00 00 00 03 c2 10 f0 /* C0h = 0x0(2 Port SDC)0x01(1 PortA FBC) * 0x02(MTK) 0x03(1 PortA VESA) */ - 15 01 00 00 10 00 02 c0 03 + 15 01 00 00 00 00 02 c0 03 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3b 03 0a 0a + 15 01 00 00 00 00 04 3b 03 0a 0a /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 e5 01 + 15 01 00 00 00 00 02 e5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 bb 10 + 15 01 00 00 00 00 02 bb 10 /* Non Reload MTP */ - 15 01 00 00 10 00 02 fb 01 + 15 01 00 00 00 00 02 fb 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi index ca2ff6eb4924..353b3b2b09bd 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,162 +32,162 @@ qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 ff 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1e - 15 01 00 00 10 00 02 0b 73 - 15 01 00 00 10 00 02 0c 73 - 15 01 00 00 10 00 02 0e b0 - 15 01 00 00 10 00 02 0f aE - 15 01 00 00 10 00 02 11 b8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5a 00 - 15 01 00 00 10 00 02 5b 01 - 15 01 00 00 10 00 02 5c 80 - 15 01 00 00 10 00 02 5d 81 - 15 01 00 00 10 00 02 5e 00 - 15 01 00 00 10 00 02 5f 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 ff 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1e + 15 01 00 00 00 00 02 0b 73 + 15 01 00 00 00 00 02 0c 73 + 15 01 00 00 00 00 02 0e b0 + 15 01 00 00 00 00 02 0f aE + 15 01 00 00 00 00 02 11 b8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5a 00 + 15 01 00 00 00 00 02 5b 01 + 15 01 00 00 00 00 02 5c 80 + 15 01 00 00 00 00 02 5d 81 + 15 01 00 00 00 00 02 5e 00 + 15 01 00 00 00 00 02 5f 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1c - 15 01 00 00 10 00 02 01 0b - 15 01 00 00 10 00 02 02 0c - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0f - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8a - 15 01 00 00 10 00 02 0a 13 - 15 01 00 00 10 00 02 0b 13 - 15 01 00 00 10 00 02 0c 15 - 15 01 00 00 10 00 02 0d 15 - 15 01 00 00 10 00 02 0e 17 - 15 01 00 00 10 00 02 0f 17 - 15 01 00 00 10 00 02 10 1c - 15 01 00 00 10 00 02 11 0b - 15 01 00 00 10 00 02 12 0c - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0f - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8a - 15 01 00 00 10 00 02 1a 13 - 15 01 00 00 10 00 02 1b 13 - 15 01 00 00 10 00 02 1c 15 - 15 01 00 00 10 00 02 1d 15 - 15 01 00 00 10 00 02 1e 17 - 15 01 00 00 10 00 02 1f 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1c + 15 01 00 00 00 00 02 01 0b + 15 01 00 00 00 00 02 02 0c + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0f + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8a + 15 01 00 00 00 00 02 0a 13 + 15 01 00 00 00 00 02 0b 13 + 15 01 00 00 00 00 02 0c 15 + 15 01 00 00 00 00 02 0d 15 + 15 01 00 00 00 00 02 0e 17 + 15 01 00 00 00 00 02 0f 17 + 15 01 00 00 00 00 02 10 1c + 15 01 00 00 00 00 02 11 0b + 15 01 00 00 00 00 02 12 0c + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0f + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8a + 15 01 00 00 00 00 02 1a 13 + 15 01 00 00 00 00 02 1b 13 + 15 01 00 00 00 00 02 1c 15 + 15 01 00 00 00 00 02 1d 15 + 15 01 00 00 00 00 02 1e 17 + 15 01 00 00 00 00 02 1f 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6d - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6d + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 e0 00 - 15 01 00 00 10 00 02 dc 21 - 15 01 00 00 10 00 02 dd 22 - 15 01 00 00 10 00 02 de 07 - 15 01 00 00 10 00 02 df 07 - 15 01 00 00 10 00 02 e3 6d - 15 01 00 00 10 00 02 e1 07 - 15 01 00 00 10 00 02 e2 07 + 15 01 00 00 00 00 02 e0 00 + 15 01 00 00 00 00 02 dc 21 + 15 01 00 00 00 00 02 dd 22 + 15 01 00 00 00 00 02 de 07 + 15 01 00 00 00 00 02 df 07 + 15 01 00 00 00 00 02 e3 6d + 15 01 00 00 00 00 02 e1 07 + 15 01 00 00 00 00 02 e2 07 /* UD */ - 15 01 00 00 10 00 02 29 d8 - 15 01 00 00 10 00 02 2a 2a + 15 01 00 00 00 00 02 29 d8 + 15 01 00 00 00 00 02 2a 2a /* CLK */ - 15 01 00 00 10 00 02 4b 03 - 15 01 00 00 10 00 02 4c 11 - 15 01 00 00 10 00 02 4d 10 - 15 01 00 00 10 00 02 4e 01 - 15 01 00 00 10 00 02 4f 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4b 03 + 15 01 00 00 00 00 02 4c 11 + 15 01 00 00 00 00 02 4d 10 + 15 01 00 00 00 00 02 4e 01 + 15 01 00 00 00 00 02 4f 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5b 43 - 15 01 00 00 10 00 02 5c 00 - 15 01 00 00 10 00 02 5f 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5b 43 + 15 01 00 00 00 00 02 5c 00 + 15 01 00 00 00 00 02 5f 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7a 80 - 15 01 00 00 10 00 02 7b 91 - 15 01 00 00 10 00 02 7c d8 - 15 01 00 00 10 00 02 7d 60 - 15 01 00 00 10 00 02 7f 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7a 80 + 15 01 00 00 00 00 02 7b 91 + 15 01 00 00 00 00 02 7c d8 + 15 01 00 00 00 00 02 7d 60 + 15 01 00 00 00 00 02 7f 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 b3 c0 - 15 01 00 00 10 00 02 b4 00 - 15 01 00 00 10 00 02 b5 00 + 15 01 00 00 00 00 02 b3 c0 + 15 01 00 00 00 00 02 b4 00 + 15 01 00 00 00 00 02 b5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0a - 15 01 00 00 10 00 02 94 0a + 15 01 00 00 00 00 02 93 0a + 15 01 00 00 00 00 02 94 0a /* Inversion Type */ - 15 01 00 00 10 00 02 8a 00 - 15 01 00 00 10 00 02 9b ff + 15 01 00 00 00 00 02 8a 00 + 15 01 00 00 00 00 02 9b ff /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9d b0 - 15 01 00 00 10 00 02 9f 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9d b0 + 15 01 00 00 00 00 02 9f 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 ec 00 + 15 01 00 00 00 00 02 ec 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VESA DSC PPS settings(1440x2560 slide 16H) */ - 39 01 00 00 10 00 11 c1 09 20 00 10 02 00 02 68 01 + 39 01 00 00 00 00 11 c1 09 20 00 10 02 00 02 68 01 bb 00 0a 06 67 04 c5 - 39 01 00 00 10 00 03 c2 10 f0 + 39 01 00 00 00 00 03 c2 10 f0 /* C0h = 0x00(2 Port SDC); 0x01(1 PortA FBC); * 0x02(MTK); 0x03(1 PortA VESA) */ - 15 01 00 00 10 00 02 c0 03 + 15 01 00 00 00 00 02 c0 03 /* VBP+VSA=,VFP = 10H */ - 39 01 00 00 10 00 04 3b 03 0a 0a + 39 01 00 00 00 00 04 3b 03 0a 0a /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 e5 01 + 15 01 00 00 00 00 02 e5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 bb 03 + 15 01 00 00 00 00 02 bb 03 /* Non Reload MTP */ - 15 01 00 00 10 00 02 fb 01 + 15 01 00 00 00 00 02 fb 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi index 28b0d6d9cf14..6ff016676de7 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -61,154 +61,154 @@ qcom,ulps-enabled; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 FF 20 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1E - 15 01 00 00 10 00 02 0B 73 - 15 01 00 00 10 00 02 0C 73 - 15 01 00 00 10 00 02 0E B0 - 15 01 00 00 10 00 02 0F AE - 15 01 00 00 10 00 02 11 B8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5A 00 - 15 01 00 00 10 00 02 5B 01 - 15 01 00 00 10 00 02 5C 80 - 15 01 00 00 10 00 02 5D 81 - 15 01 00 00 10 00 02 5E 00 - 15 01 00 00 10 00 02 5F 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 FF 20 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1E + 15 01 00 00 00 00 02 0B 73 + 15 01 00 00 00 00 02 0C 73 + 15 01 00 00 00 00 02 0E B0 + 15 01 00 00 00 00 02 0F AE + 15 01 00 00 00 00 02 11 B8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5A 00 + 15 01 00 00 00 00 02 5B 01 + 15 01 00 00 00 00 02 5C 80 + 15 01 00 00 00 00 02 5D 81 + 15 01 00 00 00 00 02 5E 00 + 15 01 00 00 00 00 02 5F 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 ff 24 - 15 01 00 00 10 00 02 fb 01 - 15 01 00 00 10 00 02 00 1C - 15 01 00 00 10 00 02 01 0B - 15 01 00 00 10 00 02 02 0C - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0F - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8A - 15 01 00 00 10 00 02 0A 13 - 15 01 00 00 10 00 02 0B 13 - 15 01 00 00 10 00 02 0C 15 - 15 01 00 00 10 00 02 0D 15 - 15 01 00 00 10 00 02 0E 17 - 15 01 00 00 10 00 02 0F 17 - 15 01 00 00 10 00 02 10 1C - 15 01 00 00 10 00 02 11 0B - 15 01 00 00 10 00 02 12 0C - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0F - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8A - 15 01 00 00 10 00 02 1A 13 - 15 01 00 00 10 00 02 1B 13 - 15 01 00 00 10 00 02 1C 15 - 15 01 00 00 10 00 02 1D 15 - 15 01 00 00 10 00 02 1E 17 - 15 01 00 00 10 00 02 1F 17 + 15 01 00 00 00 00 02 ff 24 + 15 01 00 00 00 00 02 fb 01 + 15 01 00 00 00 00 02 00 1C + 15 01 00 00 00 00 02 01 0B + 15 01 00 00 00 00 02 02 0C + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0F + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8A + 15 01 00 00 00 00 02 0A 13 + 15 01 00 00 00 00 02 0B 13 + 15 01 00 00 00 00 02 0C 15 + 15 01 00 00 00 00 02 0D 15 + 15 01 00 00 00 00 02 0E 17 + 15 01 00 00 00 00 02 0F 17 + 15 01 00 00 00 00 02 10 1C + 15 01 00 00 00 00 02 11 0B + 15 01 00 00 00 00 02 12 0C + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0F + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8A + 15 01 00 00 00 00 02 1A 13 + 15 01 00 00 00 00 02 1B 13 + 15 01 00 00 00 00 02 1C 15 + 15 01 00 00 00 00 02 1D 15 + 15 01 00 00 00 00 02 1E 17 + 15 01 00 00 00 00 02 1F 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6D - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6D + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 E0 00 - 15 01 00 00 10 00 02 DC 21 - 15 01 00 00 10 00 02 DD 22 - 15 01 00 00 10 00 02 DE 07 - 15 01 00 00 10 00 02 DF 07 - 15 01 00 00 10 00 02 E3 6D - 15 01 00 00 10 00 02 E1 07 - 15 01 00 00 10 00 02 E2 07 + 15 01 00 00 00 00 02 E0 00 + 15 01 00 00 00 00 02 DC 21 + 15 01 00 00 00 00 02 DD 22 + 15 01 00 00 00 00 02 DE 07 + 15 01 00 00 00 00 02 DF 07 + 15 01 00 00 00 00 02 E3 6D + 15 01 00 00 00 00 02 E1 07 + 15 01 00 00 00 00 02 E2 07 /* UD */ - 15 01 00 00 10 00 02 29 D8 - 15 01 00 00 10 00 02 2A 2A + 15 01 00 00 00 00 02 29 D8 + 15 01 00 00 00 00 02 2A 2A /* CLK */ - 15 01 00 00 10 00 02 4B 03 - 15 01 00 00 10 00 02 4C 11 - 15 01 00 00 10 00 02 4D 10 - 15 01 00 00 10 00 02 4E 01 - 15 01 00 00 10 00 02 4F 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4B 03 + 15 01 00 00 00 00 02 4C 11 + 15 01 00 00 00 00 02 4D 10 + 15 01 00 00 00 00 02 4E 01 + 15 01 00 00 00 00 02 4F 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5B 43 - 15 01 00 00 10 00 02 5C 00 - 15 01 00 00 10 00 02 5F 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5B 43 + 15 01 00 00 00 00 02 5C 00 + 15 01 00 00 00 00 02 5F 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7A 80 - 15 01 00 00 10 00 02 7B 91 - 15 01 00 00 10 00 02 7C D8 - 15 01 00 00 10 00 02 7D 60 - 15 01 00 00 10 00 02 7F 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7A 80 + 15 01 00 00 00 00 02 7B 91 + 15 01 00 00 00 00 02 7C D8 + 15 01 00 00 00 00 02 7D 60 + 15 01 00 00 00 00 02 7F 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 B3 C0 - 15 01 00 00 10 00 02 B4 00 - 15 01 00 00 10 00 02 B5 00 + 15 01 00 00 00 00 02 B3 C0 + 15 01 00 00 00 00 02 B4 00 + 15 01 00 00 00 00 02 B5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0A - 15 01 00 00 10 00 02 94 0A + 15 01 00 00 00 00 02 93 0A + 15 01 00 00 00 00 02 94 0A /* Inversion Type */ - 15 01 00 00 10 00 02 8A 00 - 15 01 00 00 10 00 02 9B FF + 15 01 00 00 00 00 02 8A 00 + 15 01 00 00 00 00 02 9B FF /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9D B0 - 15 01 00 00 10 00 02 9F 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9D B0 + 15 01 00 00 00 00 02 9F 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 EC 00 + 15 01 00 00 00 00 02 EC 00 /* CMD1 */ - 15 01 00 00 10 00 02 ff 10 + 15 01 00 00 00 00 02 ff 10 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3B 03 0A 0A + 15 01 00 00 00 00 04 3B 03 0A 0A /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 E5 01 + 15 01 00 00 00 00 02 E5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 BB 10 + 15 01 00 00 00 00 02 BB 10 /* Non Reload MTP */ - 15 01 00 00 10 00 02 FB 01 + 15 01 00 00 00 00 02 FB 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi index f2f77e3ed9cb..d179acd043ed 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi @@ -28,158 +28,158 @@ qcom,mdss-dsi-v-front-porch = <8>; qcom,mdss-dsi-v-pulse-width = <1>; qcom,mdss-dsi-bpp = <24>; - qcom,mdss-dsi-underflow-color = <0xff>; + qcom,mdss-dsi-underflow-color = <0x3ff>; qcom,mdss-dsi-border-color = <0>; qcom,mdss-dsi-on-command = [ /* CMD2_P0 */ - 15 01 00 00 10 00 02 FF 20 - 15 01 00 00 10 00 02 FB 01 - 15 01 00 00 10 00 02 00 01 - 15 01 00 00 10 00 02 01 55 - 15 01 00 00 10 00 02 02 45 - 15 01 00 00 10 00 02 05 40 - 15 01 00 00 10 00 02 06 19 - 15 01 00 00 10 00 02 07 1E - 15 01 00 00 10 00 02 0B 73 - 15 01 00 00 10 00 02 0C 73 - 15 01 00 00 10 00 02 0E B0 - 15 01 00 00 10 00 02 0F AE - 15 01 00 00 10 00 02 11 B8 - 15 01 00 00 10 00 02 13 00 - 15 01 00 00 10 00 02 58 80 - 15 01 00 00 10 00 02 59 01 - 15 01 00 00 10 00 02 5A 00 - 15 01 00 00 10 00 02 5B 01 - 15 01 00 00 10 00 02 5C 80 - 15 01 00 00 10 00 02 5D 81 - 15 01 00 00 10 00 02 5E 00 - 15 01 00 00 10 00 02 5F 01 - 15 01 00 00 10 00 02 72 31 - 15 01 00 00 10 00 02 68 03 + 15 01 00 00 00 00 02 FF 20 + 15 01 00 00 00 00 02 FB 01 + 15 01 00 00 00 00 02 00 01 + 15 01 00 00 00 00 02 01 55 + 15 01 00 00 00 00 02 02 45 + 15 01 00 00 00 00 02 05 40 + 15 01 00 00 00 00 02 06 19 + 15 01 00 00 00 00 02 07 1E + 15 01 00 00 00 00 02 0B 73 + 15 01 00 00 00 00 02 0C 73 + 15 01 00 00 00 00 02 0E B0 + 15 01 00 00 00 00 02 0F AE + 15 01 00 00 00 00 02 11 B8 + 15 01 00 00 00 00 02 13 00 + 15 01 00 00 00 00 02 58 80 + 15 01 00 00 00 00 02 59 01 + 15 01 00 00 00 00 02 5A 00 + 15 01 00 00 00 00 02 5B 01 + 15 01 00 00 00 00 02 5C 80 + 15 01 00 00 00 00 02 5D 81 + 15 01 00 00 00 00 02 5E 00 + 15 01 00 00 00 00 02 5F 01 + 15 01 00 00 00 00 02 72 31 + 15 01 00 00 00 00 02 68 03 /* CMD2_P4 */ - 15 01 00 00 10 00 02 FF 24 - 15 01 00 00 10 00 02 FB 01 - 15 01 00 00 10 00 02 00 1C - 15 01 00 00 10 00 02 01 0B - 15 01 00 00 10 00 02 02 0C - 15 01 00 00 10 00 02 03 01 - 15 01 00 00 10 00 02 04 0F - 15 01 00 00 10 00 02 05 10 - 15 01 00 00 10 00 02 06 10 - 15 01 00 00 10 00 02 07 10 - 15 01 00 00 10 00 02 08 89 - 15 01 00 00 10 00 02 09 8A - 15 01 00 00 10 00 02 0A 13 - 15 01 00 00 10 00 02 0B 13 - 15 01 00 00 10 00 02 0C 15 - 15 01 00 00 10 00 02 0D 15 - 15 01 00 00 10 00 02 0E 17 - 15 01 00 00 10 00 02 0F 17 - 15 01 00 00 10 00 02 10 1C - 15 01 00 00 10 00 02 11 0B - 15 01 00 00 10 00 02 12 0C - 15 01 00 00 10 00 02 13 01 - 15 01 00 00 10 00 02 14 0F - 15 01 00 00 10 00 02 15 10 - 15 01 00 00 10 00 02 16 10 - 15 01 00 00 10 00 02 17 10 - 15 01 00 00 10 00 02 18 89 - 15 01 00 00 10 00 02 19 8A - 15 01 00 00 10 00 02 1A 13 - 15 01 00 00 10 00 02 1B 13 - 15 01 00 00 10 00 02 1C 15 - 15 01 00 00 10 00 02 1D 15 - 15 01 00 00 10 00 02 1E 17 - 15 01 00 00 10 00 02 1F 17 + 15 01 00 00 00 00 02 FF 24 + 15 01 00 00 00 00 02 FB 01 + 15 01 00 00 00 00 02 00 1C + 15 01 00 00 00 00 02 01 0B + 15 01 00 00 00 00 02 02 0C + 15 01 00 00 00 00 02 03 01 + 15 01 00 00 00 00 02 04 0F + 15 01 00 00 00 00 02 05 10 + 15 01 00 00 00 00 02 06 10 + 15 01 00 00 00 00 02 07 10 + 15 01 00 00 00 00 02 08 89 + 15 01 00 00 00 00 02 09 8A + 15 01 00 00 00 00 02 0A 13 + 15 01 00 00 00 00 02 0B 13 + 15 01 00 00 00 00 02 0C 15 + 15 01 00 00 00 00 02 0D 15 + 15 01 00 00 00 00 02 0E 17 + 15 01 00 00 00 00 02 0F 17 + 15 01 00 00 00 00 02 10 1C + 15 01 00 00 00 00 02 11 0B + 15 01 00 00 00 00 02 12 0C + 15 01 00 00 00 00 02 13 01 + 15 01 00 00 00 00 02 14 0F + 15 01 00 00 00 00 02 15 10 + 15 01 00 00 00 00 02 16 10 + 15 01 00 00 00 00 02 17 10 + 15 01 00 00 00 00 02 18 89 + 15 01 00 00 00 00 02 19 8A + 15 01 00 00 00 00 02 1A 13 + 15 01 00 00 00 00 02 1B 13 + 15 01 00 00 00 00 02 1C 15 + 15 01 00 00 00 00 02 1D 15 + 15 01 00 00 00 00 02 1E 17 + 15 01 00 00 00 00 02 1F 17 /* STV */ - 15 01 00 00 10 00 02 20 40 - 15 01 00 00 10 00 02 21 01 - 15 01 00 00 10 00 02 22 00 - 15 01 00 00 10 00 02 23 40 - 15 01 00 00 10 00 02 24 40 - 15 01 00 00 10 00 02 25 6D - 15 01 00 00 10 00 02 26 40 - 15 01 00 00 10 00 02 27 40 + 15 01 00 00 00 00 02 20 40 + 15 01 00 00 00 00 02 21 01 + 15 01 00 00 00 00 02 22 00 + 15 01 00 00 00 00 02 23 40 + 15 01 00 00 00 00 02 24 40 + 15 01 00 00 00 00 02 25 6D + 15 01 00 00 00 00 02 26 40 + 15 01 00 00 00 00 02 27 40 /* Vend */ - 15 01 00 00 10 00 02 E0 00 - 15 01 00 00 10 00 02 DC 21 - 15 01 00 00 10 00 02 DD 22 - 15 01 00 00 10 00 02 DE 07 - 15 01 00 00 10 00 02 DF 07 - 15 01 00 00 10 00 02 E3 6D - 15 01 00 00 10 00 02 E1 07 - 15 01 00 00 10 00 02 E2 07 + 15 01 00 00 00 00 02 E0 00 + 15 01 00 00 00 00 02 DC 21 + 15 01 00 00 00 00 02 DD 22 + 15 01 00 00 00 00 02 DE 07 + 15 01 00 00 00 00 02 DF 07 + 15 01 00 00 00 00 02 E3 6D + 15 01 00 00 00 00 02 E1 07 + 15 01 00 00 00 00 02 E2 07 /* UD */ - 15 01 00 00 10 00 02 29 D8 - 15 01 00 00 10 00 02 2A 2A + 15 01 00 00 00 00 02 29 D8 + 15 01 00 00 00 00 02 2A 2A /* CLK */ - 15 01 00 00 10 00 02 4B 03 - 15 01 00 00 10 00 02 4C 11 - 15 01 00 00 10 00 02 4D 10 - 15 01 00 00 10 00 02 4E 01 - 15 01 00 00 10 00 02 4F 01 - 15 01 00 00 10 00 02 50 10 - 15 01 00 00 10 00 02 51 00 - 15 01 00 00 10 00 02 52 80 - 15 01 00 00 10 00 02 53 00 - 15 01 00 00 10 00 02 56 00 - 15 01 00 00 10 00 02 54 07 - 15 01 00 00 10 00 02 58 07 - 15 01 00 00 10 00 02 55 25 + 15 01 00 00 00 00 02 4B 03 + 15 01 00 00 00 00 02 4C 11 + 15 01 00 00 00 00 02 4D 10 + 15 01 00 00 00 00 02 4E 01 + 15 01 00 00 00 00 02 4F 01 + 15 01 00 00 00 00 02 50 10 + 15 01 00 00 00 00 02 51 00 + 15 01 00 00 00 00 02 52 80 + 15 01 00 00 00 00 02 53 00 + 15 01 00 00 00 00 02 56 00 + 15 01 00 00 00 00 02 54 07 + 15 01 00 00 00 00 02 58 07 + 15 01 00 00 00 00 02 55 25 /* Reset XDONB */ - 15 01 00 00 10 00 02 5B 43 - 15 01 00 00 10 00 02 5C 00 - 15 01 00 00 10 00 02 5F 73 - 15 01 00 00 10 00 02 60 73 - 15 01 00 00 10 00 02 63 22 - 15 01 00 00 10 00 02 64 00 - 15 01 00 00 10 00 02 67 08 - 15 01 00 00 10 00 02 68 04 + 15 01 00 00 00 00 02 5B 43 + 15 01 00 00 00 00 02 5C 00 + 15 01 00 00 00 00 02 5F 73 + 15 01 00 00 00 00 02 60 73 + 15 01 00 00 00 00 02 63 22 + 15 01 00 00 00 00 02 64 00 + 15 01 00 00 00 00 02 67 08 + 15 01 00 00 00 00 02 68 04 /* Resolution:1440x2560*/ - 15 01 00 00 10 00 02 72 02 + 15 01 00 00 00 00 02 72 02 /* mux */ - 15 01 00 00 10 00 02 7A 80 - 15 01 00 00 10 00 02 7B 91 - 15 01 00 00 10 00 02 7C D8 - 15 01 00 00 10 00 02 7D 60 - 15 01 00 00 10 00 02 7F 15 - 15 01 00 00 10 00 02 75 15 + 15 01 00 00 00 00 02 7A 80 + 15 01 00 00 00 00 02 7B 91 + 15 01 00 00 00 00 02 7C D8 + 15 01 00 00 00 00 02 7D 60 + 15 01 00 00 00 00 02 7F 15 + 15 01 00 00 00 00 02 75 15 /* ABOFF */ - 15 01 00 00 10 00 02 B3 C0 - 15 01 00 00 10 00 02 B4 00 - 15 01 00 00 10 00 02 B5 00 + 15 01 00 00 00 00 02 B3 C0 + 15 01 00 00 00 00 02 B4 00 + 15 01 00 00 00 00 02 B5 00 /* Source EQ */ - 15 01 00 00 10 00 02 78 00 - 15 01 00 00 10 00 02 79 00 - 15 01 00 00 10 00 02 80 00 - 15 01 00 00 10 00 02 83 00 + 15 01 00 00 00 00 02 78 00 + 15 01 00 00 00 00 02 79 00 + 15 01 00 00 00 00 02 80 00 + 15 01 00 00 00 00 02 83 00 /* FP BP */ - 15 01 00 00 10 00 02 93 0A - 15 01 00 00 10 00 02 94 0A + 15 01 00 00 00 00 02 93 0A + 15 01 00 00 00 00 02 94 0A /* Inversion Type */ - 15 01 00 00 10 00 02 8A 00 - 15 01 00 00 10 00 02 9B FF + 15 01 00 00 00 00 02 8A 00 + 15 01 00 00 00 00 02 9B FF /* IMGSWAP =1 @PortSwap=1 */ - 15 01 00 00 10 00 02 9D B0 - 15 01 00 00 10 00 02 9F 63 - 15 01 00 00 10 00 02 98 10 + 15 01 00 00 00 00 02 9D B0 + 15 01 00 00 00 00 02 9F 63 + 15 01 00 00 00 00 02 98 10 /* FRM */ - 15 01 00 00 10 00 02 EC 00 + 15 01 00 00 00 00 02 EC 00 /* CMD1 */ - 15 01 00 00 10 00 02 FF 10 + 15 01 00 00 00 00 02 FF 10 /* VBP+VSA=,VFP = 10H */ - 15 01 00 00 10 00 04 3B 03 0A 0A + 15 01 00 00 00 00 04 3B 03 0A 0A /* FTE on */ - 15 01 00 00 10 00 02 35 00 + 15 01 00 00 00 00 02 35 00 /* EN_BK =1(auto black) */ - 15 01 00 00 10 00 02 E5 01 + 15 01 00 00 00 00 02 E5 01 /* CMD mode(10) VDO mode(03) */ - 15 01 00 00 10 00 02 BB 03 + 15 01 00 00 00 00 02 BB 03 /* Non Reload MTP */ - 15 01 00 00 10 00 02 FB 01 + 15 01 00 00 00 00 02 FB 01 /* SlpOut + DispOn */ - 05 01 00 00 a0 00 02 11 00 - 05 01 00 00 a0 00 02 29 00 + 05 01 00 00 78 00 02 11 00 + 05 01 00 00 78 00 02 29 00 ]; qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00 05 01 00 00 78 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi index 3c0134b665fc..e3f60de3c3eb 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-cmd.dtsi @@ -20,13 +20,13 @@ qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-panel-width = <1080>; qcom,mdss-dsi-panel-height = <1920>; - qcom,mdss-dsi-h-front-porch = <96>; - qcom,mdss-dsi-h-back-porch = <64>; - qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-front-porch = <120>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; qcom,mdss-dsi-h-sync-skew = <0>; - qcom,mdss-dsi-v-back-porch = <16>; - qcom,mdss-dsi-v-front-porch = <4>; - qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-v-back-porch = <2>; + qcom,mdss-dsi-v-front-porch = <12>; + qcom,mdss-dsi-v-pulse-width = <2>; qcom,mdss-dsi-h-left-border = <0>; qcom,mdss-dsi-h-right-border = <0>; qcom,mdss-dsi-v-top-border = <0>; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi index d6b24f4e54d2..068459bf2504 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35695b-truly-fhd-video.dtsi @@ -20,13 +20,13 @@ qcom,mdss-dsi-stream = <0>; qcom,mdss-dsi-panel-width = <1080>; qcom,mdss-dsi-panel-height = <1920>; - qcom,mdss-dsi-h-front-porch = <96>; - qcom,mdss-dsi-h-back-porch = <64>; - qcom,mdss-dsi-h-pulse-width = <16>; + qcom,mdss-dsi-h-front-porch = <120>; + qcom,mdss-dsi-h-back-porch = <60>; + qcom,mdss-dsi-h-pulse-width = <12>; qcom,mdss-dsi-h-sync-skew = <0>; - qcom,mdss-dsi-v-back-porch = <16>; - qcom,mdss-dsi-v-front-porch = <4>; - qcom,mdss-dsi-v-pulse-width = <1>; + qcom,mdss-dsi-v-back-porch = <2>; + qcom,mdss-dsi-v-front-porch = <12>; + qcom,mdss-dsi-v-pulse-width = <2>; qcom,mdss-dsi-h-left-border = <0>; qcom,mdss-dsi-h-right-border = <0>; qcom,mdss-dsi-v-top-border = <0>; @@ -169,8 +169,7 @@ 15 01 00 00 00 00 02 e3 00 15 01 00 00 00 00 02 ec 00 15 01 00 00 00 00 02 ff 10 - 15 01 00 00 00 00 02 bb 10 - 15 01 00 00 00 00 02 35 02 + 15 01 00 00 00 00 02 bb 03 05 01 00 00 78 00 02 11 00 05 01 00 00 78 00 02 29 00]; qcom,mdss-dsi-off-command = [05 01 00 00 14 00 02 28 00 diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi index e8e773a33622..1154c28bb9ea 100644 --- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi @@ -497,6 +497,7 @@ #address-cells = <1>; #size-cells = <0>; #io-channel-cells = <1>; + qcom,pmic-revid = <&pm660_revid>; }; pm660_fg: qpnp,fg { @@ -517,8 +518,10 @@ reg = <0x4000 0x100>; interrupts = <0x0 0x40 0x0 IRQ_TYPE_EDGE_BOTH>, <0x0 0x40 0x1 IRQ_TYPE_EDGE_BOTH>, - <0x0 0x40 0x2 IRQ_TYPE_EDGE_BOTH>, - <0x0 0x40 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x0 0x40 0x2 + IRQ_TYPE_EDGE_RISING>, + <0x0 0x40 0x3 + IRQ_TYPE_EDGE_RISING>, <0x0 0x40 0x4 IRQ_TYPE_EDGE_BOTH>, <0x0 0x40 0x5 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi index be47b6483288..72f9f9ea9b2d 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi @@ -290,6 +290,10 @@ "msg-tx-failed", "msg-tx-discarded", "msg-rx-discarded"; + + qcom,default-sink-caps = <5000 3000>, /* 5V @ 3A */ + <9000 3000>, /* 9V @ 3A */ + <12000 2250>; /* 12V @ 2.25A */ }; bcl@4200 { @@ -333,8 +337,10 @@ reg = <0x4000 0x100>; interrupts = <0x2 0x40 0x0 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x1 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x40 0x2 IRQ_TYPE_EDGE_BOTH>, - <0x2 0x40 0x3 IRQ_TYPE_EDGE_BOTH>, + <0x2 0x40 0x2 + IRQ_TYPE_EDGE_RISING>, + <0x2 0x40 0x3 + IRQ_TYPE_EDGE_RISING>, <0x2 0x40 0x4 IRQ_TYPE_EDGE_BOTH>, <0x2 0x40 0x5 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi index e6e04f19d7ea..138fa2b57248 100644 --- a/arch/arm/boot/dts/qcom/msm-smb138x.dtsi +++ b/arch/arm/boot/dts/qcom/msm-smb138x.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -57,8 +57,8 @@ die_temp@2 { reg = <2>; - qcom,scale = <(-1032)>; - qcom,offset = <344125>; + qcom,scale = <(-1306)>; + qcom,offset = <397904>; }; batt_i@3 { @@ -96,16 +96,24 @@ #size-cells = <1>; interrupt-parent = <&smb138x>; io-channels = <&smb138x_tadc 2>, - <&smb138x_tadc 12>, - <&smb138x_tadc 3>; + <&smb138x_tadc 3>, + <&smb138x_tadc 14>, + <&smb138x_tadc 15>, + <&smb138x_tadc 16>, + <&smb138x_tadc 17>; io-channel-names = "charger_temp", - "charger_temp_max", - "batt_i"; + "batt_i", + "connector_temp_thr1", + "connector_temp_thr2", + "connector_temp_thr3", + "charger_temp_max"; qcom,chgr-misc@1600 { reg = <0x1600 0x100>; - interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "wdog-bark"; + interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>, + <0x16 0x6 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "wdog-bark", + "temperature-change"; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi index 3ed55f9d8671..5ac31e3dd0cb 100644 --- a/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-vidc.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,6 +32,7 @@ <0x0818C000 0x2000>, <0x0818E000 0x2000>; qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,firmware-name = "venus"; qcom,imem-size = <524288>; /* 512 kB */ qcom,never-unload-fw; diff --git a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi index f8dae210bc4e..c35ea886408d 100644 --- a/arch/arm/boot/dts/qcom/msm8998-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-camera.dtsi @@ -51,8 +51,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -86,8 +86,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -121,8 +121,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -159,7 +159,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -197,7 +197,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -235,7 +235,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; @@ -273,7 +273,7 @@ "ispif_ahb_clk", "csi_src_clk", "csiphy_clk_src", "csi_clk", "csi_ahb_clk", "csi_rdi_clk", "csi_pix_clk", "cphy_csid_clk"; - qcom,clock-rates = <0 0 0 0 0 0 0 256000000 256000000 + qcom,clock-rates = <0 0 0 0 0 0 0 274290000 274290000 0 0 0 0 0>; status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi index 845c96eb5ef4..7dfcd34c2743 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mdss.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,7 @@ interrupt-controller; #interrupt-cells = <1>; vdd-supply = <&gdsc_mdss>; + gdsc-core-supply = <&gdsc_bimc_smmu>; /* Bus Scale Settings */ qcom,msm-bus,name = "mdss_mdp"; @@ -126,7 +127,7 @@ <0x012ac 0xc0000ccc>, <0x012b4 0xc0000ccc>, <0x012bc 0x00cccccc>, - <0x012c4 0x000000cc>, + <0x012c4 0x0000cccc>, <0x013a8 0x0cccc0c0>, <0x013b0 0xccccc0c0>, <0x013b8 0xcccc0000>, @@ -500,6 +501,9 @@ qcom,msm_ext_disp = <&msm_ext_disp>; + qcom,aux-cfg-settings = [00 13 00 10 0a 26 0a 03 8b 03]; + qcom,logical2physical-lane-map = [02 03 01 00]; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi index 4aadd4802b51..236020385e1c 100644 --- a/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-mtp.dtsi @@ -171,6 +171,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &i2c_5 { status = "okay"; synaptics@20 { diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi index 25e381c2cb18..3c1c49edcc82 100644 --- a/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-qrd-vr1.dtsi @@ -143,6 +143,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &soc { gpio_keys { compatible = "gpio-keys"; diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi index fb69a793a680..38072e447fba 100644 --- a/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-qrd.dtsi @@ -159,6 +159,19 @@ }; }; +&pmi8998_gpios { + /* GPIO 6 for the internal QNOVO discharge FET control signal */ + gpio@c500 { + status = "okay"; + qcom,mode = <1>; + qcom,pull = <5>; + qcom,vin-sel = <0>; + qcom,src-sel = <2>; + qcom,out-strength = <1>; + qcom,master-en = <1>; + }; +}; + &i2c_5 { status = "okay"; synaptics@20 { diff --git a/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi index fdc452a47a46..93da11e66799 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2-camera.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,8 +42,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -77,8 +77,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; @@ -112,8 +112,8 @@ "csi_src_clk", "csi_clk", "cphy_csid_clk", "csiphy_timer_src_clk", "csiphy_timer_clk", "camss_ispif_ahb_clk", "csiphy_clk_src", "csiphy_clk"; - qcom,clock-rates = <0 0 0 0 0 0 256000000 0 0 200000000 0 - 0 256000000 0>; + qcom,clock-rates = <0 0 0 0 0 0 274290000 0 0 200000000 0 + 0 274290000 0>; status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi index 1d8fe225c9af..b6ddd549efe5 100644 --- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi @@ -44,6 +44,7 @@ qcom,acdextint0-val = <0x2cf9ae8 0x2cf9ae8>; qcom,acdextint1-val = <0x2cf9afe 0x2cf9afe>; qcom,acdautoxfer-val = <0x00000015 0x00000015>; + qcom,pwrcl-apcs-mem-acc-threshold-voltage = <852000>; qcom,perfcl-apcs-mem-acc-threshold-voltage = <852000>; qcom,apm-threshold-voltage = <800000>; @@ -452,6 +453,8 @@ qcom,cpr-aging-ref-voltage = <1056000>; qcom,apm-threshold-voltage = <800000>; qcom,apm-hysteresis-voltage = <0>; + qcom,mem-acc-threshold-voltage = <852000>; + qcom,mem-acc-crossover-voltage = <852000>; }; &apc0_pwrcl_vreg { diff --git a/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi b/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi index e449d81a25e5..3e7cacac9d43 100644 --- a/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-vidc.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -39,6 +39,7 @@ qcom,imem-size = <524288>; /* 512 kB */ qcom,max-hw-load = <2563200>; /* Full 4k @ 60 + 1080p @ 60 */ + qcom,power-conf = <8294400>; /* WxH - 3840*2160 */ qcom,load-freq-tbl = /* Encoders */ <972000 465000000 0x55555555>, /* 4k UHD @ 30 */ diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 30679791006b..2e41f3a3567d 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -3041,7 +3041,25 @@ }; - qcom,icnss@18800000 { + msm_ath10k_wlan: qcom,msm_ath10k_wlan@18000000 { + status = "disabled"; + compatible = "qcom,wcn3990-wifi"; + interrupts = + <0 413 0 /* CE0 */ >, + <0 414 0 /* CE1 */ >, + <0 415 0 /* CE2 */ >, + <0 416 0 /* CE3 */ >, + <0 417 0 /* CE4 */ >, + <0 418 0 /* CE5 */ >, + <0 420 0 /* CE6 */ >, + <0 421 0 /* CE7 */ >, + <0 422 0 /* CE8 */ >, + <0 423 0 /* CE9 */ >, + <0 424 0 /* CE10 */ >, + <0 425 0 /* CE11 */ >; + }; + + qcom,icnss@18800000 { compatible = "qcom,icnss"; reg = <0x18800000 0x800000>, <0xa0000000 0x10000000>, diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi index 2232327f1302..af288ff26d06 100644 --- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi @@ -25,6 +25,27 @@ qcom,led-strings-list = [01 02]; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi index b07a9190331b..a47f8419f41a 100644 --- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi @@ -26,6 +26,27 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &mem_client_3_size { qcom,peripheral-size = <0x500000>; }; diff --git a/arch/arm/boot/dts/qcom/sdm630-rumi.dts b/arch/arm/boot/dts/qcom/sdm630-rumi.dts index 2ea1af4da90c..018429a4ebb1 100644 --- a/arch/arm/boot/dts/qcom/sdm630-rumi.dts +++ b/arch/arm/boot/dts/qcom/sdm630-rumi.dts @@ -67,6 +67,27 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + &clock_gcc { compatible = "qcom,dummycc"; clock-output-names = "gcc_clocks"; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 7a1507163c26..38df4a63c5f5 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -17,6 +17,7 @@ #include <dt-bindings/clock/qcom,rpmcc.h> #include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/regulator/qcom,rpm-smd-regulator.h> +#include <dt-bindings/clock/qcom,cpu-osm.h> / { model = "Qualcomm Technologies, Inc. SDM630"; @@ -50,6 +51,7 @@ reg = <0x0 0x100>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile0>; + qcom,ea = <&ea0>; efficiency = <1126>; next-level-cache = <&L2_1>; L2_1: l2-cache { @@ -74,6 +76,7 @@ reg = <0x0 0x101>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile1>; + qcom,ea = <&ea1>; efficiency = <1126>; next-level-cache = <&L2_1>; L1_I_101: l1-icache { @@ -92,6 +95,7 @@ reg = <0x0 0x102>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile2>; + qcom,ea = <&ea2>; efficiency = <1126>; next-level-cache = <&L2_1>; L1_I_102: l1-icache { @@ -110,6 +114,7 @@ reg = <0x0 0x103>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile3>; + qcom,ea = <&ea3>; efficiency = <1126>; next-level-cache = <&L2_1>; L1_I_103: l1-icache { @@ -128,6 +133,7 @@ reg = <0x0 0x0>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile4>; + qcom,ea = <&ea4>; efficiency = <1024>; next-level-cache = <&L2_0>; L2_0: l2-cache { @@ -152,6 +158,7 @@ reg = <0x0 0x1>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile4>; + qcom,ea = <&ea5>; efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_1: l1-icache { @@ -170,6 +177,7 @@ reg = <0x0 0x2>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile4>; + qcom,ea = <&ea6>; efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_2: l1-icache { @@ -188,6 +196,7 @@ reg = <0x0 0x3>; enable-method = "psci"; qcom,limits-info = <&mitigation_profile4>; + qcom,ea = <&ea7>; efficiency = <1024>; next-level-cache = <&L2_0>; L1_I_3: l1-icache { @@ -293,7 +302,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0x400000>; + size = <0x0 0xa00000>; }; qseecom_mem: qseecom_region { @@ -493,6 +502,8 @@ reg-names = "tsens_physical"; interrupts = <0 184 0>, <0 430 0>; interrupt-names = "tsens-upper-lower", "tsens-critical"; + qcom,client-id = <0 1 2 3 4 5 6 7 8 9 10 11>; + qcom,sensor-id = <0 8 10 4 5 6 7 9 2 1 3 11>; qcom,sensors = <12>; }; @@ -680,6 +691,45 @@ }; }; + qcom,msm-core@780000 { + compatible = "qcom,apss-core-ea"; + reg = <0x780000 0x1000>; + qcom,low-hyst-temp = <10>; + qcom,high-hyst-temp = <5>; + + ea0: ea0 { + sensor = <&sensor_information3>; + }; + + ea1: ea1 { + sensor = <&sensor_information4>; + }; + + ea2: ea2 { + sensor = <&sensor_information5>; + }; + + ea3: ea3 { + sensor = <&sensor_information6>; + }; + + ea4: ea4 { + sensor = <&sensor_information7>; + }; + + ea5: ea5 { + sensor = <&sensor_information7>; + }; + + ea6: ea6 { + sensor = <&sensor_information7>; + }; + + ea7: ea7 { + sensor = <&sensor_information7>; + }; + }; + wdog: qcom,wdt@17817000 { status = "disabled"; compatible = "qcom,msm-watchdog"; @@ -690,6 +740,7 @@ qcom,pet-time = <10000>; qcom,ipi-ping; qcom,wakeup-enable; + qcom,scandump-size = <0x40000>; }; uartblsp1dm1: serial@0c170000 { @@ -905,6 +956,7 @@ qcom,use-ipa-tethering-bridge; qcom,modem-cfg-emb-pipe-flt; qcom,ipa-wdi2; + qcom,use-dma-zone; qcom,msm-bus,name = "ipa"; qcom,msm-bus,num-cases = <4>; qcom,msm-bus,num-paths = <2>; @@ -958,6 +1010,105 @@ qcom,ipa-advertise-sg-support; }; + clock_cpu: qcom,clk-cpu-630@179c0000 { + compatible = "qcom,clk-cpu-osm-sdm630"; + status = "disabled"; + reg = <0x179c0000 0x4000>, <0x17916000 0x1000>, + <0x17816000 0x1000>, <0x179d1000 0x1000>, + <0x00784130 0x8>; + reg-names = "osm", "pwrcl_pll", "perfcl_pll", + "apcs_common", "perfcl_efuse"; + + interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "pwrcl-irq", "perfcl-irq"; + + qcom,pwrcl-speedbin0-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 614400000 0x05040020 0x03200020 0x1 2 >, + < 883200000 0x0404002e 0x04250025 0x1 3 >, + < 1094400000 0x04040039 0x052e002e 0x2 4 >, + < 1382400000 0x04040048 0x07390039 0x2 5 >, + < 1536000000 0x04040050 0x08400040 0x3 6 >, + < 1728000000 0x0404005a 0x09480048 0x3 7 >, + < 1843200000 0x04040060 0x094c004c 0x3 8 >; + + qcom,perfcl-speedbin0-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 9 >, + < 2380800000 0x0404007c 0x0c630063 0x3 10 >; + + qcom,perfcl-speedbin1-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 8 >, + < 2208000000 0x04040073 0x0b5c005c 0x3 10 >; + + qcom,perfcl-speedbin2-v0 = + < 300000000 0x0004000f 0x01200020 0x1 1 >, + < 787200000 0x05040029 0x04200020 0x1 2 >, + < 1113600000 0x0404003a 0x052e002e 0x1 3 >, + < 1344000000 0x04040046 0x07380038 0x2 4 >, + < 1516800000 0x0404004f 0x073f003f 0x2 5 >, + < 1670400000 0x04040057 0x08450045 0x2 6 >, + < 1881600000 0x04040062 0x094e004e 0x3 7 >, + < 2016000000 0x04040069 0x0a540054 0x3 8 >, + < 2150400000 0x04040070 0x0b590059 0x3 9 >, + < 2380800000 0x0404007c 0x0c630063 0x3 10 >, + < 2515200000 0x04040083 0x0d680068 0x3 11 >; + + qcom,up-timer = <1000 1000>; + qcom,down-timer = <1000 1000>; + qcom,pc-override-index = <0 0>; + qcom,set-ret-inactive; + qcom,enable-llm-freq-vote; + qcom,llm-freq-up-timer = <327675 327675>; + qcom,llm-freq-down-timer = <327675 327675>; + qcom,enable-llm-volt-vote; + qcom,llm-volt-up-timer = <327675 327675>; + qcom,llm-volt-down-timer = <327675 327675>; + qcom,cc-reads = <10>; + qcom,cc-delay = <5>; + qcom,cc-factor = <100>; + qcom,osm-clk-rate = <200000000>; + qcom,xo-clk-rate = <19200000>; + + qcom,l-val-base = <0x17916004 0x17816004>; + qcom,apcs-itm-present = <0x179d143c 0x179d143c>; + qcom,apcs-pll-user-ctl = <0x1791600c 0x1781600c>; + qcom,apcs-cfg-rcgr = <0x17911054 0x17811054>; + qcom,apcs-cmd-rcgr = <0x17911050 0x17811050>; + qcom,apm-mode-ctl = <0x179d0004 0x179d0010>; + qcom,apm-ctrl-status = <0x179d000c 0x179d0018>; + + qcom,apm-threshold-voltage = <872000>; + qcom,boost-fsm-en; + qcom,safe-fsm-en; + qcom,ps-fsm-en; + qcom,droop-fsm-en; + qcom,wfx-fsm-en; + qcom,pc-fsm-en; + + clock-names = "aux_clk", "xo_a"; + clocks = <&clock_gcc HMSS_GPLL0_CLK_SRC>, + <&clock_rpmcc RPM_XO_A_CLK_SRC>; + + #clock-cells = <1>; + }; + qcom,ipc-spinlock@1f40000 { compatible = "qcom,ipc-spinlock-sfpb"; reg = <0x1f40000 0x8000>; @@ -975,6 +1126,41 @@ qcom,mpu-enabled; }; + qcom,msm-adsprpc-mem { + compatible = "qcom,msm-adsprpc-mem-region"; + memory-region = <&adsp_mem>; + }; + + qcom,msm_fastrpc { + compatible = "qcom,msm-fastrpc-adsp"; + qcom,fastrpc-glink; + + qcom,msm_fastrpc_compute_cb1 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 3>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb2 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 7>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb3 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 8>; + dma-coherent; + }; + qcom,msm_fastrpc_compute_cb4 { + compatible = "qcom,msm-fastrpc-compute-cb"; + label = "adsprpc-smd"; + iommus = <&lpass_q6_smmu 9>; + dma-coherent; + }; + }; + dcc: dcc@10b3000 { compatible = "qcom,dcc"; reg = <0x10b3000 0x1000>, @@ -1397,6 +1583,108 @@ 0x178a80b8 0x178b80b8>; }; + jtag_fuse: jtagfuse@786040 { + compatible = "qcom,jtag-fuse-v4"; + reg = <0x786040 0x8>; + reg-names = "fuse-base"; + }; + + jtag_mm0: jtagmm@7840000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7840000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU4>; + }; + + jtag_mm1: jtagmm@7940000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7940000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU5>; + }; + + jtag_mm2: jtagmm@7a40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7a40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU6>; + }; + + jtag_mm3: jtagmm@7b40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7b40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU7>; + }; + + jtag_mm4: jtagmm@7c40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7c40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU0>; + }; + + jtag_mm5: jtagmm@7d40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7d40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU1>; + }; + + jtag_mm6: jtagmm@7e40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7e40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU2>; + }; + + jtag_mm7: jtagmm@7f40000 { + compatible = "qcom,jtagv8-mm"; + reg = <0x7f40000 0x1000>; + reg-names = "etm-base"; + + clocks = <&clock_rpmcc RPM_QDSS_CLK>, + <&clock_rpmcc RPM_QDSS_A_CLK>; + clock-names = "core_clk", "core_a_clk"; + + qcom,coresight-jtagmm-cpu = <&CPU3>; + }; + spmi_bus: qcom,spmi@800f000 { compatible = "qcom,spmi-pmic-arb"; reg = <0x800f000 0x1000>, @@ -1541,6 +1829,7 @@ #include "msm-arm-smmu-630.dtsi" #include "sdm660-camera.dtsi" #include "sdm630-pm.dtsi" +#include "sdm660-vidc.dtsi" &gdsc_usb30 { status = "ok"; @@ -1608,3 +1897,7 @@ &gdsc_gpu_cx { status = "ok"; }; + +&blsp2_uart1_hs { + status = "ok"; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi index 5bdca492fee2..1145bfa63cba 100644 --- a/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-cdp.dtsi @@ -184,6 +184,15 @@ qcom,panel-roi-alignment = <2 2 4 2 1080 2>; }; +&mdss_dp_ctrl { + pinctrl-names = "mdss_dp_active", "mdss_dp_sleep"; + pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>; + pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>; + qcom,aux-en-gpio = <&tlmm 55 0>; + qcom,aux-sel-gpio = <&tlmm 56 0>; + qcom,usbplug-cc-gpio = <&tlmm 58 0>; +}; + &sdhc_1 { /* device core power supply */ vdd-supply = <&pm660l_l4>; diff --git a/arch/arm/boot/dts/qcom/sdm660-common.dtsi b/arch/arm/boot/dts/qcom/sdm660-common.dtsi index a5e66f38df3c..5a0997faf133 100644 --- a/arch/arm/boot/dts/qcom/sdm660-common.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-common.dtsi @@ -11,6 +11,89 @@ */ &soc { + ufsphy1: ufsphy@1da7000 { + compatible = "qcom,ufs-phy-qmp-v3-660"; + reg = <0x1da7000 0xdb8>; + reg-names = "phy_mem"; + #phy-cells = <0>; + clock-names = "ref_clk_src", + "ref_clk", + "ref_aux_clk"; + clocks = <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_CLKREF_CLK>, + <&clock_gcc GCC_UFS_PHY_AUX_CLK>; + status = "disabled"; + }; + + ufs1: ufshc@1da4000 { + compatible = "qcom,ufshc"; + reg = <0x1da4000 0x3000>; + interrupts = <0 265 0>; + phys = <&ufsphy1>; + phy-names = "ufsphy"; + + clock-names = + "core_clk", + "bus_aggr_clk", + "iface_clk", + "core_clk_unipro", + "core_clk_ice", + "ref_clk", + "tx_lane0_sync_clk", + "rx_lane0_sync_clk"; + clocks = + <&clock_gcc GCC_UFS_AXI_CLK>, + <&clock_gcc GCC_AGGRE2_UFS_AXI_CLK>, + <&clock_gcc GCC_UFS_AHB_CLK>, + <&clock_gcc GCC_UFS_UNIPRO_CORE_CLK>, + <&clock_gcc GCC_UFS_ICE_CORE_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_UFS_TX_SYMBOL_0_CLK>, + <&clock_gcc GCC_UFS_RX_SYMBOL_0_CLK>; + freq-table-hz = + <50000000 200000000>, + <0 0>, + <0 0>, + <37500000 150000000>, + <75000000 300000000>, + <0 0>, + <0 0>, + <0 0>; + + lanes-per-direction = <1>; + + qcom,msm-bus,name = "ufs1"; + qcom,msm-bus,num-cases = <12>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <95 512 0 0>, <1 650 0 0>, /* No vote */ + <95 512 922 0>, <1 650 1000 0>, /* PWM G1 */ + <95 512 1844 0>, <1 650 1000 0>, /* PWM G2 */ + <95 512 3688 0>, <1 650 1000 0>, /* PWM G3 */ + <95 512 7376 0>, <1 650 1000 0>, /* PWM G4 */ + <95 512 127796 0>, <1 650 1000 0>, /* HS G1 RA */ + <95 512 255591 0>, <1 650 1000 0>, /* HS G2 RA */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RA */ + <95 512 149422 0>, <1 650 1000 0>, /* HS G1 RB */ + <95 512 298189 0>, <1 650 1000 0>, /* HS G2 RB */ + <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RB */ + <95 512 7643136 0>, <1 650 307200 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1", + "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1", + "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1", + "MAX"; + + qcom,pm-qos-cpu-groups = <0x0F 0xF0>; + qcom,pm-qos-cpu-group-latency-us = <26 26>; + qcom,pm-qos-default-cpu = <0>; + + resets = <&clock_gcc GCC_UFS_BCR>; + reset-names = "core_reset"; + + status = "disabled"; + }; + usb3: ssusb@a800000 { compatible = "qcom,dwc-usb3-msm"; reg = <0x0a800000 0xfc100>, diff --git a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi index 2adc4cfae77f..e5cf0b1534ec 100644 --- a/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-gpu.dtsi @@ -58,8 +58,9 @@ label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; status = "ok"; - reg = <0x5000000 0x40000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0x5000000 0x40000 + 0x780000 0x6220>; + reg-names = "kgsl_3d0_reg_memory", "qfprom_memory"; interrupts = <0 300 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; @@ -70,7 +71,6 @@ /* <HZ/12> */ qcom,idle-timeout = <80>; - qcom,no-nap; qcom,highest-bank-bit = <14>; @@ -135,6 +135,8 @@ /* Context aware jump target power level */ qcom,ca-target-pwrlevel = <4>; + qcom,gpu-speed-bin = <0x41a0 0x1fe00000 21>; + /* GPU Mempools */ qcom,gpu-mempools { #address-cells= <1>; @@ -155,92 +157,349 @@ }; }; - /* Power levels */ - qcom,gpu-pwrlevels { + /* + * Speed-bin zero is default speed bin. + * For rest of the speed bins, speed-bin value + * is calulated as FMAX/4.8 MHz round up to zero + * decimal places. + */ + qcom,gpu-pwrlevel-bins { #address-cells = <1>; #size-cells = <0>; - compatible = "qcom,gpu-pwrlevels"; - - /* TURBO */ - qcom,gpu-pwrlevel@0 { - reg = <0>; - qcom,gpu-freq = <750000000>; - qcom,bus-freq = <13>; - qcom,bus-min = <12>; - qcom,bus-max = <13>; - }; - - /* TURBO */ - qcom,gpu-pwrlevel@1 { - reg = <1>; - qcom,gpu-freq = <700000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <11>; - qcom,bus-max = <13>; - }; - - /* NOM_L1 */ - qcom,gpu-pwrlevel@2 { - reg = <2>; - qcom,gpu-freq = <647000000>; - qcom,bus-freq = <11>; - qcom,bus-min = <10>; - qcom,bus-max = <12>; - }; - - /* NOM */ - qcom,gpu-pwrlevel@3 { - reg = <3>; - qcom,gpu-freq = <588000000>; - qcom,bus-freq = <10>; - qcom,bus-min = <9>; - qcom,bus-max = <12>; - }; - - /* SVS_L1 */ - qcom,gpu-pwrlevel@4 { - reg = <4>; - qcom,gpu-freq = <465000000>; - qcom,bus-freq = <9>; - qcom,bus-min = <8>; - qcom,bus-max = <11>; - }; - - /* SVS */ - qcom,gpu-pwrlevel@5 { - reg = <5>; - qcom,gpu-freq = <370000000>; - qcom,bus-freq = <8>; - qcom,bus-min = <6>; - qcom,bus-max = <9>; + compatible="qcom,gpu-pwrlevel-bins"; + + qcom,gpu-pwrlevels-0 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <0>; + + qcom,initial-pwrlevel = <6>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <750000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <11>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@8 { + reg = <8>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* Low SVS */ - qcom,gpu-pwrlevel@6 { - reg = <6>; - qcom,gpu-freq = <266000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <3>; - qcom,bus-max = <6>; + qcom,gpu-pwrlevels-1 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <157>; + + qcom,initial-pwrlevel = <6>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <750000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <11>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@8 { + reg = <8>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* Min SVS */ - qcom,gpu-pwrlevel@7 { - reg = <7>; - qcom,gpu-freq = <160000000>; - qcom,bus-freq = <3>; - qcom,bus-min = <3>; - qcom,bus-max = <5>; + qcom,gpu-pwrlevels-2 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <146>; + + qcom,initial-pwrlevel = <5>; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <12>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; - /* XO */ - qcom,gpu-pwrlevel@8 { - reg = <8>; - qcom,gpu-freq = <19200000>; - qcom,bus-freq = <0>; - qcom,bus-min = <0>; - qcom,bus-max = <0>; + qcom,gpu-pwrlevels-3 { + #address-cells = <1>; + #size-cells = <0>; + + qcom,speed-bin = <135>; + + qcom,initial-pwrlevel = <4>; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <13>; + qcom,bus-min = <12>; + qcom,bus-max = <13>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <12>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <11>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <266000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <6>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* XO */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; }; }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi index a0cc0a6180e5..ce8273e4f1b8 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-panels.dtsi @@ -33,7 +33,7 @@ qcom,panel-supply-entry@0 { reg = <0>; qcom,supply-name = "wqhd-vddio"; - qcom,supply-min-voltage = <1880000>; + qcom,supply-min-voltage = <1800000>; qcom,supply-max-voltage = <1950000>; qcom,supply-enable-load = <32000>; qcom,supply-disable-load = <80>; @@ -196,19 +196,23 @@ }; &dsi_nt35695b_truly_fhd_video { - qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 18 07 08 04 03 04 a0]; + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1a 08 09 05 03 04 a0]; + qcom,mdss-dsi-min-refresh-rate = <48>; + qcom,mdss-dsi-max-refresh-rate = <60>; + qcom,mdss-dsi-pan-enable-dynamic-fps; + qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp"; }; &dsi_nt35695b_truly_fhd_cmd { - qcom,mdss-dsi-panel-timings-phy-v2 = [23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 1e 07 08 05 03 04 a0 - 23 18 07 08 04 03 04 a0]; + qcom,mdss-dsi-panel-timings-phy-v2 = [24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1e 08 09 05 03 04 a0 + 24 1a 08 09 05 03 04 a0]; }; &dsi_truly_1080_vid { diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi index d2134c56541e..69d3736d4ba8 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss-pll.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -79,4 +79,39 @@ }; }; }; + + mdss_dp_pll: qcom,mdss_dp_pll@c011000 { + compatible = "qcom,mdss_dp_pll_sdm660"; + status = "ok"; + label = "MDSS DP PLL"; + cell-index = <0>; + #clock-cells = <1>; + + reg = <0xc011c00 0x190>, + <0xc011000 0x910>, + <0x0c8c2300 0x8>; + reg-names = "pll_base", "phy_base", "gdsc_base"; + + gdsc-supply = <&gdsc_mdss>; + + clocks = <&clock_mmss MMSS_MDSS_AHB_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_USB3_CLKREF_CLK>; + clock-names = "iface_clk", "ref_clk_src", "ref_clk"; + clock-rate = <0>; + + qcom,platform-supply-entries { + #address-cells = <1>; + #size-cells = <0>; + + qcom,platform-supply-entry@0 { + reg = <0>; + qcom,supply-name = "gdsc"; + qcom,supply-min-voltage = <0>; + qcom,supply-max-voltage = <0>; + qcom,supply-enable-load = <0>; + qcom,supply-disable-load = <0>; + }; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi index 5257e79816a3..b7329121ca49 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi @@ -46,8 +46,9 @@ /* VBIF QoS remapper settings*/ qcom,mdss-vbif-qos-rt-setting = <1 2 2 2>; - qcom,vbif-settings = <0x00ac 0x00000040>, - <0x00d0 0x00001010>; /* v1 only */ + qcom,mdss-vbif-qos-nrt-setting = <1 1 1 1>; + qcom,vbif-settings = <0x00ac 0x00008040>, + <0x00d0 0x00002828>; qcom,mdss-has-panic-ctrl; qcom,mdss-per-pipe-panic-luts = <0x000f>, @@ -127,7 +128,7 @@ <0x012ac 0xc0000ccc>, <0x012b4 0xc0000ccc>, <0x012bc 0x00cccccc>, - <0x012c4 0x000000cc>, + <0x012c4 0x0000cccc>, <0x013a8 0x0cccc0c0>, <0x013b0 0xccccc0c0>, <0x013b8 0xcccc0000>, @@ -436,7 +437,7 @@ }; msm_ext_disp: qcom,msm_ext_disp { - status = "disabled"; + status = "ok"; compatible = "qcom,msm-ext-disp"; ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx { @@ -446,16 +447,16 @@ }; mdss_dp_ctrl: qcom,dp_ctrl@c990000 { - status = "disabled"; + status = "ok"; cell-index = <0>; compatible = "qcom,mdss-dp"; qcom,mdss-fb-map = <&mdss_fb2>; gdsc-supply = <&gdsc_mdss>; - vdda-1p2-supply = <&pm660_l1>; + vdda-1p8-supply = <&pm660_l10>; vdda-0p9-supply = <&pm660l_l1>; - reg = <0xc990000 0xa84>, + reg = <0xc990000 0xa8c>, <0xc011000 0x910>, <0x1fcb200 0x050>, <0xc8c2200 0x1a0>, @@ -464,8 +465,37 @@ reg-names = "dp_ctrl", "dp_phy", "tcsr_regs", "dp_mmss_cc", "qfprom_physical","hdcp_physical"; + clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>, + <&clock_mmss MMSS_MDSS_AHB_CLK>, + <&clock_mmss MMSS_MDSS_AXI_CLK>, + <&clock_mmss MMSS_MDSS_MDP_CLK>, + <&clock_mmss MMSS_MDSS_HDMI_DP_AHB_CLK>, + <&clock_mmss MMSS_MDSS_DP_AUX_CLK>, + <&clock_rpmcc RPM_LN_BB_CLK1>, + <&clock_gcc GCC_USB3_CLKREF_CLK>, + <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, + <&clock_mmss MMSS_MDSS_DP_LINK_CLK>, + <&clock_mmss MMSS_MDSS_DP_LINK_INTF_CLK>, + <&clock_mmss MMSS_MDSS_DP_CRYPTO_CLK>, + <&clock_mmss MMSS_MDSS_DP_PIXEL_CLK>, + <&clock_mmss DP_PIXEL_CLK_SRC>, + <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>; + clock-names = "core_mnoc_clk", "core_iface_clk", "core_bus_clk", + "core_mdp_core_clk", "core_alt_iface_clk", + "core_aux_clk", "core_ref_clk_src", "core_ref_clk", + "core_ahb_phy_clk", "ctrl_link_clk", + "ctrl_link_iface_clk", "ctrl_crypto_clk", + "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent"; + + qcom,dp-usbpd-detection = <&pm660_pdphy>; + qcom,msm_ext_disp = <&msm_ext_disp>; + qcom,aux-cfg-settings = [00 13 00 00 0a 28 0a 03 b7 03]; + qcom,logical2physical-lane-map = [00 01 02 03]; + qcom,phy-register-offset = <0x4>; + qcom,max-pclk-frequency-khz = <593470>; + qcom,core-supply-entries { #address-cells = <1>; #size-cells = <0>; @@ -486,9 +516,9 @@ qcom,ctrl-supply-entry@0 { reg = <0>; - qcom,supply-name = "vdda-1p2"; - qcom,supply-min-voltage = <1200000>; - qcom,supply-max-voltage = <1250000>; + qcom,supply-name = "vdda-1p8"; + qcom,supply-min-voltage = <1780000>; + qcom,supply-max-voltage = <1950000>; qcom,supply-enable-load = <12560>; qcom,supply-disable-load = <4>; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi index b666d846ca04..150b88c10646 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi @@ -106,6 +106,15 @@ qcom,platform-te-gpio = <&tlmm 59 0>; }; +&mdss_dp_ctrl { + pinctrl-names = "mdss_dp_active", "mdss_dp_sleep"; + pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>; + pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>; + qcom,aux-en-gpio = <&tlmm 55 0>; + qcom,aux-sel-gpio = <&tlmm 56 0>; + qcom,usbplug-cc-gpio = <&tlmm 58 0>; +}; + &pm660l_wled { qcom,led-strings-list = [01 02]; }; @@ -147,6 +156,20 @@ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; }; +&dsi_nt35695b_truly_fhd_video { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + +&dsi_nt35695b_truly_fhd_cmd { + qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled"; + qcom,mdss-dsi-bl-min-level = <1>; + qcom,mdss-dsi-bl-max-level = <4095>; + qcom,panel-supply-entries = <&dsi_panel_pwr_supply>; +}; + &sdhc_1 { /* device core power supply */ vdd-supply = <&pm660l_l4>; diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi index dbc98a97fc8d..273f196364ce 100644 --- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi @@ -1439,6 +1439,58 @@ }; }; + mdss_dp_aux_active: mdss_dp_aux_active { + mux { + pins = "gpio55", "gpio56"; + function = "gpio"; + }; + + config { + pins = "gpio55", "gpio56"; + bias-disable = <0>; /* no pull */ + drive-strength = <8>; + }; + }; + + mdss_dp_aux_suspend: mdss_dp_aux_suspend { + mux { + pins = "gpio55", "gpio56"; + function = "gpio"; + }; + + config { + pins = "gpio55", "gpio56"; + bias-pull-down; + drive-strength = <2>; + }; + }; + + mdss_dp_usbplug_cc_active: mdss_dp_usbplug_cc_active { + mux { + pins = "gpio58"; + function = "gpio"; + }; + + config { + pins = "gpio58"; + bias-disable; + drive-strength = <16>; + }; + }; + + mdss_dp_usbplug_cc_suspend: mdss_dp_usbplug_cc_suspend { + mux { + pins = "gpio58"; + function = "gpio"; + }; + + config { + pins = "gpio58"; + bias-pull-down; + drive-strength = <2>; + }; + }; + ts_mux { ts_active: ts_active { mux { diff --git a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi index ae3f1949115a..82e6a5be4d10 100644 --- a/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-vidc.dtsi @@ -109,8 +109,8 @@ qcom,clock-freq-tbl { qcom,profile-enc { qcom,codec-mask = <0x55555555>; - qcom,cycles-per-mb = <863>; - qcom,low-power-mode-factor = <35616>; + qcom,cycles-per-mb = <931>; + qcom,low-power-mode-factor = <33286>; }; qcom,profile-dec { qcom,codec-mask = <0xf3ffffff>; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 358ff9c96292..f35619d2a21e 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1251,6 +1251,51 @@ < 2457600 >; }; + ufs_ice: ufsice@1db0000 { + compatible = "qcom,ice"; + reg = <0x1db0000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ufs_core_clk", "bus_clk", + "iface_clk", "ice_core_clk"; + clocks = <&clock_gcc GCC_UFS_AXI_CLK>, + <&clock_gcc GCC_UFS_CLKREF_CLK>, + <&clock_gcc GCC_UFS_AHB_CLK>, + <&clock_gcc GCC_UFS_ICE_CORE_CLK>; + qcom,op-freq-hz = <0>, <0>, <0>, <300000000>; + vdd-hba-supply = <&gdsc_ufs>; + qcom,msm-bus,name = "ufs_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 650 0 0>, /* No vote */ + <1 650 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "ufs"; + }; + + sdcc1_ice: sdcc1ice@c0c8000 { + compatible = "qcom,ice"; + reg = <0xc0c8000 0x8000>; + qcom,enable-ice-clk; + clock-names = "ice_core_clk_src", "ice_core_clk", + "bus_clk", "iface_clk"; + clocks = <&clock_gcc SDCC1_ICE_CORE_CLK_SRC>, + <&clock_gcc GCC_SDCC1_ICE_CORE_CLK>, + <&clock_gcc GCC_SDCC1_APPS_CLK>, + <&clock_gcc GCC_SDCC1_AHB_CLK>; + qcom,op-freq-hz = <300000000>, <0>, <0>, <0>; + qcom,msm-bus,name = "sdcc_ice_noc"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <78 512 0 0>, /* No vote */ + <78 512 1000 0>; /* Max. bandwidth */ + qcom,bus-vector-names = "MIN", + "MAX"; + qcom,instance-type = "sdcc"; + }; + sdhc_1: sdhci@c0c4000 { compatible = "qcom,sdhci-msm-v5"; reg = <0xc0c4000 0x1000>, <0xc0c5000 0x1000>; @@ -1261,6 +1306,7 @@ qcom,bus-width = <8>; qcom,large-address-bus; + sdhc-msm-crypto = <&sdcc1_ice>; qcom,devfreq,freq-table = <50000000 200000000>; @@ -1342,6 +1388,7 @@ qcom,use-ipa-tethering-bridge; qcom,modem-cfg-emb-pipe-flt; qcom,ipa-wdi2; + qcom,use-dma-zone; qcom,msm-bus,name = "ipa"; qcom,msm-bus,num-cases = <4>; qcom,msm-bus,num-paths = <2>; @@ -1511,7 +1558,7 @@ dcc: dcc@10b3000 { compatible = "qcom,dcc"; reg = <0x10b3000 0x1000>, - <0x10b4000 0x2000>; + <0x10b4000 0x800>; reg-names = "dcc-base", "dcc-ram-base"; clocks = <&clock_gcc GCC_DCC_AHB_CLK>; @@ -2129,6 +2176,7 @@ interrupts = <0 265 0>; phys = <&ufsphy1>; phy-names = "ufsphy"; + ufs-qcom-crypto = <&ufs_ice>; clock-names = "core_clk", diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig index 0028dbbb5c68..d7eb67ff85c1 100644 --- a/arch/arm/configs/sdm660-perf_defconfig +++ b/arch/arm/configs/sdm660-perf_defconfig @@ -610,7 +610,6 @@ CONFIG_CORESIGHT_EVENT=y CONFIG_CORESIGHT_QCOM_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_CTI=y CONFIG_CORESIGHT_TPDA=y CONFIG_CORESIGHT_TPDM=y CONFIG_CORESIGHT_QPDI=y diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig index c2ceac22f15f..dfab3902ec99 100644 --- a/arch/arm/configs/sdm660_defconfig +++ b/arch/arm/configs/sdm660_defconfig @@ -7,7 +7,6 @@ CONFIG_RCU_EXPERT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y @@ -15,7 +14,6 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_SCHEDTUNE=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y -CONFIG_CGROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_SCHED_HMP=y CONFIG_SCHED_HMP_CSTATE_AWARE=y @@ -23,6 +21,7 @@ CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_XZ is not set diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index d8a62f634ecc..b24885a89bff 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -626,7 +626,6 @@ CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y CONFIG_CORESIGHT_QCOM_REPLICATOR=y CONFIG_CORESIGHT_STM=y CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_CTI=y CONFIG_CORESIGHT_TPDA=y CONFIG_CORESIGHT_TPDM=y CONFIG_CORESIGHT_QPDI=y diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 3c8c1f9acbfa..9a7411a33127 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -815,9 +815,9 @@ static int overlap_ptr_cmp(const void *a, const void *b) return st == 0 ? ed : st; } -static void context_build_overlap(struct smq_invoke_ctx *ctx) +static int context_build_overlap(struct smq_invoke_ctx *ctx) { - int i; + int i, err = 0; remote_arg_t *lpra = ctx->lpra; int inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); @@ -826,6 +826,11 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) for (i = 0; i < nbufs; ++i) { ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; + if (lpra[i].buf.len) { + VERIFY(err, ctx->overs[i].end > ctx->overs[i].start); + if (err) + goto bail; + } ctx->overs[i].raix = i; ctx->overps[i] = &ctx->overs[i]; } @@ -851,6 +856,8 @@ static void context_build_overlap(struct smq_invoke_ctx *ctx) max = *ctx->overps[i]; } } +bail: + return err; } #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ @@ -923,8 +930,11 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, } ctx->sc = invoke->sc; - if (bufs) - context_build_overlap(ctx); + if (bufs) { + VERIFY(err, 0 == context_build_overlap(ctx)); + if (err) + goto bail; + } ctx->retval = -1; ctx->pid = current->pid; ctx->tgid = current->tgid; @@ -1493,6 +1503,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, return err; } +static int fastrpc_channel_open(struct fastrpc_file *fl); static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init_attrs *uproc) { @@ -1501,6 +1512,10 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = 0, *mem = 0; + + VERIFY(err, !fastrpc_channel_open(fl)); + if (err) + goto bail; if (init->flags == FASTRPC_INIT_ATTACH) { remote_arg_t ra[1]; int tgid = current->tgid; @@ -1625,7 +1640,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, fds[2] = 0; ioctl.inv.handle = 1; - ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 3, 0); + ioctl.inv.sc = REMOTE_SCALARS_MAKE(8, 3, 0); ioctl.inv.pra = ra; ioctl.fds = 0; ioctl.attrs = 0; @@ -1651,6 +1666,9 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) remote_arg_t ra[1]; int tgid = 0; + VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS); + if (err) + goto bail; VERIFY(err, fl->apps->channel[fl->cid].chan != 0); if (err) goto bail; @@ -2307,42 +2325,20 @@ static const struct file_operations debugfs_fops = { .open = fastrpc_debugfs_open, .read = fastrpc_debugfs_read, }; - -static int fastrpc_device_open(struct inode *inode, struct file *filp) +static int fastrpc_channel_open(struct fastrpc_file *fl) { - int cid = MINOR(inode->i_rdev); - struct dentry *debugfs_file; - int err = 0; struct fastrpc_apps *me = &gfa; - struct fastrpc_file *fl = 0; - - VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL)); - if (err) - return err; - - filp->private_data = fl; + int cid, err = 0; mutex_lock(&me->smd_mutex); - debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root, - fl, &debugfs_fops); - context_list_ctor(&fl->clst); - spin_lock_init(&fl->hlock); - INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); - INIT_HLIST_NODE(&fl->hn); - fl->tgid = current->tgid; - fl->apps = me; - fl->cid = cid; - if (debugfs_file != NULL) - fl->debugfs_file = debugfs_file; - memset(&fl->perf, 0, sizeof(fl->perf)); - - VERIFY(err, !fastrpc_session_alloc_locked(&me->channel[cid], 0, - &fl->sctx)); + VERIFY(err, fl && fl->sctx); + if (err) + goto bail; + cid = fl->cid; + VERIFY(err, cid >= 0 && cid < NUM_CHANNELS); if (err) goto bail; - fl->cid = cid; fl->ssrcount = me->channel[cid].ssrcount; if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) || (me->channel[cid].chan == 0)) { @@ -2368,25 +2364,58 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) me->channel[cid].ssrcount; } } - spin_lock(&me->hlock); - hlist_add_head(&fl->hn, &me->drivers); - spin_unlock(&me->hlock); bail: mutex_unlock(&me->smd_mutex); - - if (err && fl) - fastrpc_device_release(inode, filp); return err; } +static int fastrpc_device_open(struct inode *inode, struct file *filp) +{ + int err = 0; + struct fastrpc_file *fl = 0; + struct fastrpc_apps *me = &gfa; + + VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL)); + if (err) + return err; + + context_list_ctor(&fl->clst); + spin_lock_init(&fl->hlock); + INIT_HLIST_HEAD(&fl->maps); + INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_NODE(&fl->hn); + fl->tgid = current->tgid; + fl->apps = me; + fl->mode = FASTRPC_MODE_SERIAL; + fl->cid = -1; + filp->private_data = fl; + spin_lock(&me->hlock); + hlist_add_head(&fl->hn, &me->drivers); + spin_unlock(&me->hlock); + return 0; +} + static int fastrpc_get_info(struct fastrpc_file *fl, uint32_t *info) { int err = 0; + uint32_t cid; - VERIFY(err, fl && fl->sctx); + VERIFY(err, fl != 0); if (err) goto bail; + if (fl->cid == -1) { + cid = *info; + VERIFY(err, cid < NUM_CHANNELS); + if (err) + goto bail; + fl->cid = cid; + fl->ssrcount = fl->apps->channel[cid].ssrcount; + VERIFY(err, !fastrpc_session_alloc_locked( + &fl->apps->channel[cid], 0, &fl->sctx)); + if (err) + goto bail; + } *info = (fl->sctx->smmu.enabled ? 1 : 0); bail: return err; @@ -2487,6 +2516,9 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, goto bail; break; case FASTRPC_IOCTL_GETINFO: + VERIFY(err, 0 == copy_from_user(&info, param, sizeof(info))); + if (err) + goto bail; VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); if (err) goto bail; @@ -2802,6 +2834,7 @@ static struct platform_driver fastrpc_driver = { static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; + struct device *dev = 0; int err = 0, i; memset(me, 0, sizeof(*me)); @@ -2818,7 +2851,7 @@ static int __init fastrpc_device_init(void) cdev_init(&me->cdev, &fops); me->cdev.owner = THIS_MODULE; VERIFY(err, 0 == cdev_add(&me->cdev, MKDEV(MAJOR(me->dev_no), 0), - NUM_CHANNELS)); + 1)); if (err) goto cdev_init_bail; me->class = class_create(THIS_MODULE, "fastrpc"); @@ -2826,15 +2859,14 @@ static int __init fastrpc_device_init(void) if (err) goto class_create_bail; me->compat = (NULL == fops.compat_ioctl) ? 0 : 1; + dev = device_create(me->class, NULL, + MKDEV(MAJOR(me->dev_no), 0), + NULL, gcinfo[0].name); + VERIFY(err, !IS_ERR_OR_NULL(dev)); + if (err) + goto device_create_bail; for (i = 0; i < NUM_CHANNELS; i++) { - if (!gcinfo[i].name) - continue; - me->channel[i].dev = device_create(me->class, NULL, - MKDEV(MAJOR(me->dev_no), i), - NULL, gcinfo[i].name); - VERIFY(err, !IS_ERR(me->channel[i].dev)); - if (err) - goto device_create_bail; + me->channel[i].dev = dev; me->channel[i].ssrcount = 0; me->channel[i].prevssrcount = 0; me->channel[i].ramdumpenabled = 0; @@ -2853,12 +2885,12 @@ static int __init fastrpc_device_init(void) return 0; device_create_bail: for (i = 0; i < NUM_CHANNELS; i++) { - if (IS_ERR_OR_NULL(me->channel[i].dev)) - continue; - device_destroy(me->class, MKDEV(MAJOR(me->dev_no), i)); - subsys_notif_unregister_notifier(me->channel[i].handle, - &me->channel[i].nb); + if (me->channel[i].handle) + subsys_notif_unregister_notifier(me->channel[i].handle, + &me->channel[i].nb); } + if (!IS_ERR_OR_NULL(dev)) + device_destroy(me->class, MKDEV(MAJOR(me->dev_no), 0)); class_destroy(me->class); class_create_bail: cdev_del(&me->cdev); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index f7e84dd55606..fcd6d1142618 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -391,6 +391,10 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, sizeof(*info)))); if (err) return -EFAULT; + err = get_user(u, info32); + err |= put_user(u, info); + if (err) + return err; ret = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_GETINFO, (unsigned long)info); if (ret) diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c index 0462a64614f3..3342984eb795 100644 --- a/drivers/char/diag/diagfwd_bridge.c +++ b/drivers/char/diag/diagfwd_bridge.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -90,6 +90,18 @@ static int diagfwd_bridge_mux_disconnect(int id, int mode) { if (id < 0 || id >= NUM_REMOTE_DEV) return -EINVAL; + + if ((mode == DIAG_USB_MODE && + driver->logging_mode == DIAG_MEMORY_DEVICE_MODE) || + (mode == DIAG_MEMORY_DEVICE_MODE && + driver->logging_mode == DIAG_USB_MODE)) { + /* + * Don't close the MHI channels when usb is disconnected + * and a process is running in memory device mode. + */ + return 0; + } + if (bridge_info[id].dev_ops && bridge_info[id].dev_ops->close) bridge_info[id].dev_ops->close(bridge_info[id].ctxt); return 0; diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c index 79e8a7d8eb00..1639b1b7f94b 100644 --- a/drivers/clk/msm/clock-osm.c +++ b/drivers/clk/msm/clock-osm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -83,6 +83,7 @@ enum clk_osm_trace_packet_id { #define VERSION_REG 0x0 #define OSM_TABLE_SIZE 40 +#define MAX_VIRTUAL_CORNER (OSM_TABLE_SIZE - 1) #define MAX_CLUSTER_CNT 2 #define CORE_COUNT_VAL(val) ((val & GENMASK(18, 16)) >> 16) #define SINGLE_CORE 1 @@ -1662,6 +1663,14 @@ static int clk_osm_resolve_crossover_corners(struct clk_osm *c, break; } } + + /* + * This assumes the OSM table uses corners + * 0 to MAX_VIRTUAL_CORNER - 1. + */ + if (!c->mem_acc_threshold_vc) + c->mem_acc_threshold_vc = + MAX_VIRTUAL_CORNER; } return 0; @@ -3232,9 +3241,10 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev) return rc; } - rc = clk_osm_resolve_crossover_corners(&pwrcl_clk, pdev, NULL); + rc = clk_osm_resolve_crossover_corners(&pwrcl_clk, pdev, + "qcom,pwrcl-apcs-mem-acc-threshold-voltage"); if (rc) - dev_info(&pdev->dev, "No APM crossover corner programmed\n"); + dev_info(&pdev->dev, "No MEM-ACC crossover corner programmed\n"); rc = clk_osm_resolve_crossover_corners(&perfcl_clk, pdev, "qcom,perfcl-apcs-mem-acc-threshold-voltage"); diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 40c592457ea1..6e6adbff4676 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1111,6 +1111,16 @@ static int clk_dp_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, return clk_dp_set_rate(hw, rate, parent_rate); } +static int clk_dp_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw, + req->best_parent_rate); + req->rate = req->rate; + + return 0; +} + const struct clk_ops clk_dp_ops = { .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, @@ -1118,7 +1128,7 @@ const struct clk_ops clk_dp_ops = { .recalc_rate = clk_rcg2_recalc_rate, .set_rate = clk_dp_set_rate, .set_rate_and_parent = clk_dp_set_rate_and_parent, - .determine_rate = clk_pixel_determine_rate, + .determine_rate = clk_dp_determine_rate, .list_registers = clk_rcg2_list_registers, }; EXPORT_SYMBOL_GPL(clk_dp_ops); diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c index 934779f16107..aec73d62bc18 100644 --- a/drivers/clk/qcom/mmcc-sdm660.c +++ b/drivers/clk/qcom/mmcc-sdm660.c @@ -965,8 +965,9 @@ static struct clk_rcg2 dp_pixel_clk_src = { .parent_names = mmcc_parent_names_6, .num_parents = 4, .ops = &clk_dp_ops, + .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT, VDD_DIG_FMAX_MAP3( - LOWER, 148380, + LOWER, 154000, LOW, 296740, NOMINAL, 593470), }, diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c index 9b4a001bec95..674913cb20bf 100644 --- a/drivers/crypto/msm/ota_crypto.c +++ b/drivers/crypto/msm/ota_crypto.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2014,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -880,8 +880,8 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, int len; len = _disp_stats(); - - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); return rc; diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 8d17ea89e266..ee7e735761e2 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -4967,6 +4967,11 @@ int qce_aead_req(void *handle, struct qce_req *q_req) else q_req->cryptlen = areq->cryptlen - authsize; + if (q_req->cryptlen > UINT_MAX - areq->assoclen) { + pr_err("Integer overflow on total aead req length.\n"); + return -EINVAL; + } + totallen = q_req->cryptlen + areq->assoclen; if (pce_dev->support_cmd_dscr) { diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index a629c621648c..5ce87a6edcc3 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1987,9 +1987,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcedev); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index a898dbcbd0ca..893b0b6da6b8 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto driver * - * Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -5419,9 +5419,9 @@ static ssize_t _debug_stats_read(struct file *file, char __user *buf, len = _disp_stats(qcrypto); - rc = simple_read_from_buffer((void __user *) buf, len, + if (len <= count) + rc = simple_read_from_buffer((void __user *) buf, len, ppos, (void *) _debug_read_buf, len); - return rc; } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 008b8babf31e..d4729fa59edb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -339,22 +339,23 @@ config GPIO_PXA Say yes here to support the PXA GPIO device config GPIO_QPNP_PIN + tristate "Qualcomm Technologies, Inc. QPNP GPIO support" depends on SPMI - tristate "Qualcomm QPNP gpio support" help - Say 'y' here to include support for the Qualcomm QPNP gpio - driver. This driver supports Device Tree and allows a - device_node to be registered as a gpio-controller. It - does not handle gpio interrupts directly, they are handled - via the spmi arbiter interrupt driver. + Say 'y' here to include support for the Qualcomm Technologies, Inc. + QPNP GPIO driver. This driver supports Device Tree and allows a + device_node to be registered as a gpio-controller. It does not handle + GPIO interrupts directly; they are handled via the SPMI arbiter + interrupt driver. config GPIO_QPNP_PIN_DEBUG - depends on GPIO_QPNP_PIN - depends on DEBUG_FS - bool "Qualcomm QPNP GPIO debug support" + bool "Qualcomm Technologies, Inc. QPNP GPIO debug support" + depends on GPIO_QPNP_PIN && DEBUG_FS help - Say 'y' here to include debug support for the Qualcomm - QPNP gpio driver. + Say 'y' here to include debug support for the Qualcomm Technologies, + Inc. QPNP GPIO driver. This provides a userspace debug interface to + get and set all of the supported features of PMIC GPIO and MPP pins + including those which are managed by the gpio framework. config GPIO_RCAR tristate "Renesas R-Car GPIO" diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c index de24d99ea34e..62cd78a95303 100644 --- a/drivers/gpio/qpnp-pin.c +++ b/drivers/gpio/qpnp-pin.c @@ -295,7 +295,7 @@ static int qpnp_pin_check_config(enum qpnp_pin_param_type idx, if (val >= QPNP_PIN_GPIO_LV_MV_MODE_INVALID) return -EINVAL; } else if (val >= QPNP_PIN_GPIO_MODE_INVALID) { - return -EINVAL; + return -EINVAL; } } else if (q_spec->type == Q_MPP_TYPE) { if (val >= QPNP_PIN_MPP_MODE_INVALID) @@ -753,16 +753,17 @@ int qpnp_pin_config(int gpio, struct qpnp_pin_cfg *param) } EXPORT_SYMBOL(qpnp_pin_config); -#define Q_MAX_CHIP_NAME 128 int qpnp_pin_map(const char *name, uint32_t pmic_pin) { struct qpnp_pin_chip *q_chip; struct qpnp_pin_spec *q_spec = NULL; + if (!name) + return -EINVAL; + mutex_lock(&qpnp_pin_chips_lock); list_for_each_entry(q_chip, &qpnp_pin_chips, chip_list) { - if (strncmp(q_chip->gpio_chip.label, name, - Q_MAX_CHIP_NAME) != 0) + if (strcmp(q_chip->gpio_chip.label, name) != 0) continue; if (q_chip->pmic_pin_lowest <= pmic_pin && q_chip->pmic_pin_highest >= pmic_pin) { @@ -778,7 +779,7 @@ int qpnp_pin_map(const char *name, uint32_t pmic_pin) } EXPORT_SYMBOL(qpnp_pin_map); -static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -811,14 +812,13 @@ static int qpnp_pin_to_irq(struct gpio_chip *gpio_chip, unsigned offset) return q_spec->irq; } -static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) +static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned int offset) { - int rc, ret_val; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec = NULL; - u8 buf[1], en_mask; - u8 shift, mask, reg; - int val; + u8 buf, en_mask, shift, mask, reg; + unsigned int val; + int rc; if (WARN_ON(!q_chip)) return -ENODEV; @@ -840,7 +840,9 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) == QPNP_PIN_MODE_DIG_IN) { rc = regmap_read(q_chip->regmap, Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val); - buf[0] = (u8)val; + if (rc) + return rc; + buf = val; if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0) en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK; @@ -850,26 +852,23 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset) else /* MPP */ en_mask = Q_REG_STATUS1_MPP_EN_MASK; - if (!(buf[0] & en_mask)) + if (!(buf & en_mask)) return -EPERM; - return buf[0] & Q_REG_STATUS1_VAL_MASK; - } else { - if (is_gpio_lv_mv(q_spec)) { - shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; - mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; - } else { - shift = Q_REG_OUT_INVERT_SHIFT; - mask = Q_REG_OUT_INVERT_MASK; - reg = q_spec->regs[Q_REG_I_MODE_CTL]; - } + return buf & Q_REG_STATUS1_VAL_MASK; + } - ret_val = (reg & mask) >> shift; - return ret_val; + if (is_gpio_lv_mv(q_spec)) { + shift = Q_REG_DIG_OUT_SRC_INVERT_SHIFT; + mask = Q_REG_DIG_OUT_SRC_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_DIG_OUT_SRC_CTL]; + } else { + shift = Q_REG_OUT_INVERT_SHIFT; + mask = Q_REG_OUT_INVERT_MASK; + reg = q_spec->regs[Q_REG_I_MODE_CTL]; } - return 0; + return (reg & mask) >> shift; } static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, @@ -905,7 +904,7 @@ static int __qpnp_pin_set(struct qpnp_pin_chip *q_chip, static void qpnp_pin_set(struct gpio_chip *gpio_chip, - unsigned offset, int value) + unsigned int offset, int value) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -950,7 +949,7 @@ static int qpnp_pin_set_mode(struct qpnp_pin_chip *q_chip, } static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, - unsigned offset) + unsigned int offset) { struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); struct qpnp_pin_spec *q_spec; @@ -966,8 +965,7 @@ static int qpnp_pin_direction_input(struct gpio_chip *gpio_chip, } static int qpnp_pin_direction_output(struct gpio_chip *gpio_chip, - unsigned offset, - int val) + unsigned int offset, int val) { int rc; struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev); @@ -1343,7 +1341,7 @@ struct qpnp_pin_debugfs_args { const char *filename; }; -static struct qpnp_pin_debugfs_args dfs_args[] = { +static struct qpnp_pin_debugfs_args dfs_args[Q_NUM_PARAMS] = { { Q_PIN_CFG_MODE, "mode" }, { Q_PIN_CFG_OUTPUT_TYPE, "output_type" }, { Q_PIN_CFG_INVERT, "invert" }, @@ -1371,8 +1369,6 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) struct dentry *dfs, *dfs_io_dir; int i, j, rc; - BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args)); - q_chip->dfs_dir = debugfs_create_dir(q_chip->gpio_chip.label, driver_dfs_dir); if (q_chip->dfs_dir == NULL) { @@ -1403,12 +1399,8 @@ static int qpnp_pin_debugfs_create(struct qpnp_pin_chip *q_chip) continue; params[type] = type; - dfs = debugfs_create_file( - filename, - S_IRUGO | S_IWUSR, - dfs_io_dir, - &q_spec->params[type], - &qpnp_pin_fops); + dfs = debugfs_create_file(filename, 0644, dfs_io_dir, + &q_spec->params[type], &qpnp_pin_fops); if (dfs == NULL) goto dfs_err; } @@ -1674,7 +1666,7 @@ static int qpnp_pin_remove(struct platform_device *pdev) return qpnp_pin_free_chip(q_chip); } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-pin", }, {} diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 15c4b9427f8e..7e2e3aa91fce 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -1639,7 +1639,8 @@ static void a5xx_pwrlevel_change_settings(struct adreno_device *adreno_dev, static void a5xx_clk_set_options(struct adreno_device *adreno_dev, const char *name, struct clk *clk) { - if (adreno_is_a540(adreno_dev)) { + /* Handle clock settings for GFX PSCBCs */ + if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev)) { if (!strcmp(name, "mem_iface_clk")) { clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH); clk_set_flags(clk, CLKFLAG_NORETAIN_MEM); diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 413a3098b0ef..7f93ab8fa8d4 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -917,11 +917,15 @@ int kgsl_pwrscale_init(struct device *dev, const char *governor) "qcom,enable-midframe-timer")) { kgsl_midframe = kzalloc( sizeof(struct kgsl_midframe_info), GFP_KERNEL); - hrtimer_init(&kgsl_midframe->timer, - CLOCK_MONOTONIC, HRTIMER_MODE_REL); - kgsl_midframe->timer.function = - kgsl_pwrscale_midframe_timer; - kgsl_midframe->device = device; + if (kgsl_midframe) { + hrtimer_init(&kgsl_midframe->timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + kgsl_midframe->timer.function = + kgsl_pwrscale_midframe_timer; + kgsl_midframe->device = device; + } else + KGSL_PWR_ERR(device, + "Failed to enable-midframe-timer feature\n"); } /* diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index b7504fdd380f..57145ea72e90 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -165,10 +165,19 @@ #define FAB_ID_GF 0x30 #define FAB_ID_SMIC 0x11 +#define FAB_ID_660_GF 0x0 +#define FAB_ID_660_TSMC 0x2 +#define FAB_ID_660_MX 0x3 #define FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV 1303168 #define FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C 3784 #define FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV 1338433 #define FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C 3655 +#define FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV 1309001 +#define FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C 3403 +#define FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV 1295898 +#define FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C 3596 +#define FG_ADC_RR_CHG_TEMP_660_MGNA_OFFSET_UV 1314779 +#define FG_RR_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C 3496 #define FG_ADC_RR_CHG_TEMP_OFFSET_MILLI_DEGC 25000 #define FG_ADC_RR_CHG_THRESHOLD_SCALE 4 @@ -388,23 +397,70 @@ static int rradc_post_process_die_temp(struct rradc_chip *chip, return 0; } +static int rradc_get_660_fab_coeff(struct rradc_chip *chip, + int64_t *offset, int64_t *slope) +{ + switch (chip->pmic_fab_id->fab_id) { + case FAB_ID_660_GF: + *offset = FG_ADC_RR_CHG_TEMP_660_GF_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_GF_SLOPE_UV_PER_C; + break; + case FAB_ID_660_TSMC: + *offset = FG_ADC_RR_CHG_TEMP_660_SMIC_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_SMIC_SLOPE_UV_PER_C; + break; + default: + *offset = FG_ADC_RR_CHG_TEMP_660_MGNA_OFFSET_UV; + *slope = FG_RR_CHG_TEMP_660_MGNA_SLOPE_UV_PER_C; + } + + return 0; +} + +static int rradc_get_8998_fab_coeff(struct rradc_chip *chip, + int64_t *offset, int64_t *slope) +{ + switch (chip->pmic_fab_id->fab_id) { + case FAB_ID_GF: + *offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; + *slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + break; + case FAB_ID_SMIC: + *offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; + *slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + break; + default: + return -EINVAL; + } + + return 0; +} + static int rradc_post_process_chg_temp_hot(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 adc_code, int *result_millidegc) { int64_t uv = 0, offset = 0, slope = 0; + int rc = 0; if (chip->revid_dev_node) { - switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_GF: - offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + switch (chip->pmic_fab_id->pmic_subtype) { + case PM660_SUBTYPE: + rc = rradc_get_660_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; - case FAB_ID_SMIC: - offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + case PMI8998_SUBTYPE: + rc = rradc_get_8998_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; default: + pr_err("No PMIC subtype found\n"); return -EINVAL; } } else { @@ -444,18 +500,26 @@ static int rradc_post_process_chg_temp(struct rradc_chip *chip, int *result_millidegc) { int64_t uv = 0, offset = 0, slope = 0; + int rc = 0; if (chip->revid_dev_node) { - switch (chip->pmic_fab_id->fab_id) { - case FAB_ID_GF: - offset = FG_ADC_RR_CHG_TEMP_GF_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_GF_SLOPE_UV_PER_C; + switch (chip->pmic_fab_id->pmic_subtype) { + case PM660_SUBTYPE: + rc = rradc_get_660_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; - case FAB_ID_SMIC: - offset = FG_ADC_RR_CHG_TEMP_SMIC_OFFSET_UV; - slope = FG_ADC_RR_CHG_TEMP_SMIC_SLOPE_UV_PER_C; + case PMI8998_SUBTYPE: + rc = rradc_get_8998_fab_coeff(chip, &offset, &slope); + if (rc < 0) { + pr_err("Unable to get fab id coefficients\n"); + return -EINVAL; + } break; default: + pr_err("No PMIC subtype found\n"); return -EINVAL; } } else { diff --git a/drivers/iio/adc/qcom-tadc.c b/drivers/iio/adc/qcom-tadc.c index 4a56847a43e7..9241288c1d43 100644 --- a/drivers/iio/adc/qcom-tadc.c +++ b/drivers/iio/adc/qcom-tadc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -10,6 +10,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "TADC: %s: " fmt, __func__ + #include <linux/iio/iio.h> #include <linux/interrupt.h> #include <linux/module.h> @@ -101,8 +103,16 @@ enum tadc_chan_id { TADC_BATT_P, TADC_INPUT_P, TADC_THERM1_THR1, + TADC_THERM1_THR2, + TADC_THERM1_THR3, + TADC_THERM1_THR4, TADC_THERM2_THR1, + TADC_THERM2_THR2, + TADC_THERM2_THR3, TADC_DIE_TEMP_THR1, + TADC_DIE_TEMP_THR2, + TADC_DIE_TEMP_THR3, + TADC_CHAN_ID_MAX, }; #define TADC_CHAN(_name, _type, _channel, _info_mask) \ @@ -164,19 +174,39 @@ static const struct iio_chan_spec tadc_iio_chans[] = { [TADC_INPUT_P] = TADC_POWER_CHAN( "input", TADC_INPUT_P), [TADC_THERM1_THR1] = TADC_THERM_CHAN( - "batt_hot", TADC_THERM1_THR1), + "batt_warm", TADC_THERM1_THR1), + [TADC_THERM1_THR2] = TADC_THERM_CHAN( + "batt_cool", TADC_THERM1_THR2), + [TADC_THERM1_THR3] = TADC_THERM_CHAN( + "batt_cold", TADC_THERM1_THR3), + [TADC_THERM1_THR4] = TADC_THERM_CHAN( + "batt_hot", TADC_THERM1_THR4), [TADC_THERM2_THR1] = TADC_THERM_CHAN( - "skin_hot", TADC_THERM2_THR1), + "skin_lb", TADC_THERM2_THR1), + [TADC_THERM2_THR2] = TADC_THERM_CHAN( + "skin_ub", TADC_THERM2_THR2), + [TADC_THERM2_THR3] = TADC_THERM_CHAN( + "skin_rst", TADC_THERM2_THR3), [TADC_DIE_TEMP_THR1] = TADC_THERM_CHAN( - "die_hot", TADC_DIE_TEMP_THR1), + "die_lb", TADC_DIE_TEMP_THR1), + [TADC_DIE_TEMP_THR2] = TADC_THERM_CHAN( + "die_ub", TADC_DIE_TEMP_THR2), + [TADC_DIE_TEMP_THR3] = TADC_THERM_CHAN( + "die_rst", TADC_DIE_TEMP_THR3), +}; + +struct tadc_therm_thr { + int addr_lo; + int addr_hi; }; struct tadc_chan_data { - s32 scale; - s32 offset; - u32 rbias; - const struct tadc_pt *table; - size_t tablesize; + s32 scale; + s32 offset; + u32 rbias; + const struct tadc_pt *table; + size_t tablesize; + struct tadc_therm_thr thr[4]; }; struct tadc_chip { @@ -186,6 +216,7 @@ struct tadc_chip { u32 tadc_cmp_base; struct tadc_chan_data chans[TADC_NUM_CH]; struct completion eoc_complete; + struct mutex write_lock; }; struct tadc_pt { @@ -238,14 +269,24 @@ static const struct tadc_pt tadc_therm_3450b_68k[] = { { 1712127, -40000 }, }; -static int tadc_read(struct tadc_chip *chip, u16 reg, u8 *val, - size_t val_count) +static bool tadc_is_reg_locked(struct tadc_chip *chip, u16 reg) +{ + if ((reg & 0xFF00) == chip->tadc_cmp_base) + return true; + + if (reg == TADC_HWTRIG_CONV_CH_EN_REG(chip)) + return true; + + return false; +} + +static int tadc_read(struct tadc_chip *chip, u16 reg, u8 *val, size_t count) { int rc = 0; - rc = regmap_bulk_read(chip->regmap, reg, val, val_count); + rc = regmap_bulk_read(chip->regmap, reg, val, count); if (rc < 0) - pr_err("Couldn't read %04x rc=%d\n", reg, rc); + pr_err("Couldn't read 0x%04x rc=%d\n", reg, rc); return rc; } @@ -254,57 +295,108 @@ static int tadc_write(struct tadc_chip *chip, u16 reg, u8 data) { int rc = 0; + mutex_lock(&chip->write_lock); + if (tadc_is_reg_locked(chip, reg)) { + rc = regmap_write(chip->regmap, (reg & 0xFF00) | 0xD0, 0xA5); + if (rc < 0) { + pr_err("Couldn't unlock secure register rc=%d\n", rc); + goto unlock; + } + } + rc = regmap_write(chip->regmap, reg, data); - if (rc < 0) - pr_err("Couldn't write %02x to %04x rc=%d\n", - data, reg, rc); + if (rc < 0) { + pr_err("Couldn't write 0x%02x to 0x%04x rc=%d\n", + data, reg, rc); + goto unlock; + } + +unlock: + mutex_unlock(&chip->write_lock); + return rc; +} +static int tadc_bulk_write(struct tadc_chip *chip, u16 reg, u8 *data, + size_t count) +{ + int rc = 0, i; + + mutex_lock(&chip->write_lock); + for (i = 0; i < count; ++i, ++reg) { + if (tadc_is_reg_locked(chip, reg)) { + rc = regmap_write(chip->regmap, + (reg & 0xFF00) | 0xD0, 0xA5); + if (rc < 0) { + pr_err("Couldn't unlock secure register rc=%d\n", + rc); + goto unlock; + } + } + + rc = regmap_write(chip->regmap, reg, data[i]); + if (rc < 0) { + pr_err("Couldn't write 0x%02x to 0x%04x rc=%d\n", + data[i], reg, rc); + goto unlock; + } + } +unlock: + mutex_unlock(&chip->write_lock); return rc; } -static int tadc_lerp(const struct tadc_pt *pts, size_t tablesize, s32 input, - s32 *output) +static int tadc_lerp(const struct tadc_pt *pts, size_t size, bool inv, + s32 input, s32 *output) { int i; s64 temp; + bool ascending; if (pts == NULL) { pr_err("Table is NULL\n"); return -EINVAL; } - if (tablesize < 1) { + if (size < 1) { pr_err("Table has no entries\n"); return -ENOENT; } - if (tablesize == 1) { - *output = pts[0].y; + if (size == 1) { + *output = inv ? pts[0].x : pts[0].y; return 0; } - if (pts[0].x > pts[1].x) { - pr_err("Table is not in acending order\n"); - return -EINVAL; - } - - if (input <= pts[0].x) { - *output = pts[0].y; + ascending = inv ? (pts[0].y < pts[1].y) : (pts[0].x < pts[1].x); + if (ascending ? (input <= (inv ? pts[0].y : pts[0].x)) : + (input >= (inv ? pts[0].y : pts[0].x))) { + *output = inv ? pts[0].x : pts[0].y; return 0; } - if (input >= pts[tablesize - 1].x) { - *output = pts[tablesize - 1].y; + if (ascending ? (input >= (inv ? pts[size - 1].y : pts[size - 1].x)) : + (input <= (inv ? pts[size - 1].y : pts[size - 1].x))) { + *output = inv ? pts[size - 1].x : pts[size - 1].y; return 0; } - for (i = 1; i < tablesize; i++) - if (input <= pts[i].x) + for (i = 1; i < size; i++) + if (ascending ? (input <= (inv ? pts[i].y : pts[i].x)) : + (input >= (inv ? pts[i].y : pts[i].x))) break; - temp = (s64)(pts[i].y - pts[i - 1].y) * (s64)(input - pts[i - 1].x); - temp = div_s64(temp, pts[i].x - pts[i - 1].x); - *output = temp + pts[i - 1].y; + if (inv) { + temp = (s64)(pts[i].x - pts[i - 1].x) * + (s64)(input - pts[i - 1].y); + temp = div_s64(temp, pts[i].y - pts[i - 1].y); + *output = temp + pts[i - 1].x; + } else { + temp = (s64)(pts[i].y - pts[i - 1].y) * + (s64)(input - pts[i - 1].x); + temp = div_s64(temp, pts[i].x - pts[i - 1].x); + *output = temp + pts[i - 1].y; + } + return 0; } @@ -321,15 +413,32 @@ static int tadc_lerp(const struct tadc_pt *pts, size_t tablesize, s32 input, * Combine these equations and solve for Rtherm * Rtherm = (ADC * Rbias) / (1024 - ADC) */ -static int tadc_process_therm(const struct tadc_chan_data *chan_data, - s16 adc, s32 *result) +static int tadc_get_processed_therm(const struct tadc_chan_data *chan_data, + s16 adc, s32 *result) { - s64 rtherm; + s32 rtherm; - rtherm = (s64)adc * (s64)chan_data->rbias; - rtherm = div_s64(rtherm, TADC_RESOLUTION - adc); - return tadc_lerp(chan_data->table, chan_data->tablesize, rtherm, - result); + rtherm = div_s64((s64)adc * chan_data->rbias, TADC_RESOLUTION - adc); + return tadc_lerp(chan_data->table, chan_data->tablesize, false, rtherm, + result); +} + +static int tadc_get_raw_therm(const struct tadc_chan_data *chan_data, + int mdegc, int *result) +{ + int rc; + s32 rtherm; + + rc = tadc_lerp(chan_data->table, chan_data->tablesize, true, mdegc, + &rtherm); + if (rc < 0) { + pr_err("Couldn't interpolate %d\n rc=%d", mdegc, rc); + return rc; + } + + *result = div64_s64((s64)rtherm * TADC_RESOLUTION, + (s64)chan_data->rbias + rtherm); + return 0; } static int tadc_read_channel(struct tadc_chip *chip, u16 address, int *adc) @@ -339,12 +448,31 @@ static int tadc_read_channel(struct tadc_chip *chip, u16 address, int *adc) rc = tadc_read(chip, address, val, ARRAY_SIZE(val)); if (rc < 0) { - dev_err(chip->dev, "Couldn't read channel rc=%d\n", rc); + pr_err("Couldn't read channel rc=%d\n", rc); return rc; } - *adc = (s16)(val[0] | val[1] << BITS_PER_BYTE); - return 0; + /* the 10th bit is the sign bit for all channels */ + *adc = sign_extend32(val[0] | val[1] << BITS_PER_BYTE, 10); + return rc; +} + +static int tadc_write_channel(struct tadc_chip *chip, u16 address, int adc) +{ + u8 val[2]; + int rc; + + /* the 10th bit is the sign bit for all channels */ + adc = sign_extend32(adc, 10); + val[0] = (u8)adc; + val[1] = (u8)(adc >> BITS_PER_BYTE); + rc = tadc_bulk_write(chip, address, val, 2); + if (rc < 0) { + pr_err("Couldn't write to channel rc=%d\n", rc); + return rc; + } + + return rc; } #define CONVERSION_TIMEOUT_MS 100 @@ -356,8 +484,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) rc = tadc_read(chip, TADC_MBG_ERR_REG(chip), val, 1); if (rc < 0) { - dev_err(chip->dev, "Couldn't read mbg error status rc=%d\n", - rc); + pr_err("Couldn't read mbg error status rc=%d\n", rc); return rc; } @@ -368,8 +495,7 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) rc = tadc_write(chip, TADC_CONV_REQ_REG(chip), channels); if (rc < 0) { - dev_err(chip->dev, "Couldn't write conversion request rc=%d\n", - rc); + pr_err("Couldn't write conversion request rc=%d\n", rc); return rc; } @@ -379,21 +505,19 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) if (timeleft == 0) { rc = tadc_read(chip, TADC_SW_CH_CONV_REG(chip), val, 1); if (rc < 0) { - dev_err(chip->dev, "Couldn't read conversion status rc=%d\n", - rc); + pr_err("Couldn't read conversion status rc=%d\n", rc); return rc; } if (val[0] != channels) { - dev_err(chip->dev, "Conversion timed out\n"); + pr_err("Conversion timed out\n"); return -ETIMEDOUT; } } rc = tadc_read(chip, TADC_CH1_ADC_LO_REG(chip), val, ARRAY_SIZE(val)); if (rc < 0) { - dev_err(chip->dev, "Couldn't read adc channels rc=%d\n", - rc); + pr_err("Couldn't read adc channels rc=%d\n", rc); return rc; } @@ -404,84 +528,102 @@ static int tadc_do_conversion(struct tadc_chip *chip, u8 channels, s16 *adc) } static int tadc_read_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int *val, int *val2, - long mask) + struct iio_chan_spec const *chan, int *val, int *val2, + long mask) { struct tadc_chip *chip = iio_priv(indio_dev); - const struct tadc_chan_data *chan_data = &chip->chans[chan->channel]; - int rc = 0, offset = 0, scale, scale2, scale_type; + struct tadc_chan_data *chan_data = NULL; + int rc, offset = 0, scale, scale2, scale_type; s16 adc[TADC_NUM_CH]; switch (chan->channel) { case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: chan_data = &chip->chans[TADC_THERM1]; break; case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: chan_data = &chip->chans[TADC_THERM2]; break; case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: chan_data = &chip->chans[TADC_DIE_TEMP]; break; default: + if (chan->channel >= ARRAY_SIZE(chip->chans)) { + pr_err("Channel %d is out of bounds\n", chan->channel); + return -EINVAL; + } + + chan_data = &chip->chans[chan->channel]; break; } + if (!chan_data) + return -EINVAL; + switch (mask) { case IIO_CHAN_INFO_RAW: switch (chan->channel) { case TADC_THERM1_THR1: + case TADC_THERM2_THR1: + case TADC_DIE_TEMP_THR1: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH1_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read THERM1 threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[0].addr_lo, val); break; - case TADC_THERM2_THR1: + case TADC_THERM1_THR2: + case TADC_THERM2_THR2: + case TADC_DIE_TEMP_THR2: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH2_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read THERM2 threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[1].addr_lo, val); break; - case TADC_DIE_TEMP_THR1: + case TADC_THERM1_THR3: + case TADC_THERM2_THR3: + case TADC_DIE_TEMP_THR3: rc = tadc_read_channel(chip, - TADC_CMP_THR1_CH3_CMP_LO_REG(chip), val); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read DIE_TEMP threshold rc=%d\n", - rc); - return rc; - } + chan_data->thr[2].addr_lo, val); + break; + case TADC_THERM1_THR4: + rc = tadc_read_channel(chip, + chan_data->thr[3].addr_lo, val); break; default: rc = tadc_do_conversion(chip, BIT(chan->channel), adc); - if (rc < 0) { - dev_err(chip->dev, "Couldn't read channel %d\n", - chan->channel); - return rc; - } - *val = adc[chan->channel]; + if (rc >= 0) + *val = adc[chan->channel]; break; } + + if (rc < 0) { + pr_err("Couldn't read channel %d\n", chan->channel); + return rc; + } + return IIO_VAL_INT; case IIO_CHAN_INFO_PROCESSED: switch (chan->channel) { case TADC_THERM1: case TADC_THERM2: case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: rc = tadc_read_raw(indio_dev, chan, val, NULL, - IIO_CHAN_INFO_RAW); + IIO_CHAN_INFO_RAW); if (rc < 0) return rc; - rc = tadc_process_therm(chan_data, *val, val); + rc = tadc_get_processed_therm(chan_data, *val, val); if (rc < 0) { - dev_err(chip->dev, "Couldn't process 0x%04x from channel %d rc=%d\n", - *val, chan->channel, rc); + pr_err("Couldn't process 0x%04x from channel %d rc=%d\n", + *val, chan->channel, rc); return rc; } break; @@ -489,7 +631,8 @@ static int tadc_read_raw(struct iio_dev *indio_dev, rc = tadc_do_conversion(chip, BIT(TADC_BATT_I) | BIT(TADC_BATT_V), adc); if (rc < 0) { - dev_err(chip->dev, "Couldn't read battery current and voltage channels\n"); + pr_err("Couldn't read battery current and voltage channels rc=%d\n", + rc); return rc; } @@ -499,7 +642,8 @@ static int tadc_read_raw(struct iio_dev *indio_dev, rc = tadc_do_conversion(chip, BIT(TADC_INPUT_I) | BIT(TADC_INPUT_V), adc); if (rc < 0) { - dev_err(chip->dev, "Couldn't read input current and voltage channels\n"); + pr_err("Couldn't read input current and voltage channels rc=%d\n", + rc); return rc; } @@ -507,13 +651,13 @@ static int tadc_read_raw(struct iio_dev *indio_dev, break; default: rc = tadc_read_raw(indio_dev, chan, val, NULL, - IIO_CHAN_INFO_RAW); + IIO_CHAN_INFO_RAW); if (rc < 0) return rc; /* offset is optional */ rc = tadc_read_raw(indio_dev, chan, &offset, NULL, - IIO_CHAN_INFO_OFFSET); + IIO_CHAN_INFO_OFFSET); if (rc < 0) return rc; @@ -525,18 +669,20 @@ static int tadc_read_raw(struct iio_dev *indio_dev, break; case IIO_VAL_FRACTIONAL: *val = div_s64((s64)*val * scale + offset, - scale2); + scale2); break; default: return -EINVAL; } break; } + return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: switch (chan->channel) { case TADC_DIE_TEMP: case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: *val = chan_data->scale; return IIO_VAL_INT; case TADC_BATT_I: @@ -548,14 +694,134 @@ static int tadc_read_raw(struct iio_dev *indio_dev, *val2 = TADC_RESOLUTION; return IIO_VAL_FRACTIONAL; } + return -EINVAL; case IIO_CHAN_INFO_OFFSET: *val = chan_data->offset; return IIO_VAL_INT; } + return -EINVAL; } +static int tadc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, + long mask) +{ + struct tadc_chip *chip = iio_priv(indio_dev); + const struct tadc_chan_data *chan_data; + int rc, raw; + s32 rem; + + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: + chan_data = &chip->chans[TADC_THERM1]; + break; + case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: + chan_data = &chip->chans[TADC_THERM2]; + break; + case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: + chan_data = &chip->chans[TADC_DIE_TEMP]; + break; + default: + if (chan->channel >= ARRAY_SIZE(chip->chans)) { + pr_err("Channel %d is out of bounds\n", chan->channel); + return -EINVAL; + } + + chan_data = &chip->chans[chan->channel]; + break; + } + + if (!chan_data) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM1_THR2: + case TADC_THERM1_THR3: + case TADC_THERM1_THR4: + case TADC_THERM2_THR1: + case TADC_THERM2_THR2: + case TADC_THERM2_THR3: + rc = tadc_get_raw_therm(chan_data, val, &raw); + if (rc < 0) { + pr_err("Couldn't get raw value rc=%d\n", rc); + return rc; + } + break; + case TADC_DIE_TEMP_THR1: + case TADC_DIE_TEMP_THR2: + case TADC_DIE_TEMP_THR3: + /* DIV_ROUND_CLOSEST does not like negative numbers */ + raw = div_s64_rem(val - chan_data->offset, + chan_data->scale, &rem); + if (abs(rem) >= abs(chan_data->scale / 2)) + raw++; + break; + default: + return -EINVAL; + } + + rc = tadc_write_raw(indio_dev, chan, raw, 0, + IIO_CHAN_INFO_RAW); + if (rc < 0) { + pr_err("Couldn't write raw rc=%d\n", rc); + return rc; + } + + break; + case IIO_CHAN_INFO_RAW: + switch (chan->channel) { + case TADC_THERM1_THR1: + case TADC_THERM2_THR1: + case TADC_DIE_TEMP_THR1: + rc = tadc_write_channel(chip, + chan_data->thr[0].addr_lo, val); + break; + case TADC_THERM1_THR2: + case TADC_THERM2_THR2: + case TADC_DIE_TEMP_THR2: + rc = tadc_write_channel(chip, + chan_data->thr[1].addr_lo, val); + break; + case TADC_THERM1_THR3: + case TADC_THERM2_THR3: + case TADC_DIE_TEMP_THR3: + rc = tadc_write_channel(chip, + chan_data->thr[2].addr_lo, val); + break; + case TADC_THERM1_THR4: + rc = tadc_write_channel(chip, + chan_data->thr[3].addr_lo, val); + break; + default: + return -EINVAL; + } + + if (rc < 0) { + pr_err("Couldn't write channel %d\n", chan->channel); + return rc; + } + + break; + default: + return -EINVAL; + } + + return 0; +} + + static irqreturn_t handle_eoc(int irq, void *dev_id) { struct tadc_chip *chip = dev_id; @@ -587,72 +853,144 @@ static int tadc_parse_dt(struct tadc_chip *chip) for_each_available_child_of_node(node, child) { rc = of_property_read_u32(child, "reg", &chan_id); if (rc < 0) { - dev_err(chip->dev, "Couldn't find channel for %s rc=%d", - child->name, rc); + pr_err("Couldn't find channel for %s rc=%d", + child->name, rc); return rc; } if (chan_id > TADC_NUM_CH - 1) { - dev_err(chip->dev, "Channel %d is out of range [0, %d]\n", - chan_id, TADC_NUM_CH - 1); + pr_err("Channel %d is out of range [0, %d]\n", + chan_id, TADC_NUM_CH - 1); return -EINVAL; } chan_data = &chip->chans[chan_id]; - switch (chan_id) { - case TADC_THERM1: - case TADC_THERM2: + if (chan_id == TADC_THERM1 || chan_id == TADC_THERM2) { rc = of_property_read_u32(child, "qcom,rbias", &chan_data->rbias); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,rbias rc=%d\n", - rc); + pr_err("Couldn't read qcom,rbias rc=%d\n", rc); return rc; } rc = of_property_read_u32(child, "qcom,beta-coefficient", &beta); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,beta-coefficient rc=%d\n", - rc); + pr_err("Couldn't read qcom,beta-coefficient rc=%d\n", + rc); return rc; } rc = of_property_read_u32(child, "qcom,rtherm-at-25degc", &rtherm); if (rc < 0) { - dev_err(chip->dev, "Couldn't read qcom,rtherm-at-25degc rc=%d\n", + pr_err("Couldn't read qcom,rtherm-at-25degc rc=%d\n", rc); return rc; } rc = tadc_set_therm_table(chan_data, beta, rtherm); if (rc < 0) { - dev_err(chip->dev, "Couldn't set therm table rc=%d\n", - rc); + pr_err("Couldn't set therm table rc=%d\n", rc); return rc; } - break; - default: + } else { rc = of_property_read_s32(child, "qcom,scale", - &chan_data->scale); + &chan_data->scale); if (rc < 0) { - dev_err(chip->dev, "Couldn't read scale rc=%d\n", - rc); + pr_err("Couldn't read scale rc=%d\n", rc); return rc; } of_property_read_s32(child, "qcom,offset", - &chan_data->offset); - break; + &chan_data->offset); } } return rc; } +static int tadc_init_hw(struct tadc_chip *chip) +{ + int rc; + + chip->chans[TADC_THERM1].thr[0].addr_lo = + TADC_CMP_THR1_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[0].addr_hi = + TADC_CMP_THR1_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[1].addr_lo = + TADC_CMP_THR2_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[1].addr_hi = + TADC_CMP_THR2_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[2].addr_lo = + TADC_CMP_THR3_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[2].addr_hi = + TADC_CMP_THR3_CH1_CMP_HI_REG(chip); + chip->chans[TADC_THERM1].thr[3].addr_lo = + TADC_CMP_THR4_CH1_CMP_LO_REG(chip); + chip->chans[TADC_THERM1].thr[3].addr_hi = + TADC_CMP_THR4_CH1_CMP_HI_REG(chip); + + chip->chans[TADC_THERM2].thr[0].addr_lo = + TADC_CMP_THR1_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[0].addr_hi = + TADC_CMP_THR1_CH2_CMP_HI_REG(chip); + chip->chans[TADC_THERM2].thr[1].addr_lo = + TADC_CMP_THR2_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[1].addr_hi = + TADC_CMP_THR2_CH2_CMP_HI_REG(chip); + chip->chans[TADC_THERM2].thr[2].addr_lo = + TADC_CMP_THR3_CH2_CMP_LO_REG(chip); + chip->chans[TADC_THERM2].thr[2].addr_hi = + TADC_CMP_THR3_CH2_CMP_HI_REG(chip); + + chip->chans[TADC_DIE_TEMP].thr[0].addr_lo = + TADC_CMP_THR1_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[0].addr_hi = + TADC_CMP_THR1_CH3_CMP_HI_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[1].addr_lo = + TADC_CMP_THR2_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[1].addr_hi = + TADC_CMP_THR2_CH3_CMP_HI_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[2].addr_lo = + TADC_CMP_THR3_CH3_CMP_LO_REG(chip); + chip->chans[TADC_DIE_TEMP].thr[2].addr_hi = + TADC_CMP_THR3_CH3_CMP_HI_REG(chip); + + rc = tadc_write(chip, TADC_CMP_THR1_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + rc = tadc_write(chip, TADC_CMP_THR2_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + rc = tadc_write(chip, TADC_CMP_THR3_CMP_REG(chip), 0); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + /* enable all temperature hardware triggers */ + rc = tadc_write(chip, TADC_HWTRIG_CONV_CH_EN_REG(chip), + BIT(TADC_THERM1) | + BIT(TADC_THERM2) | + BIT(TADC_DIE_TEMP)); + if (rc < 0) { + pr_err("Couldn't enable hardware triggers rc=%d\n", rc); + return rc; + } + + return 0; +} + static const struct iio_info tadc_info = { .read_raw = &tadc_read_raw, + .write_raw = &tadc_write_raw, .driver_module = THIS_MODULE, }; @@ -661,7 +999,7 @@ static int tadc_probe(struct platform_device *pdev) struct device_node *node = pdev->dev.of_node; struct iio_dev *indio_dev; struct tadc_chip *chip; - int rc = 0, irq; + int rc, irq; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*chip)); if (!indio_dev) @@ -673,11 +1011,12 @@ static int tadc_probe(struct platform_device *pdev) rc = of_property_read_u32(node, "reg", &chip->tadc_base); if (rc < 0) { - dev_err(chip->dev, "Couldn't read base address rc=%d\n", rc); + pr_err("Couldn't read base address rc=%d\n", rc); return rc; } chip->tadc_cmp_base = chip->tadc_base + 0x100; + mutex_init(&chip->write_lock); chip->regmap = dev_get_regmap(chip->dev->parent, NULL); if (!chip->regmap) { pr_err("Couldn't get regmap\n"); @@ -690,6 +1029,12 @@ static int tadc_probe(struct platform_device *pdev) return rc; } + rc = tadc_init_hw(chip); + if (rc < 0) { + pr_err("Couldn't initialize hardware rc=%d\n", rc); + return rc; + } + irq = of_irq_get_byname(node, "eoc"); if (irq < 0) { pr_err("Couldn't get eoc irq rc=%d\n", irq); @@ -697,7 +1042,7 @@ static int tadc_probe(struct platform_device *pdev) } rc = devm_request_threaded_irq(chip->dev, irq, NULL, handle_eoc, - IRQF_ONESHOT, "eoc", chip); + IRQF_ONESHOT, "eoc", chip); if (rc < 0) { pr_err("Couldn't request irq %d rc=%d\n", irq, rc); return rc; @@ -711,10 +1056,12 @@ static int tadc_probe(struct platform_device *pdev) indio_dev->num_channels = ARRAY_SIZE(tadc_iio_chans); rc = devm_iio_device_register(chip->dev, indio_dev); - if (rc < 0) - dev_err(chip->dev, "Couldn't register IIO device rc=%d\n", rc); + if (rc < 0) { + pr_err("Couldn't register IIO device rc=%d\n", rc); + return rc; + } - return rc; + return 0; } static int tadc_remove(struct platform_device *pdev) diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c index 217e9306aa0f..407b2ef4d2e9 100644 --- a/drivers/iio/inkern.c +++ b/drivers/iio/inkern.c @@ -664,3 +664,21 @@ err_unlock: return ret; } EXPORT_SYMBOL_GPL(iio_write_channel_raw); + +int iio_write_channel_processed(struct iio_channel *chan, int val) +{ + int ret; + + mutex_lock(&chan->indio_dev->info_exist_lock); + if (chan->indio_dev->info == NULL) { + ret = -ENODEV; + goto err_unlock; + } + + ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_PROCESSED); +err_unlock: + mutex_unlock(&chan->indio_dev->info_exist_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(iio_write_channel_processed); diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 0fc18922801e..966227a3df1a 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -581,40 +581,6 @@ config LEDS_POWERNV depends on LEDS_CLASS depends on PPC_POWERNV depends on OF - -config LEDS_QPNP - tristate "Support for QPNP LEDs" - depends on LEDS_CLASS && SPMI - help - This driver supports the leds functionality of Qualcomm PNP PMIC. It - includes RGB Leds, WLED and Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp. - -config LEDS_QPNP_FLASH - tristate "Support for QPNP Flash LEDs" - depends on LEDS_CLASS && SPMI - help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash. - -config LEDS_QPNP_FLASH_V2 - tristate "Support for QPNP V2 Flash LEDs" - depends on LEDS_CLASS && MFD_SPMI_PMIC - help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash-v2. - -config LEDS_QPNP_WLED - tristate "Support for QPNP WLED" - depends on LEDS_CLASS && SPMI help This option enables support for the system LEDs present on PowerNV platforms. Say 'y' to enable this support in kernel. @@ -625,31 +591,38 @@ config LEDS_QPNP tristate "Support for QPNP LEDs" depends on LEDS_CLASS && SPMI help - This driver supports the leds functionality of Qualcomm PNP PMIC. It - includes RGB Leds, WLED and Flash Led. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp. + This driver supports the LED functionality of Qualcomm Technologies, + Inc. QPNP PMICs. It primarily supports controlling tri-color RGB + LEDs in both PWM and light pattern generator (LPG) modes. For older + PMICs, it also supports WLEDs and flash LEDs. config LEDS_QPNP_FLASH tristate "Support for QPNP Flash LEDs" depends on LEDS_CLASS && SPMI help - This driver supports the leds functionality of Qualcomm Technologies - PNP PMIC. It includes Flash Led. + This driver supports the flash LED functionality of Qualcomm + Technologies, Inc. QPNP PMICs. This driver supports PMICs up through + PM8994. It can configure the flash LED target current for several + independent channels. - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-flash. +config LEDS_QPNP_FLASH_V2 + tristate "Support for QPNP V2 Flash LEDs" + depends on LEDS_CLASS && MFD_SPMI_PMIC && !LEDS_QPNP_FLASH + help + This driver supports the flash V2 LED functionality of Qualcomm + Technologies, Inc. QPNP PMICs. This driver supports PMICs starting + from PMI8998. It can configure the flash LED target current for + several independent channels. It also supports various over current + and over temperature mitigation features. config LEDS_QPNP_WLED tristate "Support for QPNP WLED" depends on LEDS_CLASS && SPMI help - This driver supports the WLED (White LED) functionality of - Qualcomm Technologies PNP PMIC. WLED is used for display backlight. - - To compile this driver as a module, choose M here: the module will - be called leds-qpnp-wled. + This driver supports the WLED (White LED) functionality of Qualcomm + Technologies, Inc. QPNP PMICs. WLED is used for LCD backlight with + variable brightness. It also supports outputting the Avdd supply for + AMOLED displays. config LEDS_SYSCON bool "LED support for LEDs on system controllers" diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index b6aa4a87f31d..08809a93d4b2 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -1166,6 +1166,10 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, struct qpnp_flash_led *led = NULL; int rc; + /* + * strncmp() must be used here since a prefix comparison is required + * in order to support names like led:switch_0 and led:flash_1. + */ if (!strncmp(led_cdev->name, "led:switch", strlen("led:switch"))) { snode = container_of(led_cdev, struct flash_switch_data, cdev); led = dev_get_drvdata(&snode->pdev->dev); @@ -1214,8 +1218,7 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, /* sysfs attributes exported by flash_led */ static struct device_attribute qpnp_flash_led_attrs[] = { - __ATTR(max_current, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_max_current_show, NULL), + __ATTR(max_current, 0664, qpnp_flash_led_max_current_show, NULL), }; static int flash_led_psy_notifier_call(struct notifier_block *nb, diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c index 98dfa56add51..c27c0593cd10 100644 --- a/drivers/leds/leds-qpnp-flash.c +++ b/drivers/leds/leds-qpnp-flash.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -608,10 +608,9 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, } /* - * When charging is enabled, enforce this new - * enabelment sequence to reduce fuel gauge - * resolution reading. - */ + * When charging is enabled, enforce this new enablement + * sequence to reduce fuel gauge reading resolution. + */ if (led->charging_enabled) { rc = qpnp_led_masked_write(led, FLASH_MODULE_ENABLE_CTRL(led->base), @@ -637,10 +636,10 @@ qpnp_flash_led_get_max_avail_current(struct flash_node_data *flash_node, max_curr_avail_ma = (prop.intval / FLASH_LED_UA_PER_MA); } - /* When thermal mitigation is available, this logic - * will execute, to derate current based on PMIC die - * temperature. - */ + /* + * When thermal mitigation is available, this logic will execute to + * derate current based upon the PMIC die temperature. + */ if (led->pdata->die_current_derate_en) { chg_temp_milidegc = qpnp_flash_led_get_die_temp(led); if (chg_temp_milidegc < 0) @@ -797,21 +796,14 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev, } static struct device_attribute qpnp_flash_led_attrs[] = { - __ATTR(strobe, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_led_strobe_type_store), - __ATTR(reg_dump, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_dump_regs_show, - NULL), - __ATTR(enable_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_flash_led_current_derate_store), - __ATTR(max_allowed_current, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_flash_led_max_current_show, - NULL), - __ATTR(enable_die_temp_current_derate, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_flash_led_die_temp_store), + __ATTR(strobe, 0664, NULL, qpnp_led_strobe_type_store), + __ATTR(reg_dump, 0664, qpnp_flash_led_dump_regs_show, NULL), + __ATTR(enable_current_derate, 0664, NULL, + qpnp_flash_led_current_derate_store), + __ATTR(max_allowed_current, 0664, qpnp_flash_led_max_current_show, + NULL), + __ATTR(enable_die_temp_current_derate, 0664, NULL, + qpnp_flash_led_die_temp_store), }; static int qpnp_flash_led_get_thermal_derate_rate(const char *rate) @@ -1771,8 +1763,6 @@ error_enable_gpio: flash_node->flash_on = false; mutex_unlock(&led->flash_led_lock); - - return; } static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, @@ -1823,8 +1813,6 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev, } queue_work(led->ordered_workq, &flash_node->work); - - return; } static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led) @@ -2359,26 +2347,24 @@ static int qpnp_flash_led_parse_common_dt( dev_err(&led->pdev->dev, "Unable to acquire pinctrl\n"); led->pinctrl = NULL; return 0; - } else { - led->gpio_state_active = - pinctrl_lookup_state(led->pinctrl, "flash_led_enable"); - if (IS_ERR_OR_NULL(led->gpio_state_active)) { - dev_err(&led->pdev->dev, - "Can not lookup LED active state\n"); - devm_pinctrl_put(led->pinctrl); - led->pinctrl = NULL; - return PTR_ERR(led->gpio_state_active); - } - led->gpio_state_suspend = - pinctrl_lookup_state(led->pinctrl, + } + + led->gpio_state_active = pinctrl_lookup_state(led->pinctrl, + "flash_led_enable"); + if (IS_ERR_OR_NULL(led->gpio_state_active)) { + dev_err(&led->pdev->dev, "Cannot lookup LED active state\n"); + devm_pinctrl_put(led->pinctrl); + led->pinctrl = NULL; + return PTR_ERR(led->gpio_state_active); + } + + led->gpio_state_suspend = pinctrl_lookup_state(led->pinctrl, "flash_led_disable"); - if (IS_ERR_OR_NULL(led->gpio_state_suspend)) { - dev_err(&led->pdev->dev, - "Can not lookup LED disable state\n"); - devm_pinctrl_put(led->pinctrl); - led->pinctrl = NULL; - return PTR_ERR(led->gpio_state_suspend); - } + if (IS_ERR_OR_NULL(led->gpio_state_suspend)) { + dev_err(&led->pdev->dev, "Cannot lookup LED disable state\n"); + devm_pinctrl_put(led->pinctrl); + led->pinctrl = NULL; + return PTR_ERR(led->gpio_state_suspend); } return 0; @@ -2408,13 +2394,10 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) return rc; } - led = devm_kzalloc(&pdev->dev, sizeof(struct qpnp_flash_led), - GFP_KERNEL); - if (!led) { - dev_err(&pdev->dev, - "Unable to allocate memory for flash LED\n"); + led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); + if (!led) return -ENOMEM; - } + led->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!led->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -2426,13 +2409,9 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) led->current_addr = FLASH_LED0_CURRENT(led->base); led->current2_addr = FLASH_LED1_CURRENT(led->base); - led->pdata = devm_kzalloc(&pdev->dev, - sizeof(struct flash_led_platform_data), GFP_KERNEL); - if (!led->pdata) { - dev_err(&pdev->dev, - "Unable to allocate memory for platform data\n"); + led->pdata = devm_kzalloc(&pdev->dev, sizeof(*led->pdata), GFP_KERNEL); + if (!led->pdata) return -ENOMEM; - } led->peripheral_type = (u8)qpnp_flash_led_get_peripheral_type(led); if (led->peripheral_type < 0) { @@ -2571,21 +2550,21 @@ static int qpnp_flash_led_probe(struct platform_device *pdev) } led->dbgfs_root = root; - file = debugfs_create_file("enable_debug", S_IRUSR | S_IWUSR, root, - led, &flash_led_dfs_dbg_feature_fops); + file = debugfs_create_file("enable_debug", 0600, root, led, + &flash_led_dfs_dbg_feature_fops); if (!file) { pr_err("error creating 'enable_debug' entry\n"); goto error_led_debugfs; } - file = debugfs_create_file("latched", S_IRUSR | S_IWUSR, root, led, + file = debugfs_create_file("latched", 0600, root, led, &flash_led_dfs_latched_reg_fops); if (!file) { pr_err("error creating 'latched' entry\n"); goto error_led_debugfs; } - file = debugfs_create_file("strobe", S_IRUSR | S_IWUSR, root, led, + file = debugfs_create_file("strobe", 0600, root, led, &flash_led_dfs_strobe_reg_fops); if (!file) { pr_err("error creating 'strobe' entry\n"); @@ -2639,7 +2618,7 @@ static int qpnp_flash_led_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-flash-led",}, { }, }; diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c index 718badb16ea1..1e24c79c3f0a 100644 --- a/drivers/leds/leds-qpnp-wled.c +++ b/drivers/leds/leds-qpnp-wled.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -721,10 +721,11 @@ static ssize_t qpnp_wled_ramp_ms_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_wled *wled = dev_get_drvdata(dev); - int data; + int data, rc; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; wled->ramp_ms = data; return count; @@ -744,10 +745,11 @@ static ssize_t qpnp_wled_ramp_step_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct qpnp_wled *wled = dev_get_drvdata(dev); - int data; + int data, rc; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; wled->ramp_step = data; return count; @@ -832,8 +834,9 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev, int data, i, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; for (i = 0; i < wled->num_strings; i++) { if (data < QPNP_WLED_FS_CURR_MIN_UA) @@ -869,24 +872,15 @@ static ssize_t qpnp_wled_fs_curr_ua_store(struct device *dev, /* sysfs attributes exported by wled */ static struct device_attribute qpnp_wled_attrs[] = { - __ATTR(dump_regs, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_dump_regs_show, - NULL), - __ATTR(dim_mode, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_dim_mode_show, - qpnp_wled_dim_mode_store), - __ATTR(fs_curr_ua, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_fs_curr_ua_show, - qpnp_wled_fs_curr_ua_store), - __ATTR(start_ramp, (S_IRUGO | S_IWUSR | S_IWGRP), - NULL, - qpnp_wled_ramp_store), - __ATTR(ramp_ms, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_ramp_ms_show, - qpnp_wled_ramp_ms_store), - __ATTR(ramp_step, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_wled_ramp_step_show, - qpnp_wled_ramp_step_store), + __ATTR(dump_regs, 0664, qpnp_wled_dump_regs_show, NULL), + __ATTR(dim_mode, 0664, qpnp_wled_dim_mode_show, + qpnp_wled_dim_mode_store), + __ATTR(fs_curr_ua, 0664, qpnp_wled_fs_curr_ua_show, + qpnp_wled_fs_curr_ua_store), + __ATTR(start_ramp, 0664, NULL, qpnp_wled_ramp_store), + __ATTR(ramp_ms, 0664, qpnp_wled_ramp_ms_show, qpnp_wled_ramp_ms_store), + __ATTR(ramp_step, 0664, qpnp_wled_ramp_step_show, + qpnp_wled_ramp_step_store), }; /* worker for setting wled brightness */ @@ -2196,7 +2190,7 @@ static int qpnp_wled_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-wled",}, { }, }; diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c index d16fcc3c97ae..85a6be824485 100644 --- a/drivers/leds/leds-qpnp.c +++ b/drivers/leds/leds-qpnp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -666,7 +666,7 @@ static int qpnp_wled_set(struct qpnp_led_data *led) return rc; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY + 10); } else if (led->wled_cfg->pmic_version == PMIC_VER_8941) { if (led->wled_cfg->num_physical_strings <= WLED_THREE_STRINGS) { @@ -696,7 +696,8 @@ static int qpnp_wled_set(struct qpnp_led_data *led) "WLED write sink reg failed"); return rc; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, + WLED_OVP_DELAY + 10); } else { val = WLED_DISABLE_ALL_SINKS; rc = regmap_write(led->regmap, @@ -724,7 +725,8 @@ static int qpnp_wled_set(struct qpnp_led_data *led) msleep(WLED_OVP_DELAY_LOOP); tries++; } - usleep_range(WLED_OVP_DELAY, WLED_OVP_DELAY); + usleep_range(WLED_OVP_DELAY, + WLED_OVP_DELAY + 10); } } @@ -859,9 +861,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) led->mpp_cfg->enable = true; if (led->cdev.brightness < led->mpp_cfg->min_brightness) { - dev_warn(&led->pdev->dev, - "brightness is less than supported..." \ - "set to minimum supported\n"); + dev_warn(&led->pdev->dev, "brightness is less than supported, set to minimum supported\n"); led->cdev.brightness = led->mpp_cfg->min_brightness; } @@ -940,9 +940,7 @@ static int qpnp_mpp_set(struct qpnp_led_data *led) LED_MPP_EN_CTRL(led->base), LED_MPP_EN_MASK, LED_MPP_EN_ENABLE); if (rc) { - dev_err(&led->pdev->dev, - "Failed to write led enable " \ - "reg\n"); + dev_err(&led->pdev->dev, "Failed to write led enable reg\n"); goto err_mpp_reg_write; } } else { @@ -1102,30 +1100,27 @@ static int qpnp_flash_regulator_operate(struct qpnp_led_data *led, bool on) led_array[i].flash_cfg-> flash_wa_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash wa regulator" - "enable failed(%d)\n", + dev_err(&led->pdev->dev, "Flash wa regulator enable failed(%d)\n", rc); return rc; } } rc = regulator_enable( - led_array[i].flash_cfg->\ - flash_boost_reg); + led_array[i].flash_cfg->flash_boost_reg); if (rc) { if (led_array[i].flash_cfg-> flash_wa_reg_get) - /* Disable flash wa regulator + /* + * Disable flash wa regulator * when flash boost regulator * enable fails */ regulator_disable( led_array[i].flash_cfg-> flash_wa_reg); - dev_err(&led->pdev->dev, - "Flash boost regulator enable" - "failed(%d)\n", rc); + dev_err(&led->pdev->dev, "Flash boost regulator enable failed(%d)\n", + rc); return rc; } led->flash_cfg->flash_on = true; @@ -1150,12 +1145,11 @@ regulator_turn_off: rc); } - rc = regulator_disable(led_array[i].flash_cfg->\ - flash_boost_reg); + rc = regulator_disable( + led_array[i].flash_cfg->flash_boost_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash boost regulator disable" - "failed(%d)\n", rc); + dev_err(&led->pdev->dev, "Flash boost regulator disable failed(%d)\n", + rc); return rc; } if (led_array[i].flash_cfg->flash_wa_reg_get) { @@ -1163,9 +1157,7 @@ regulator_turn_off: led_array[i].flash_cfg-> flash_wa_reg); if (rc) { - dev_err(&led->pdev->dev, - "Flash_wa regulator" - "disable failed(%d)\n", + dev_err(&led->pdev->dev, "Flash_wa regulator disable failed(%d)\n", rc); return rc; } @@ -1416,7 +1408,8 @@ static int qpnp_flash_set(struct qpnp_led_data *led) /* * Add 1ms delay for bharger enter stable state */ - usleep_range(FLASH_RAMP_UP_DELAY_US, FLASH_RAMP_UP_DELAY_US); + usleep_range(FLASH_RAMP_UP_DELAY_US, + FLASH_RAMP_UP_DELAY_US + 10); if (!led->flash_cfg->strobe_type) led->flash_cfg->trigger_flash &= @@ -1480,7 +1473,8 @@ static int qpnp_flash_set(struct qpnp_led_data *led) * Disable module after ramp down complete for stable * behavior */ - usleep_range(FLASH_RAMP_UP_DELAY_US, FLASH_RAMP_UP_DELAY_US); + usleep_range(FLASH_RAMP_UP_DELAY_US, + FLASH_RAMP_UP_DELAY_US + 10); rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base), @@ -1658,9 +1652,7 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led) KPDBL_MODULE_EN_MASK, KPDBL_MODULE_DIS); if (rc) { - dev_err(&led->pdev->dev, - "Failed to write led" - " enable reg\n"); + dev_err(&led->pdev->dev, "Failed to write led enable reg\n"); return rc; } } @@ -1854,8 +1846,6 @@ static void qpnp_led_work(struct work_struct *work) struct qpnp_led_data, work); __qpnp_led_work(led, led->cdev.brightness); - - return; } static int qpnp_led_set_max_brightness(struct qpnp_led_data *led) @@ -1942,7 +1932,7 @@ static int qpnp_wled_init(struct qpnp_led_data *led) return -EINVAL; } - if ((led->max_current > WLED_MAX_CURR)) { + if (led->max_current > WLED_MAX_CURR) { dev_err(&led->pdev->dev, "Invalid max current\n"); return -EINVAL; } @@ -3048,7 +3038,7 @@ static int qpnp_get_common_configs(struct qpnp_led_data *led, rc = of_property_read_string(node, "qcom,default-state", &temp_string); if (!rc) { - if (strncmp(temp_string, "on", sizeof("on")) == 0) + if (strcmp(temp_string, "on") == 0) led->default_on = true; } else if (rc != -EINVAL) return rc; @@ -3075,10 +3065,8 @@ static int qpnp_get_config_wled(struct qpnp_led_data *led, led->wled_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct wled_config_data), GFP_KERNEL); - if (!led->wled_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->wled_cfg) return -ENOMEM; - } rc = regmap_read(led->regmap, PMIC_VERSION_REG, &tmp); if (rc) { @@ -3161,10 +3149,8 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led, led->flash_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct flash_config_data), GFP_KERNEL); - if (!led->flash_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->flash_cfg) return -ENOMEM; - } rc = regmap_read(led->regmap, FLASH_PERIPHERAL_SUBTYPE(led->base), &tmp); @@ -3297,23 +3283,23 @@ static int qpnp_get_config_flash(struct qpnp_led_data *led, } return 0; - } else { - rc = of_property_read_u32(node, "qcom,duration", &val); - if (!rc) - led->flash_cfg->duration = (u8)((val - 10) / 10); - else if (rc == -EINVAL) - led->flash_cfg->duration = FLASH_DURATION_200ms; - else - goto error_get_flash_reg; - - rc = of_property_read_u32(node, "qcom,current", &val); - if (!rc) - led->flash_cfg->current_prgm = (val * - FLASH_MAX_LEVEL / led->max_current); - else - goto error_get_flash_reg; } + rc = of_property_read_u32(node, "qcom,duration", &val); + if (!rc) + led->flash_cfg->duration = (u8)((val - 10) / 10); + else if (rc == -EINVAL) + led->flash_cfg->duration = FLASH_DURATION_200ms; + else + goto error_get_flash_reg; + + rc = of_property_read_u32(node, "qcom,current", &val); + if (!rc) + led->flash_cfg->current_prgm = val * FLASH_MAX_LEVEL + / led->max_current; + else + goto error_get_flash_reg; + rc = of_property_read_u32(node, "qcom,headroom", &val); if (!rc) led->flash_cfg->headroom = (u8) val; @@ -3512,11 +3498,11 @@ bad_lpg_params: static int qpnp_led_get_mode(const char *mode) { - if (strncmp(mode, "manual", strlen(mode)) == 0) + if (strcmp(mode, "manual") == 0) return MANUAL_MODE; - else if (strncmp(mode, "pwm", strlen(mode)) == 0) + else if (strcmp(mode, "pwm") == 0) return PWM_MODE; - else if (strncmp(mode, "lpg", strlen(mode)) == 0) + else if (strcmp(mode, "lpg") == 0) return LPG_MODE; else return -EINVAL; @@ -3532,10 +3518,8 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led, led->kpdbl_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct kpdbl_config_data), GFP_KERNEL); - if (!led->kpdbl_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->kpdbl_cfg) return -ENOMEM; - } rc = of_property_read_string(node, "qcom,mode", &mode); if (!rc) { @@ -3547,11 +3531,9 @@ static int qpnp_get_config_kpdbl(struct qpnp_led_data *led, led->kpdbl_cfg->pwm_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct pwm_config_data), GFP_KERNEL); - if (!led->kpdbl_cfg->pwm_cfg) { - dev_err(&led->pdev->dev, - "Unable to allocate memory\n"); + if (!led->kpdbl_cfg->pwm_cfg) return -ENOMEM; - } + led->kpdbl_cfg->pwm_cfg->mode = led_mode; led->kpdbl_cfg->pwm_cfg->default_mode = led_mode; } else { @@ -3589,10 +3571,8 @@ static int qpnp_get_config_rgb(struct qpnp_led_data *led, led->rgb_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct rgb_config_data), GFP_KERNEL); - if (!led->rgb_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->rgb_cfg) return -ENOMEM; - } if (led->id == QPNP_ID_RGB_RED) led->rgb_cfg->enable = RGB_LED_ENABLE_RED; @@ -3641,10 +3621,8 @@ static int qpnp_get_config_mpp(struct qpnp_led_data *led, led->mpp_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct mpp_config_data), GFP_KERNEL); - if (!led->mpp_cfg) { - dev_err(&led->pdev->dev, "Unable to allocate memory\n"); + if (!led->mpp_cfg) return -ENOMEM; - } if (of_find_property(of_get_parent(node), "mpp-power-supply", NULL)) { led->mpp_cfg->mpp_reg = @@ -3770,11 +3748,8 @@ static int qpnp_get_config_gpio(struct qpnp_led_data *led, led->gpio_cfg = devm_kzalloc(&led->pdev->dev, sizeof(struct gpio_config_data), GFP_KERNEL); - if (!led->gpio_cfg) { - dev_err(&led->pdev->dev, - "Unable to allocate memory gpio struct\n"); + if (!led->gpio_cfg) return -ENOMEM; - } led->gpio_cfg->source_sel = LED_GPIO_SOURCE_SEL_DEFAULT; rc = of_property_read_u32(node, "qcom,source-sel", &val); @@ -3823,12 +3798,10 @@ static int qpnp_leds_probe(struct platform_device *pdev) if (!num_leds) return -ECHILD; - led_array = devm_kzalloc(&pdev->dev, - (sizeof(struct qpnp_led_data) * num_leds), GFP_KERNEL); - if (!led_array) { - dev_err(&pdev->dev, "Unable to allocate memory\n"); + led_array = devm_kcalloc(&pdev->dev, num_leds, sizeof(*led_array), + GFP_KERNEL); + if (!led_array) return -ENOMEM; - } for_each_child_of_node(node, temp) { led = &led_array[parsed_leds]; @@ -3881,24 +3854,22 @@ static int qpnp_leds_probe(struct platform_device *pdev) rc = qpnp_get_common_configs(led, temp); if (rc) { - dev_err(&led->pdev->dev, - "Failure reading common led configuration," \ - " rc = %d\n", rc); + dev_err(&led->pdev->dev, "Failure reading common led configuration, rc = %d\n", + rc); goto fail_id_check; } led->cdev.brightness_set = qpnp_led_set; led->cdev.brightness_get = qpnp_led_get; - if (strncmp(led_label, "wled", sizeof("wled")) == 0) { + if (strcmp(led_label, "wled") == 0) { rc = qpnp_get_config_wled(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, "Unable to read wled config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "flash", sizeof("flash")) - == 0) { + } else if (strcmp(led_label, "flash") == 0) { if (!of_find_property(node, "flash-boost-supply", NULL)) regulator_probe = true; rc = qpnp_get_config_flash(led, temp, ®ulator_probe); @@ -3907,14 +3878,14 @@ static int qpnp_leds_probe(struct platform_device *pdev) "Unable to read flash config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "rgb", sizeof("rgb")) == 0) { + } else if (strcmp(led_label, "rgb") == 0) { rc = qpnp_get_config_rgb(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, "Unable to read rgb config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "mpp", sizeof("mpp")) == 0) { + } else if (strcmp(led_label, "mpp") == 0) { rc = qpnp_get_config_mpp(led, temp); if (rc < 0) { dev_err(&led->pdev->dev, @@ -3928,7 +3899,7 @@ static int qpnp_leds_probe(struct platform_device *pdev) "Unable to read gpio config data\n"); goto fail_id_check; } - } else if (strncmp(led_label, "kpdbl", sizeof("kpdbl")) == 0) { + } else if (strcmp(led_label, "kpdbl") == 0) { bitmap_zero(kpdbl_leds_in_use, NUM_KPDBL_LEDS); is_kpdbl_master_turn_on = false; rc = qpnp_get_config_kpdbl(led, temp); @@ -4113,8 +4084,8 @@ static int qpnp_leds_remove(struct platform_device *pdev) case QPNP_ID_FLASH1_LED0: case QPNP_ID_FLASH1_LED1: if (led_array[i].flash_cfg->flash_reg_get) - regulator_put(led_array[i].flash_cfg-> \ - flash_boost_reg); + regulator_put( + led_array[i].flash_cfg->flash_boost_reg); if (led_array[i].flash_cfg->torch_enable) if (!led_array[i].flash_cfg->no_smbb_support) regulator_put(led_array[i]. @@ -4126,49 +4097,49 @@ static int qpnp_leds_remove(struct platform_device *pdev) case QPNP_ID_RGB_GREEN: case QPNP_ID_RGB_BLUE: if (led_array[i].rgb_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].rgb_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); - } else if (led_array[i].rgb_cfg->pwm_cfg->mode\ - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); + } else if (led_array[i].rgb_cfg->pwm_cfg->mode + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); break; case QPNP_ID_LED_MPP: if (!led_array[i].mpp_cfg->pwm_cfg) break; if (led_array[i].mpp_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].mpp_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); - } else if (led_array[i].mpp_cfg->pwm_cfg->mode\ - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev->\ - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); + } else if (led_array[i].mpp_cfg->pwm_cfg->mode + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); if (led_array[i].mpp_cfg->mpp_reg) regulator_put(led_array[i].mpp_cfg->mpp_reg); break; case QPNP_ID_KPDBL: if (led_array[i].kpdbl_cfg->pwm_cfg->mode == PWM_MODE) - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &pwm_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &pwm_attr_group); if (led_array[i].kpdbl_cfg->pwm_cfg->use_blink) { - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &blink_attr_group); - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &lpg_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &blink_attr_group); + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); } else if (led_array[i].kpdbl_cfg->pwm_cfg->mode - == LPG_MODE) - sysfs_remove_group(&led_array[i].cdev.dev-> - kobj, &lpg_attr_group); + == LPG_MODE) + sysfs_remove_group(&led_array[i].cdev.dev->kobj, + &lpg_attr_group); break; default: dev_err(&led_array->pdev->dev, @@ -4182,7 +4153,7 @@ static int qpnp_leds_remove(struct platform_device *pdev) } #ifdef CONFIG_OF -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,leds-qpnp",}, { }, }; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index dd7d1c836809..1ddf51407884 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -846,6 +846,7 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, enum msm_vfe_dual_hw_type dual_hw_type; enum msm_vfe_dual_hw_ms_type ms_type; unsigned long flags; + int i; struct master_slave_resource_info *ms_res = &vfe_dev->common_data->ms_resource; @@ -869,8 +870,27 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, src_info->dual_hw_ms_info.index)) { pr_err("Frame out of sync on vfe %d\n", vfe_dev->pdev->id); - msm_isp_halt_send_error(vfe_dev, - ISP_EVENT_BUF_FATAL_ERROR); + /* + * set this isp as async mode to force + *it sync again at the next sof + */ + src_info->dual_hw_ms_info.sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + /* + * set the other isp as async mode to force + * it sync again at the next sof + */ + for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { + if (ms_res->src_info[i] == NULL) + continue; + if (src_info == ms_res->src_info[i] || + ms_res->src_info[i]-> + active == 0) + continue; + ms_res->src_info[i]->dual_hw_ms_info. + sync_state = + MSM_ISP_DUAL_CAM_ASYNC; + } } ms_res->src_sof_mask |= (1 << src_info->dual_hw_ms_info.index); diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c index e3022b2dbe34..55a743737c59 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,6 +58,7 @@ #define TRUE 1 #define FALSE 0 +#define MAX_LANE_COUNT 4 #define CSID_TIMEOUT msecs_to_jiffies(100) #undef CDBG @@ -284,6 +285,12 @@ static int msm_csid_config(struct csid_device *csid_dev, csid_params->lane_assign); CDBG("%s csid_params phy_sel = %d\n", __func__, csid_params->phy_sel); + if ((csid_params->lane_cnt == 0) || + (csid_params->lane_cnt > MAX_LANE_COUNT)) { + pr_err("%s:%d invalid lane count = %d\n", + __func__, __LINE__, csid_params->lane_cnt); + return -EINVAL; + } csid_dev->csid_lane_cnt = csid_params->lane_cnt; rc = msm_csid_reset(csid_dev); diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c index 9048d54bed38..1f92186feeef 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c @@ -30,6 +30,7 @@ #include "sde_rotator_base.h" #include "sde_rotator_util.h" #include "sde_rotator_trace.h" +#include "sde_rotator_debug.h" static inline u64 fudge_factor(u64 val, u32 numer, u32 denom) { @@ -237,6 +238,8 @@ static u32 get_ot_limit(u32 reg_off, u32 bit_off, exit: SDEROT_DBG("ot_lim=%d\n", ot_lim); + SDEROT_EVTLOG(params->width, params->height, params->fmt, params->fps, + ot_lim); return ot_lim; } @@ -248,6 +251,7 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) params->reg_off_vbif_lim_conf; u32 bit_off_vbif_lim_conf = (params->xin_id % 4) * 8; u32 reg_val; + u32 sts; bool forced_on; ot_lim = get_ot_limit( @@ -258,6 +262,16 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) if (ot_lim == 0) goto exit; + if (params->rotsts_base && params->rotsts_busy_mask) { + sts = readl_relaxed(params->rotsts_base); + if (sts & params->rotsts_busy_mask) { + SDEROT_ERR( + "Rotator still busy, should not modify VBIF\n"); + SDEROT_EVTLOG_TOUT_HANDLER( + "rot", "vbif_dbg_bus", "panic"); + } + } + trace_rot_perf_set_ot(params->num, params->xin_id, ot_lim); forced_on = force_on_xin_clk(params->bit_off_mdp_clk_ctrl, @@ -283,6 +297,7 @@ void sde_mdp_set_ot_limit(struct sde_mdp_set_ot_params *params) force_on_xin_clk(params->bit_off_mdp_clk_ctrl, params->reg_off_mdp_clk_ctrl, false); + SDEROT_EVTLOG(params->num, params->xin_id, ot_lim); exit: return; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h index c04e71f459d1..a7c1e890758e 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h @@ -39,6 +39,8 @@ struct sde_mdp_set_ot_params { u32 reg_off_vbif_lim_conf; u32 reg_off_mdp_clk_ctrl; u32 bit_off_mdp_clk_ctrl; + char __iomem *rotsts_base; + u32 rotsts_busy_mask; }; enum sde_bus_vote_type { diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c index 29215c1a5910..e9988400b729 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c @@ -1237,14 +1237,16 @@ static int sde_rotator_calc_perf(struct sde_rot_mgr *mgr, perf->rdot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, - config->input.format, max_fps, true); + config->input.format, config->frame_rate, true); perf->wrot_limit = sde_mdp_get_ot_limit( config->input.width, config->input.height, - config->input.format, max_fps, false); + config->input.format, config->frame_rate, false); SDEROT_DBG("clk:%lu, rdBW:%d, wrBW:%d, rdOT:%d, wrOT:%d\n", perf->clk_rate, read_bw, write_bw, perf->rdot_limit, perf->wrot_limit); + SDEROT_EVTLOG(perf->clk_rate, read_bw, write_bw, perf->rdot_limit, + perf->wrot_limit); return 0; } diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_pipe.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_pipe.c index 3d84389513f1..5f886d7f1af2 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_pipe.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_pipe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -350,7 +350,7 @@ static int sde_mdp_src_addr_setup(struct sde_mdp_pipe *pipe, static void sde_mdp_set_ot_limit_pipe(struct sde_mdp_pipe *pipe) { - struct sde_mdp_set_ot_params ot_params; + struct sde_mdp_set_ot_params ot_params = {0,}; ot_params.xin_id = pipe->xin_id; ot_params.num = pipe->num; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_wb.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_wb.c index f9dc34167c59..863dfb09ad0f 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_wb.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r1_wb.c @@ -402,7 +402,7 @@ static int sde_mdp_wb_wait4comp(struct sde_mdp_ctl *ctl, void *arg) static void sde_mdp_set_ot_limit_wb(struct sde_mdp_writeback_ctx *ctx) { - struct sde_mdp_set_ot_params ot_params; + struct sde_mdp_set_ot_params ot_params = {0,}; ot_params.xin_id = ctx->xin_id; ot_params.num = ctx->wb_num; diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index 3bb8399da4bf..d7fb167ab49f 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -339,6 +339,8 @@ static void sde_hw_rotator_disable_irq(struct sde_hw_rotator *rot) */ static void sde_hw_rotator_dump_status(struct sde_hw_rotator *rot) { + struct sde_rot_data_type *mdata = sde_rot_get_mdata(); + SDEROT_ERR( "op_mode = %x, int_en = %x, int_status = %x\n", SDE_ROTREG_READ(rot->mdss_base, @@ -370,6 +372,10 @@ static void sde_hw_rotator_dump_status(struct sde_hw_rotator *rot) "UBWC decode status = %x, UBWC encode status = %x\n", SDE_ROTREG_READ(rot->mdss_base, ROT_SSPP_UBWC_ERROR_STATUS), SDE_ROTREG_READ(rot->mdss_base, ROT_WB_UBWC_ERROR_STATUS)); + + SDEROT_ERR("VBIF XIN HALT status = %x VBIF AXI HALT status = %x\n", + SDE_VBIF_READ(mdata, MMSS_VBIF_XIN_HALT_CTRL1), + SDE_VBIF_READ(mdata, MMSS_VBIF_AXI_HALT_CTRL1)); } /** @@ -1689,7 +1695,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, item->input.width, item->input.height, item->output.width, item->output.height, entry->src_buf.p[0].addr, entry->dst_buf.p[0].addr, - item->input.format, item->output.format); + item->input.format, item->output.format, + entry->perf->config.frame_rate); if (mdata->default_ot_rd_limit) { struct sde_mdp_set_ot_params ot_params; @@ -1708,6 +1715,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, ot_params.fmt = ctx->is_traffic_shaping ? SDE_PIX_FMT_ABGR_8888 : entry->perf->config.input.format; + ot_params.rotsts_base = rot->mdss_base + ROTTOP_STATUS; + ot_params.rotsts_busy_mask = ROT_BUSY_BIT; sde_mdp_set_ot_limit(&ot_params); } @@ -1728,6 +1737,8 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw, ot_params.fmt = ctx->is_traffic_shaping ? SDE_PIX_FMT_ABGR_8888 : entry->perf->config.input.format; + ot_params.rotsts_base = rot->mdss_base + ROTTOP_STATUS; + ot_params.rotsts_busy_mask = ROT_BUSY_BIT; sde_mdp_set_ot_limit(&ot_params); } diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index f958cf13f1e3..a20252f08f44 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1782,6 +1782,7 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) struct msm_vidc_inst *inst; int rc = 0; struct hfi_device *hdev; + struct vb2_buf_entry *temp, *next; if (!q || !q->drv_priv) { dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); return -EINVAL; @@ -1824,6 +1825,19 @@ static int msm_vdec_start_streaming(struct vb2_queue *q, unsigned int count) } stream_start_failed: + if (rc) { + mutex_lock(&inst->pendingq.lock); + list_for_each_entry_safe(temp, next, &inst->pendingq.list, + list) { + if (temp->vb->type == q->type) { + vb2_buffer_done(temp->vb, + VB2_BUF_STATE_QUEUED); + list_del(&temp->list); + kfree(temp); + } + } + mutex_unlock(&inst->pendingq.lock); + } return rc; } diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index 6127c03df581..c909511db251 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1048,9 +1048,9 @@ static struct msm_vidc_ctrl msm_venc_ctrls[] = { .id = V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE, .name = "Set Encoder performance mode", .type = V4L2_CTRL_TYPE_INTEGER, - .minimum = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY, + .minimum = V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT, .maximum = V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE, - .default_value = V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY, + .default_value = V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT, .step = 1, .qmenu = NULL, }, @@ -1666,9 +1666,10 @@ static int msm_venc_toggle_hier_p(struct msm_vidc_inst *inst, int layers) static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst) { - u32 rc = 0; - u32 prop_id = 0, power_save_min = 0, power_save_max = 0, inst_load = 0; + u32 rc = 0, height = 0, width = 0; + u32 prop_id = 0, hq_max = 0, power_conf = 0, inst_load = 0; void *pdata = NULL; + bool set_by_client = false, enable_low_power = false; struct hfi_device *hdev = NULL; enum hal_perf_mode venc_mode; enum load_calc_quirks quirks = LOAD_CALC_IGNORE_TURBO_LOAD | @@ -1679,20 +1680,38 @@ static inline int msm_venc_power_save_mode_enable(struct msm_vidc_inst *inst) return -EINVAL; } + hdev = inst->core->device; inst_load = msm_comm_get_inst_load(inst, quirks); - power_save_min = inst->capability.mbs_per_sec_power_save.min; - power_save_max = inst->capability.mbs_per_sec_power_save.max; + hq_max = inst->capability.mbs_per_sec.max; + power_conf = inst->core->resources.power_conf; + height = inst->prop.height[CAPTURE_PORT]; + width = inst->prop.width[CAPTURE_PORT]; - if (!power_save_min || !power_save_max) - return rc; + switch (msm_comm_g_ctrl_for_id(inst, + V4L2_CID_MPEG_VIDC_VIDEO_PERF_MODE)) { + case V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY: + case V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE: + set_by_client = true; + break; + } - hdev = inst->core->device; - if (inst_load >= power_save_min && inst_load <= power_save_max) { + if (inst_load > hq_max) { + dprintk(VIDC_INFO, "Setting low power w.r.t core limitation\n"); + enable_low_power = true; + } else if (!set_by_client) { + if (power_conf && width * height >= power_conf) { + dprintk(VIDC_INFO, + "Setting low power w.r.t system power recommendation\n"); + enable_low_power = true; + } + } + + if (enable_low_power) { prop_id = HAL_CONFIG_VENC_PERF_MODE; venc_mode = HAL_PERF_MODE_POWER_SAVE; pdata = &venc_mode; rc = call_hfi_op(hdev, session_set_property, - (void *)inst->session, prop_id, pdata); + (void *)inst->session, prop_id, pdata); if (rc) { dprintk(VIDC_ERR, "%s: Failed to set power save mode for inst: %pK\n", @@ -1758,6 +1777,7 @@ static int msm_venc_start_streaming(struct vb2_queue *q, unsigned int count) { struct msm_vidc_inst *inst; int rc = 0; + struct vb2_buf_entry *temp, *next; if (!q || !q->drv_priv) { dprintk(VIDC_ERR, "Invalid input, q = %pK\n", q); return -EINVAL; @@ -1795,6 +1815,19 @@ static int msm_venc_start_streaming(struct vb2_queue *q, unsigned int count) } stream_start_failed: + if (rc) { + mutex_lock(&inst->pendingq.lock); + list_for_each_entry_safe(temp, next, &inst->pendingq.list, + list) { + if (temp->vb->type == q->type) { + vb2_buffer_done(temp->vb, + VB2_BUF_STATE_QUEUED); + list_del(&temp->list); + kfree(temp); + } + } + mutex_unlock(&inst->pendingq.lock); + } return rc; } @@ -3143,7 +3176,6 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) break; } pdata = &venc_mode; - break; case V4L2_CID_MPEG_VIDC_VIDEO_HIER_B_NUM_LAYERS: if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index b36e3739e43b..662dcf7c8303 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -720,6 +720,7 @@ int msm_vidc_release_buffers(void *instance, int buffer_type) struct buffer_info *bi, *dummy; struct v4l2_buffer buffer_info; struct v4l2_plane plane[VIDEO_MAX_PLANES]; + struct vb2_buf_entry *temp, *next; int i, rc = 0; if (!inst) @@ -807,6 +808,15 @@ free_and_unmap: } } mutex_unlock(&inst->registeredbufs.lock); + + mutex_lock(&inst->pendingq.lock); + list_for_each_entry_safe(temp, next, &inst->pendingq.list, list) { + if (temp->vb->type == buffer_type) { + list_del(&temp->list); + kfree(temp); + } + } + mutex_unlock(&inst->pendingq.lock); return rc; } EXPORT_SYMBOL(msm_vidc_release_buffers); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index a3080be8cd7a..022c776a6096 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1084,6 +1084,13 @@ int read_platform_resources_from_dt( goto err_load_max_hw_load; } + rc = of_property_read_u32(pdev->dev.of_node, "qcom,power-conf", + &res->power_conf); + if (rc) { + dprintk(VIDC_DBG, + "Failed to read power configuration: %d\n", rc); + } + rc = msm_vidc_populate_legacy_context_bank(res); if (rc) { dprintk(VIDC_ERR, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index 734586a3f76c..03b31d7fd9d1 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -173,6 +173,7 @@ struct msm_vidc_platform_resources { uint32_t imem_size; enum imem_type imem_type; uint32_t max_load; + uint32_t power_conf; struct platform_device *pdev; struct regulator_set regulator_set; struct clock_set clock_set; diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c index c7c4da22139d..0f25932d8855 100644 --- a/drivers/net/ethernet/msm/ecm_ipa.c +++ b/drivers/net/ethernet/msm/ecm_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -9,7 +9,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - #include <linux/debugfs.h> #include <linux/errno.h> #include <linux/etherdevice.h> @@ -106,10 +105,6 @@ enum ecm_ipa_operation { * struct ecm_ipa_dev - main driver context parameters * @net: network interface struct implemented by this driver * @directory: debugfs directory for various debuging switches - * @tx_enable: flag that enable/disable Tx path to continue to IPA - * @rx_enable: flag that enable/disable Rx path to continue to IPA - * @rm_enable: flag that enable/disable Resource manager request prior to Tx - * @dma_enable: flag that allow on-the-fly DMA mode for IPA * @eth_ipv4_hdr_hdl: saved handle for ipv4 header-insertion table * @eth_ipv6_hdr_hdl: saved handle for ipv6 header-insertion table * @usb_to_ipa_hdl: save handle for IPA pipe operations @@ -129,10 +124,6 @@ enum ecm_ipa_operation { */ struct ecm_ipa_dev { struct net_device *net; - u32 tx_enable; - u32 rx_enable; - u32 rm_enable; - bool dma_enable; struct dentry *directory; uint32_t eth_ipv4_hdr_hdl; uint32_t eth_ipv6_hdr_hdl; @@ -167,32 +158,16 @@ static void ecm_ipa_rm_notify(void *user_data, enum ipa_rm_event event, static struct net_device_stats *ecm_ipa_get_stats(struct net_device *net); static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx); -static bool rx_filter(struct sk_buff *skb); -static bool tx_filter(struct sk_buff *skb); -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx); static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx); static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx); static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, struct net_device *net); -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file); -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file); -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos); -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos); static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos); static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx); static void ecm_ipa_debugfs_destroy(struct ecm_ipa_dev *ecm_ipa_ctx); static int ecm_ipa_ep_registers_cfg(u32 usb_to_ipa_hdl, u32 ipa_to_usb_hdl); -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client); static int ecm_ipa_set_device_ethernet_addr(u8 *dev_ethaddr, u8 device_ethaddr[]); static enum ecm_ipa_state ecm_ipa_next_state(enum ecm_ipa_state current_state, @@ -210,22 +185,11 @@ static const struct net_device_ops ecm_ipa_netdev_ops = { .ndo_get_stats = ecm_ipa_get_stats, }; -const struct file_operations ecm_ipa_debugfs_dma_ops = { - .open = ecm_ipa_debugfs_dma_open, - .read = ecm_ipa_debugfs_enable_read, - .write = ecm_ipa_debugfs_enable_write_dma, -}; - const struct file_operations ecm_ipa_debugfs_atomic_ops = { .open = ecm_ipa_debugfs_atomic_open, .read = ecm_ipa_debugfs_atomic_read, }; -const struct file_operations ecm_ipa_debugfs_stall_ops = { - .open = ecm_ipa_debugfs_stall_open, - .write = ecm_ipa_debugfs_stall_write, -}; - static void ecm_ipa_msg_free_cb(void *buff, u32 len, u32 type) { kfree(buff); @@ -286,9 +250,6 @@ int ecm_ipa_init(struct ecm_ipa_params *params) ECM_IPA_DEBUG("ecm_ipa_ctx (private) = %p\n", ecm_ipa_ctx); ecm_ipa_ctx->net = net; - ecm_ipa_ctx->tx_enable = true; - ecm_ipa_ctx->rx_enable = true; - ecm_ipa_ctx->rm_enable = true; ecm_ipa_ctx->outstanding_high = DEFAULT_OUTSTANDING_HIGH; ecm_ipa_ctx->outstanding_low = DEFAULT_OUTSTANDING_LOW; atomic_set(&ecm_ipa_ctx->outstanding_pkts, 0); @@ -604,12 +565,6 @@ static netdev_tx_t ecm_ipa_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (unlikely(tx_filter(skb))) { - dev_kfree_skb_any(skb); - ECM_IPA_DEBUG("packet got filtered out on Tx path\n"); - status = NETDEV_TX_OK; - goto out; - } ret = resource_request(ecm_ipa_ctx); if (ret) { ECM_IPA_DEBUG("Waiting to resource\n"); @@ -683,11 +638,6 @@ static void ecm_ipa_packet_receive_notify(void *priv, skb->dev = ecm_ipa_ctx->net; skb->protocol = eth_type_trans(skb, ecm_ipa_ctx->net); - if (rx_filter(skb)) { - ECM_IPA_DEBUG("packet got filtered out on Rx path\n"); - dev_kfree_skb_any(skb); - return; - } result = netif_rx(skb); if (result) @@ -1150,42 +1100,15 @@ static void ecm_ipa_destory_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_LOG_EXIT(); } -static bool rx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->rx_enable; -} - -static bool tx_filter(struct sk_buff *skb) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = netdev_priv(skb->dev); - return !ecm_ipa_ctx->tx_enable; -} - -static bool rm_enabled(struct ecm_ipa_dev *ecm_ipa_ctx) -{ - return ecm_ipa_ctx->rm_enable; -} - static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx) { - int result = 0; - - if (!rm_enabled(ecm_ipa_ctx)) - goto out; - result = ipa_rm_inactivity_timer_request_resource( - IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return result; + return ipa_rm_inactivity_timer_request_resource( + IPA_RM_RESOURCE_STD_ECM_PROD); } static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx) { - if (!rm_enabled(ecm_ipa_ctx)) - goto out; ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_STD_ECM_PROD); -out: - return; } /** @@ -1258,45 +1181,6 @@ static void ecm_ipa_tx_timeout(struct net_device *net) net->stats.tx_errors++; } -static int ecm_ipa_debugfs_stall_open(struct inode *inode, - struct file *file) -{ - ECM_IPA_LOG_ENTRY(); - - ECM_IPA_LOG_EXIT(); - - return 0; -} - -static ssize_t ecm_ipa_debugfs_stall_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - u32 cmdq_cfg_mmio_phy = 0xFD4E3038; - void *cmdq_cfg_mmio_virt; - int result; - bool val = 0; - - ECM_IPA_LOG_ENTRY(); - - file->private_data = &val; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - - cmdq_cfg_mmio_virt = ioremap(cmdq_cfg_mmio_phy, sizeof(u32)); - if (!cmdq_cfg_mmio_virt) { - ECM_IPA_ERROR("fail on mmio for cmdq_cfg_mmio_phy=0x%x", - cmdq_cfg_mmio_phy); - return result; - } - - iowrite32(val, cmdq_cfg_mmio_virt); - ECM_IPA_DEBUG("Value %d was written to cfgq", val); - - ECM_IPA_LOG_EXIT(); - - return result; - -} - static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) { struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; @@ -1306,78 +1190,6 @@ static int ecm_ipa_debugfs_atomic_open(struct inode *inode, struct file *file) return 0; } -static ssize_t ecm_ipa_debugfs_enable_write_dma(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = file->private_data; - int result; - ECM_IPA_LOG_ENTRY(); - file->private_data = &ecm_ipa_ctx->dma_enable; - result = ecm_ipa_debugfs_enable_write(file, buf, count, ppos); - if (ecm_ipa_ctx->dma_enable) - ecm_ipa_ep_registers_dma_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->ipa_to_usb_client); - else - ecm_ipa_ep_registers_cfg(ecm_ipa_ctx->usb_to_ipa_hdl, - ecm_ipa_ctx->usb_to_ipa_hdl); - ECM_IPA_LOG_EXIT(); - return result; -} - -static int ecm_ipa_debugfs_dma_open(struct inode *inode, struct file *file) -{ - struct ecm_ipa_dev *ecm_ipa_ctx = inode->i_private; - ECM_IPA_LOG_ENTRY(); - file->private_data = ecm_ipa_ctx; - ECM_IPA_LOG_EXIT(); - return 0; -} - -static ssize_t ecm_ipa_debugfs_enable_write(struct file *file, - const char __user *buf, size_t count, loff_t *ppos) -{ - unsigned long missing; - char input; - bool *enable = file->private_data; - if (count != sizeof(input) + 1) { - ECM_IPA_ERROR("wrong input length(%zd)\n", count); - return -EINVAL; - } - if (!buf) { - ECM_IPA_ERROR("Bad argument\n"); - return -EINVAL; - } - missing = copy_from_user(&input, buf, 1); - if (missing) - return -EFAULT; - ECM_IPA_DEBUG("input received %c\n", input); - *enable = input - '0'; - ECM_IPA_DEBUG("value was set to %d\n", *enable); - return count; -} - -static ssize_t ecm_ipa_debugfs_enable_read(struct file *file, - char __user *ubuf, size_t count, loff_t *ppos) -{ - int nbytes; - int size = 0; - int ret; - loff_t pos; - u8 enable_str[sizeof(char)*3] = {0}; - bool *enable = file->private_data; - pos = *ppos; - nbytes = scnprintf(enable_str, sizeof(enable_str), "%d\n", *enable); - ret = simple_read_from_buffer(ubuf, count, ppos, enable_str, nbytes); - if (ret < 0) { - ECM_IPA_ERROR("simple_read_from_buffer problem\n"); - return ret; - } - size += ret; - count -= nbytes; - *ppos = pos + size; - return size; -} - static ssize_t ecm_ipa_debugfs_atomic_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { @@ -1394,7 +1206,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) { const mode_t flags_read_write = S_IRUGO | S_IWUGO; const mode_t flags_read_only = S_IRUGO; - const mode_t flags_write_only = S_IWUGO; struct dentry *file; ECM_IPA_LOG_ENTRY(); @@ -1407,24 +1218,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create debugfs directory entry\n"); goto fail_directory; } - file = debugfs_create_bool("tx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->tx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs tx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rx_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rx_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rx file\n"); - goto fail_file; - } - file = debugfs_create_bool("rm_enable", flags_read_write, - ecm_ipa_ctx->directory, &ecm_ipa_ctx->rm_enable); - if (!file) { - ECM_IPA_ERROR("could not create debugfs rm file\n"); - goto fail_file; - } file = debugfs_create_u8("outstanding_high", flags_read_write, ecm_ipa_ctx->directory, &ecm_ipa_ctx->outstanding_high); if (!file) { @@ -1437,13 +1230,6 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) ECM_IPA_ERROR("could not create outstanding_low file\n"); goto fail_file; } - file = debugfs_create_file("dma_enable", flags_read_write, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_dma_ops); - if (!file) { - ECM_IPA_ERROR("could not create debugfs dma file\n"); - goto fail_file; - } file = debugfs_create_file("outstanding", flags_read_only, ecm_ipa_ctx->directory, ecm_ipa_ctx, &ecm_ipa_debugfs_atomic_ops); @@ -1452,14 +1238,7 @@ static int ecm_ipa_debugfs_init(struct ecm_ipa_dev *ecm_ipa_ctx) goto fail_file; } - file = debugfs_create_file("stall_ipa_rx_proc", flags_write_only, - ecm_ipa_ctx->directory, - ecm_ipa_ctx, &ecm_ipa_debugfs_stall_ops); - if (!file) { - ECM_IPA_ERROR("could not create stall_ipa_rx_proc file\n"); - goto fail_file; - } - + ECM_IPA_DEBUG("debugfs entries were created\n"); ECM_IPA_LOG_EXIT(); return 0; @@ -1523,46 +1302,6 @@ out: } /** - * ecm_ipa_ep_registers_dma_cfg() - configure the USB endpoints for ECM - * DMA - * @usb_to_ipa_hdl: handle received from ipa_connect - * - * This function will override the previous configuration - * which is needed for cores that does not support blocks logic - * Note that client handles are the actual pipe index - */ -static int ecm_ipa_ep_registers_dma_cfg(u32 usb_to_ipa_hdl, - enum ipa_client_type prod_client) -{ - int result = 0; - struct ipa_ep_cfg_mode cfg_mode; - u32 apps_to_ipa_hdl = 2; - - ECM_IPA_LOG_ENTRY(); - - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = prod_client; - result = ipa_cfg_ep_mode(apps_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure Apps to IPA\n"); - goto out; - } - memset(&cfg_mode, 0 , sizeof(cfg_mode)); - cfg_mode.mode = IPA_DMA; - cfg_mode.dst = IPA_CLIENT_A5_LAN_WAN_CONS; - result = ipa_cfg_ep_mode(usb_to_ipa_hdl, &cfg_mode); - if (result) { - ECM_IPA_ERROR("failed to configure USB to IPA\n"); - goto out; - } - ECM_IPA_DEBUG("end-point registers successfully configured\n"); -out: - ECM_IPA_LOG_EXIT(); - return result; -} - -/** * ecm_ipa_set_device_ethernet_addr() - set device etherenet address * @dev_ethaddr: device etherenet address * diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index db1ca629cbd6..f0c831b4b3d9 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -21,6 +21,26 @@ config ATH10K_AHB ---help--- This module adds support for AHB bus +config ATH10K_TARGET_SNOC + tristate "Atheros ath10k SNOC support" + depends on ATH10K + ---help--- + This module adds support for the Integrated WCN3990 WLAN module, + WCN3990 has integrated 802.11ac chipset with SNOC bus interface. + This module also adds support to register the WCN3990 wlan module + with MAC80211 network subsystem. + +config ATH10K_SNOC + bool "Enable/disable Atheros ath10k SNOC bus interface support" + depends on ATH10K + depends on ATH10K_TARGET_SNOC + ---help--- + This module add support for WLAN SNOC bus registration, WLAN + copy engine configuration for the WCN3990 chipset, WLAN hardware + shadow register configuration, create host to target communication + interface to interact with WLAN firmware, WLAN module interface + control and data receive(RX)/transmit(TX) control. + config ATH10K_DEBUG bool "Atheros ath10k debugging" depends on ATH10K diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 930fadd940d8..25b23bf2c8e6 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -24,6 +24,9 @@ ath10k_core-$(CONFIG_PM) += wow.o obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o ath10k_pci-y += pci.o \ ce.o +obj-$(CONFIG_ATH10K_TARGET_SNOC) += ath10k_snoc.o +ath10k_snoc-y += snoc.o \ + ce.o ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 89b1dfcb89fd..871329c79a46 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -305,6 +305,21 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .hw_ops = &qca99x0_ops, .decap_align_bytes = 1, }, + { + .id = ATH10K_HW_WCN3990, + .dev_id = 0, + .name = "wcn3990 hw1.0", + .continuous_frag_desc = true, + .tx_chain_mask = 0x7, + .rx_chain_mask = 0x7, + .max_spatial_stream = 4, + .fw = { + .dir = WCN3990_HW_1_0_FW_DIR, + }, + .sw_decrypt_mcast_mgmt = true, + .hw_ops = &wcn3990_ops, + .decap_align_bytes = 1, + }, }; static const char *const ath10k_core_fw_feature_str[] = { @@ -1263,12 +1278,14 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, data += ie_len; } - if (!fw_file->firmware_data || - !fw_file->firmware_len) { - ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n", - ar->hw_params.fw.dir, name); - ret = -ENOMEDIUM; - goto err; + if (ar->is_bmi) { + if (!fw_file->firmware_data || + !fw_file->firmware_len) { + ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n", + ar->hw_params.fw.dir, name); + ret = -ENOMEDIUM; + goto err; + } } return 0; @@ -1282,8 +1299,10 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) { int ret; - /* calibration file is optional, don't check for any errors */ - ath10k_fetch_cal_file(ar); + if (ar->is_bmi) { + /* calibration file is optional, don't check for any errors */ + ath10k_fetch_cal_file(ar); + } ar->fw_api = 5; ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); @@ -1574,8 +1593,6 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) { struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; - init_fw_param(ar, &ar->normal_mode_fw.fw_file); - if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) && !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well"); @@ -1797,8 +1814,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, lockdep_assert_held(&ar->conf_mutex); clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); - if (!ar->qmi.is_qmi) { - ar->running_fw = fw; + + ar->running_fw = fw; + + if (ar->is_bmi) { ath10k_bmi_start(ar); @@ -1846,7 +1865,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, goto err; } - if (!ar->qmi.is_qmi) { + if (ar->is_bmi) { status = ath10k_bmi_done(ar); if (status) goto err; @@ -2083,38 +2102,37 @@ static int ath10k_core_probe_fw(struct ath10k *ar) return ret; } - if (!ar->qmi.is_qmi) { + if (ar->is_bmi) { memset(&target_info, 0, sizeof(target_info)); ret = ath10k_bmi_get_target_info(ar, &target_info); if (ret) { ath10k_err(ar, "could not get target info (%d)\n", ret); goto err_power_down; } - ar->target_version = target_info.version; ar->hw->wiphy->hw_version = target_info.version; + } - ret = ath10k_init_hw_params(ar); - if (ret) { - ath10k_err(ar, "could not get hw params (%d)\n", ret); - goto err_power_down; - } - - ret = ath10k_core_fetch_firmware_files(ar); - if (ret) { - ath10k_err(ar, "could not fetch firmware files (%d)\n", - ret); - goto err_power_down; - } + ret = ath10k_init_hw_params(ar); + if (ret) { + ath10k_err(ar, "could not get hw params (%d)\n", ret); + goto err_power_down; + } - BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) != - sizeof(ar->normal_mode_fw.fw_file.fw_version)); - memcpy(ar->hw->wiphy->fw_version, - ar->normal_mode_fw.fw_file.fw_version, - sizeof(ar->hw->wiphy->fw_version)); + ret = ath10k_core_fetch_firmware_files(ar); + if (ret) { + ath10k_err(ar, "could not fetch firmware files (%d)\n", ret); + goto err_power_down; + } - ath10k_debug_print_hwfw_info(ar); + BUILD_BUG_ON(sizeof(ar->hw->wiphy->fw_version) != + sizeof(ar->normal_mode_fw.fw_file.fw_version)); + memcpy(ar->hw->wiphy->fw_version, + ar->normal_mode_fw.fw_file.fw_version, + sizeof(ar->hw->wiphy->fw_version)); + ath10k_debug_print_hwfw_info(ar); + if (ar->is_bmi) { ret = ath10k_core_pre_cal_download(ar); if (ret) { /* pre calibration data download is not necessary @@ -2147,7 +2165,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar) goto err_free_firmware_files; } - if (!ar->qmi.is_qmi) { + if (ar->is_bmi) { ret = ath10k_swap_code_seg_init(ar, &ar->normal_mode_fw.fw_file); if (ret) { @@ -2299,6 +2317,12 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ar->hif.ops = hif_ops; ar->hif.bus = bus; + /* By default, assume bmi is set, as most of the existing + * chip sets are based on this, set to false explicitly + * when current chip set does not support. + */ + ar->is_bmi = true; + switch (hw_rev) { case ATH10K_HW_QCA988X: case ATH10K_HW_QCA9887: @@ -2326,7 +2350,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, case ATH10K_HW_WCN3990: ar->regs = &wcn3990_regs; ar->hw_values = &wcn3990_values; - ar->qmi.is_qmi = true; + /* WCN3990 chip set is non bmi based */ + ar->is_bmi = false; ar->fw_flags = &wcn3990_fw_flags; break; default: diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index bba51b939834..9310de85f2a0 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -138,11 +138,6 @@ struct ath10k_bmi { bool done_sent; }; -struct ath10k_qmi { - bool fw_ready; - bool is_qmi; -}; - struct ath10k_mem_chunk { void *vaddr; dma_addr_t paddr; @@ -745,7 +740,6 @@ struct ath10k { const struct ath10k_hw_regs *regs; const struct ath10k_hw_values *hw_values; struct ath10k_bmi bmi; - struct ath10k_qmi qmi; struct ath10k_wmi wmi; struct ath10k_htc htc; struct ath10k_htt htt; @@ -930,6 +924,8 @@ struct ath10k { spinlock_t ce_lock; /* lock for CE access */ void *ce_states; struct fw_flag *fw_flags; + /* set for bmi chip sets */ + bool is_bmi; /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index c9c43cd1ab95..0cd1068b0beb 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -271,3 +271,5 @@ static int ath10k_qca99x0_rx_desc_get_l3_pad_bytes(struct htt_rx_desc *rxd) const struct ath10k_hw_ops qca99x0_ops = { .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes, }; + +const struct ath10k_hw_ops wcn3990_ops = {0}; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 6a8765b4e358..2e7d90ef53f2 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -128,6 +128,10 @@ enum qca9377_chip_id_rev { #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 +/* WCN3990 1.0 definitions */ +#define WCN3990_HW_1_0_DEV_VERSION ATH10K_HW_WCN3990 +#define WCN3990_HW_1_0_FW_DIR "/etc/firmware" + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" @@ -434,6 +438,7 @@ struct ath10k_hw_ops { extern const struct ath10k_hw_ops qca988x_ops; extern const struct ath10k_hw_ops qca99x0_ops; +extern const struct ath10k_hw_ops wcn3990_ops; static inline int ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 9c2697dde76d..024c66ac8e57 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -5,20 +5,20 @@ config QPNP_REVID tristate "QPNP Revision ID Peripheral" depends on SPMI help - Say 'y' here to include support for the Qualcomm QPNP REVID - peripheral. REVID prints out the PMIC type and revision numbers - in the kernel log along with the PMIC option status. The PMIC - type is mapped to a Qualcomm chip part number and logged as well. + Say 'y' here to include support for the Qualcomm Technologies, Inc. + QPNP REVID peripheral. REVID prints out the PMIC type and revision + numbers in the kernel log along with the PMIC option status. The PMIC + type is mapped to a QTI chip part number and logged as well. config QPNP_COINCELL - tristate "Qualcomm QPNP coincell charger support" + tristate "QPNP coincell charger support" depends on SPMI help This driver supports the QPNP coincell peripheral found inside of - Qualcomm QPNP PMIC devices. The coincell charger provides a means to - charge a coincell battery or backup capacitor which is used to - maintain PMIC register state when the main battery is removed from the - mobile device. + Qualcomm Technologies, Inc. QPNP PMIC devices. The coincell charger + provides a means to charge a coincell battery or backup capacitor + which is used to maintain PMIC register state when the main battery is + removed from the mobile device. config SPS bool "SPS support" diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index fd241f6b62da..58c1704a875c 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -2733,6 +2733,16 @@ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) } EXPORT_SYMBOL(gsi_enable_fw); +void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, + unsigned long *size) +{ + if (base_offset) + *base_offset = GSI_GSI_INST_RAM_BASE_OFFS; + if (size) + *size = GSI_GSI_INST_RAM_SIZE; +} +EXPORT_SYMBOL(gsi_get_inst_ram_offset_and_size); + static int msm_gsi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; diff --git a/drivers/platform/msm/gsi/gsi_reg.h b/drivers/platform/msm/gsi/gsi_reg.h index fa1e84896f73..1acaf74a0968 100644 --- a/drivers/platform/msm/gsi/gsi_reg.h +++ b/drivers/platform/msm/gsi/gsi_reg.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1838,5 +1838,7 @@ #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_BMSK 0xffffffff #define GSI_INTER_EE_n_SRC_EV_CH_IRQ_CLR_EV_CH_BIT_MAP_SHFT 0x0 +#define GSI_GSI_INST_RAM_BASE_OFFS 0x4000 +#define GSI_GSI_INST_RAM_SIZE 0x4000 #endif /* __GSI_REG_H__ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d64373327959..cd946fff31a9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -4021,7 +4021,7 @@ static int ipa3_trigger_fw_loading_mdms(void) IPADBG("FWs are available for loading\n"); - result = ipa3_load_fws(fw); + result = ipa3_load_fws(fw, ipa3_res.transport_mem_base); if (result) { IPAERR("IPA FWs loading has failed\n"); release_firmware(fw); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index b3ce52424fec..7feb1c1ce178 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2036,7 +2036,7 @@ int ipa3_uc_panic_notifier(struct notifier_block *this, unsigned long event, void *ptr); void ipa3_inc_acquire_wakelock(void); void ipa3_dec_release_wakelock(void); -int ipa3_load_fws(const struct firmware *firmware); +int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base); int ipa3_register_ipa_ready_cb(void (*ipa_ready_cb)(void *), void *user_data); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 683777d4cacd..3b909acdd823 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3581,75 +3581,164 @@ end_sequence: return res; } +static int ipa3_load_single_fw(const struct firmware *firmware, + const struct elf32_phdr *phdr) +{ + uint32_t *fw_mem_base; + int index; + const uint32_t *elf_data_ptr; + + if (phdr->p_offset > firmware->size) { + IPAERR("Invalid ELF: offset=%u is beyond elf_size=%zu\n", + phdr->p_offset, firmware->size); + return -EINVAL; + } + if ((firmware->size - phdr->p_offset) < phdr->p_filesz) { + IPAERR("Invalid ELF: offset=%u filesz=%u elf_size=%zu\n", + phdr->p_offset, phdr->p_filesz, firmware->size); + return -EINVAL; + } + + if (phdr->p_memsz % sizeof(uint32_t)) { + IPAERR("FW mem size %u doesn't align to 32bit\n", + phdr->p_memsz); + return -EFAULT; + } + + if (phdr->p_filesz > phdr->p_memsz) { + IPAERR("FW image too big src_size=%u dst_size=%u\n", + phdr->p_filesz, phdr->p_memsz); + return -EFAULT; + } + + fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); + if (!fw_mem_base) { + IPAERR("Failed to map 0x%x for the size of %u\n", + phdr->p_vaddr, phdr->p_memsz); + return -ENOMEM; + } + + /* Set the entire region to 0s */ + memset(fw_mem_base, 0, phdr->p_memsz); + + elf_data_ptr = (uint32_t *)(firmware->data + phdr->p_offset); + + /* Write the FW */ + for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); index++) { + writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); + elf_data_ptr++; + } + + iounmap(fw_mem_base); + + return 0; +} + /** * ipa3_load_fws() - Load the IPAv3 FWs into IPA&GSI SRAM. * * @firmware: Structure which contains the FW data from the user space. + * @gsi_mem_base: GSI base address * * Return value: 0 on success, negative otherwise * */ -int ipa3_load_fws(const struct firmware *firmware) +int ipa3_load_fws(const struct firmware *firmware, phys_addr_t gsi_mem_base) { const struct elf32_hdr *ehdr; const struct elf32_phdr *phdr; - const uint8_t *elf_phdr_ptr; - uint32_t *elf_data_ptr; - int phdr_idx, index; - uint32_t *fw_mem_base; - - ehdr = (struct elf32_hdr *) firmware->data; - - elf_phdr_ptr = firmware->data + sizeof(*ehdr); + unsigned long gsi_iram_ofst; + unsigned long gsi_iram_size; + phys_addr_t ipa_reg_mem_base; + u32 ipa_reg_ofst; + int rc; + + if (!gsi_mem_base) { + IPAERR("Invalid GSI base address\n"); + return -EINVAL; + } - for (phdr_idx = 0; phdr_idx < ehdr->e_phnum; phdr_idx++) { - /* - * The ELF program header will contain the starting - * address to which the firmware needs to copied. - */ - phdr = (struct elf32_phdr *)elf_phdr_ptr; + ipa_assert_on(!firmware); + /* One program header per FW image: GSI, DPS and HPS */ + if (firmware->size < (sizeof(*ehdr) + 3 * sizeof(*phdr))) { + IPAERR("Missing ELF and Program headers firmware size=%zu\n", + firmware->size); + return -EINVAL; + } - /* - * p_vaddr will contain the starting address to which the - * FW needs to be loaded. - * p_memsz will contain the size of the IRAM. - * p_filesz will contain the size of the FW image. - */ - fw_mem_base = ioremap(phdr->p_vaddr, phdr->p_memsz); - if (!fw_mem_base) { - IPAERR("Failed to map 0x%x for the size of %u\n", - phdr->p_vaddr, phdr->p_memsz); - return -ENOMEM; - } + ehdr = (struct elf32_hdr *) firmware->data; + ipa_assert_on(!ehdr); + if (ehdr->e_phnum != 3) { + IPAERR("Unexpected number of ELF program headers\n"); + return -EINVAL; + } + phdr = (struct elf32_phdr *)(firmware->data + sizeof(*ehdr)); - /* Set the entire region to 0s */ - memset(fw_mem_base, 0, phdr->p_memsz); + /* + * Each ELF program header represents a FW image and contains: + * p_vaddr : The starting address to which the FW needs to loaded. + * p_memsz : The size of the IRAM (where the image loaded) + * p_filesz: The size of the FW image embedded inside the ELF + * p_offset: Absolute offset to the image from the head of the ELF + */ - /* - * p_offset will contain and absolute offset from the beginning - * of the ELF file. - */ - elf_data_ptr = (uint32_t *) - ((uint8_t *)firmware->data + phdr->p_offset); + /* Load GSI FW image */ + gsi_get_inst_ram_offset_and_size(&gsi_iram_ofst, &gsi_iram_size); + if (phdr->p_vaddr != (gsi_mem_base + gsi_iram_ofst)) { + IPAERR( + "Invalid GSI FW img load addr vaddr=0x%x gsi_mem_base=%pa gsi_iram_ofst=0x%lx\n" + , phdr->p_vaddr, &gsi_mem_base, gsi_iram_ofst); + return -EINVAL; + } + if (phdr->p_memsz > gsi_iram_size) { + IPAERR("Invalid GSI FW img size memsz=%d gsi_iram_size=%lu\n", + phdr->p_memsz, gsi_iram_size); + return -EINVAL; + } + rc = ipa3_load_single_fw(firmware, phdr); + if (rc) + return rc; - if (phdr->p_memsz % sizeof(uint32_t)) { - IPAERR("FW size %u doesn't align to 32bit\n", - phdr->p_memsz); - return -EFAULT; - } + phdr++; + ipa_reg_mem_base = ipa3_ctx->ipa_wrapper_base + ipahal_get_reg_base(); - /* Write the FW */ - for (index = 0; index < phdr->p_filesz/sizeof(uint32_t); - index++) { - writel_relaxed(*elf_data_ptr, &fw_mem_base[index]); - elf_data_ptr++; - } + /* Load IPA DPS FW image */ + ipa_reg_ofst = ipahal_get_reg_ofst(IPA_DPS_SEQUENCER_FIRST); + if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { + IPAERR( + "Invalid IPA DPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" + , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); + return -EINVAL; + } + if (phdr->p_memsz > ipahal_get_dps_img_mem_size()) { + IPAERR("Invalid IPA DPS img size memsz=%d dps_mem_size=%u\n", + phdr->p_memsz, ipahal_get_dps_img_mem_size()); + return -EINVAL; + } + rc = ipa3_load_single_fw(firmware, phdr); + if (rc) + return rc; - iounmap(fw_mem_base); + phdr++; - elf_phdr_ptr = elf_phdr_ptr + sizeof(*phdr); + /* Load IPA HPS FW image */ + ipa_reg_ofst = ipahal_get_reg_ofst(IPA_HPS_SEQUENCER_FIRST); + if (phdr->p_vaddr != (ipa_reg_mem_base + ipa_reg_ofst)) { + IPAERR( + "Invalid IPA HPS img load addr vaddr=0x%x ipa_reg_mem_base=%pa ipa_reg_ofst=%u\n" + , phdr->p_vaddr, &ipa_reg_mem_base, ipa_reg_ofst); + return -EINVAL; + } + if (phdr->p_memsz > ipahal_get_hps_img_mem_size()) { + IPAERR("Invalid IPA HPS img size memsz=%d dps_mem_size=%u\n", + phdr->p_memsz, ipahal_get_hps_img_mem_size()); + return -EINVAL; } - IPADBG("IPA FWs (GSI FW, HPS and DPS) were loaded\n"); + rc = ipa3_load_single_fw(firmware, phdr); + if (rc) + return rc; + + IPADBG("IPA FWs (GSI FW, DPS and HPS) loaded successfully\n"); return 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c index 2bc179d5a33c..bc9d45b254b3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1257,6 +1257,21 @@ int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type) return res; } +/* + * Get IPA Data Processing Star image memory size at IPA SRAM + */ +u32 ipahal_get_dps_img_mem_size(void) +{ + return IPA_HW_DPS_IMG_MEM_SIZE_V3_0; +} + +/* + * Get IPA Header Processing Star image memory size at IPA SRAM + */ +u32 ipahal_get_hps_img_mem_size(void) +{ + return IPA_HW_HPS_IMG_MEM_SIZE_V3_0; +} int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base, struct device *ipa_pdev) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h index 654977511814..154045fe4f56 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -634,6 +634,16 @@ int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type, */ int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type); +/* + * Get IPA Data Processing Star image memory size at IPA SRAM + */ +u32 ipahal_get_dps_img_mem_size(void); + +/* + * Get IPA Header Processing Star image memory size at IPA SRAM + */ +u32 ipahal_get_hps_img_mem_size(void); + int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base, struct device *ipa_pdev); void ipahal_destroy(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h index 4c4b6661e8fc..d6a496e56861 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -546,4 +546,8 @@ struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq { struct ipa_hw_hdr_proc_ctx_tlv end; }; +/* IPA HW DPS/HPS image memory sizes */ +#define IPA_HW_DPS_IMG_MEM_SIZE_V3_0 128 +#define IPA_HW_HPS_IMG_MEM_SIZE_V3_0 320 + #endif /* _IPAHAL_I_H_ */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c index 347a8c418ebb..ed0d0032af8d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1119,6 +1119,12 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = { [IPA_HW_v3_0][IPA_QSB_MAX_READS] = { ipareg_construct_qsb_max_reads, ipareg_parse_dummy, 0x00000078, 0}, + [IPA_HW_v3_0][IPA_DPS_SEQUENCER_FIRST] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x0001e000, 0}, + [IPA_HW_v3_0][IPA_HPS_SEQUENCER_FIRST] = { + ipareg_construct_dummy, ipareg_parse_dummy, + 0x0001e080, 0}, /* IPAv3.1 */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h index 5f1e3fe410b1..0fc2a65f5e99 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -83,6 +83,8 @@ enum ipahal_reg_name { IPA_QSB_MAX_WRITES, IPA_QSB_MAX_READS, IPA_TX_CFG, + IPA_DPS_SEQUENCER_FIRST, + IPA_HPS_SEQUENCER_FIRST, IPA_REG_MAX, }; diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c index 6aaa53526868..b427f43e76df 100644 --- a/drivers/platform/msm/qpnp-coincell.c +++ b/drivers/platform/msm/qpnp-coincell.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -244,7 +244,7 @@ static int qpnp_coincell_remove(struct platform_device *pdev) return 0; } -static struct of_device_id qpnp_coincell_match_table[] = { +static const struct of_device_id qpnp_coincell_match_table[] = { { .compatible = QPNP_COINCELL_DRIVER_NAME, }, {} }; diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c index 6b5db58f856a..9ea0b40304eb 100644 --- a/drivers/platform/msm/qpnp-revid.c +++ b/drivers/platform/msm/qpnp-revid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -70,7 +70,7 @@ struct revid_chip { static LIST_HEAD(revid_chips); static DEFINE_MUTEX(revid_chips_lock); -static struct of_device_id qpnp_revid_match_table[] = { +static const struct of_device_id qpnp_revid_match_table[] = { { .compatible = QPNP_REVID_DEV_NAME }, {} }; diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 3b2ea6a6a5ed..55ab6177e6db 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -282,6 +282,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(fcc_delta), POWER_SUPPLY_ATTR(icl_reduction), POWER_SUPPLY_ATTR(parallel_mode), + POWER_SUPPLY_ATTR(connector_therm_zone), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/drivers/power/qcom/Kconfig b/drivers/power/qcom/Kconfig index b7ca61d6c21d..efb9dd9628bb 100644 --- a/drivers/power/qcom/Kconfig +++ b/drivers/power/qcom/Kconfig @@ -23,12 +23,12 @@ config APSS_CORE_EA and temperature information to the scheduler. config MSM_APM - bool "Qualcomm Technologies Inc platform specific APM driver" - help - Platform specific driver to manage the power source of - memory arrays. Interfaces with regulator drivers to ensure - SRAM Vmin requirements are met across different performance - levels. + bool "Qualcomm Technologies, Inc. platform specific APM driver" + help + Platform specific driver to manage the power source of + memory arrays. Interfaces with regulator drivers to ensure + SRAM Vmin requirements are met across different performance + levels. if MSM_PM menuconfig MSM_IDLE_STATS diff --git a/drivers/power/qcom/apm.c b/drivers/power/qcom/apm.c index ffd0e3833b32..6181b08a41a5 100644 --- a/drivers/power/qcom/apm.c +++ b/drivers/power/qcom/apm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -90,7 +90,7 @@ enum { enum { MSM8996_ID, MSM8996PRO_ID, - MSMTITANIUM_ID, + MSM8953_ID, }; struct msm_apm_ctrl_dev { @@ -239,8 +239,8 @@ free_events: return ret; } -/* Titanium register offset definition */ -#define MSMTITANIUM_APM_DLY_CNTR 0x2ac +/* MSM8953 register offset definition */ +#define MSM8953_APM_DLY_CNTR 0x2ac /* Register field shift definitions */ #define APM_CTL_SEL_SWITCH_DLY_SHIFT 0 @@ -255,12 +255,12 @@ free_events: #define APM_CTL_POST_HALT_DLY_MASK GENMASK(31, 24) /* - * Get the resources associated with the msmtitanium APM controller from + * Get the resources associated with the MSM8953 APM controller from * device tree, remap all I/O addresses, and program the initial - * register configuration required for the titanium APM controller device. + * register configuration required for the MSM8953 APM controller device. */ -static int msmtitanium_apm_ctrl_init(struct platform_device *pdev, - struct msm_apm_ctrl_dev *ctrl) +static int msm8953_apm_ctrl_init(struct platform_device *pdev, + struct msm_apm_ctrl_dev *ctrl) { struct device *dev = &pdev->dev; struct resource *res; @@ -282,7 +282,7 @@ static int msmtitanium_apm_ctrl_init(struct platform_device *pdev, * Initial APM register configuration required before starting * APM HW controller. */ - regval = readl_relaxed(ctrl->reg_base + MSMTITANIUM_APM_DLY_CNTR); + regval = readl_relaxed(ctrl->reg_base + MSM8953_APM_DLY_CNTR); val = regval; if (of_find_property(dev->of_node, "qcom,apm-post-halt-delay", NULL)) { @@ -342,7 +342,7 @@ static int msmtitanium_apm_ctrl_init(struct platform_device *pdev, } if (val != regval) { - writel_relaxed(val, ctrl->reg_base + MSMTITANIUM_APM_DLY_CNTR); + writel_relaxed(val, ctrl->reg_base + MSM8953_APM_DLY_CNTR); /* make sure write completes before return */ mb(); } @@ -619,17 +619,17 @@ done: return ret; } -/* Titanium register value definitions */ -#define MSMTITANIUM_APM_MX_MODE_VAL 0x00 -#define MSMTITANIUM_APM_APCC_MODE_VAL 0x02 -#define MSMTITANIUM_APM_MX_DONE_VAL 0x00 -#define MSMTITANIUM_APM_APCC_DONE_VAL 0x03 +/* MSM8953 register value definitions */ +#define MSM8953_APM_MX_MODE_VAL 0x00 +#define MSM8953_APM_APCC_MODE_VAL 0x02 +#define MSM8953_APM_MX_DONE_VAL 0x00 +#define MSM8953_APM_APCC_DONE_VAL 0x03 -/* Titanium register offset definitions */ -#define MSMTITANIUM_APCC_APM_MODE 0x000002a8 -#define MSMTITANIUM_APCC_APM_CTL_STS 0x000002b0 +/* MSM8953 register offset definitions */ +#define MSM8953_APCC_APM_MODE 0x000002a8 +#define MSM8953_APCC_APM_CTL_STS 0x000002b0 -static int msmtitanium_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) +static int msm8953_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) { int timeout = MSM_APM_SWITCH_TIMEOUT_US; u32 regval; @@ -639,17 +639,17 @@ static int msmtitanium_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) spin_lock_irqsave(&ctrl_dev->lock, flags); /* Switch arrays to MX supply and wait for its completion */ - writel_relaxed(MSMTITANIUM_APM_MX_MODE_VAL, ctrl_dev->reg_base + - MSMTITANIUM_APCC_APM_MODE); + writel_relaxed(MSM8953_APM_MX_MODE_VAL, ctrl_dev->reg_base + + MSM8953_APCC_APM_MODE); /* Ensure write above completes before delaying */ mb(); while (timeout > 0) { regval = readl_relaxed(ctrl_dev->reg_base + - MSMTITANIUM_APCC_APM_CTL_STS); + MSM8953_APCC_APM_CTL_STS); if ((regval & MSM_APM_CTL_STS_MASK) == - MSMTITANIUM_APM_MX_DONE_VAL) + MSM8953_APM_MX_DONE_VAL) break; udelay(1); @@ -670,7 +670,7 @@ static int msmtitanium_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) return ret; } -static int msmtitanium_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) +static int msm8953_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) { int timeout = MSM_APM_SWITCH_TIMEOUT_US; u32 regval; @@ -680,17 +680,17 @@ static int msmtitanium_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) spin_lock_irqsave(&ctrl_dev->lock, flags); /* Switch arrays to APCC supply and wait for its completion */ - writel_relaxed(MSMTITANIUM_APM_APCC_MODE_VAL, ctrl_dev->reg_base + - MSMTITANIUM_APCC_APM_MODE); + writel_relaxed(MSM8953_APM_APCC_MODE_VAL, ctrl_dev->reg_base + + MSM8953_APCC_APM_MODE); /* Ensure write above completes before delaying */ mb(); while (timeout > 0) { regval = readl_relaxed(ctrl_dev->reg_base + - MSMTITANIUM_APCC_APM_CTL_STS); + MSM8953_APCC_APM_CTL_STS); if ((regval & MSM_APM_CTL_STS_MASK) == - MSMTITANIUM_APM_APCC_DONE_VAL) + MSM8953_APM_APCC_DONE_VAL) break; udelay(1); @@ -722,8 +722,8 @@ static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) case MSM8996PRO_ID: ret = msm8996pro_apm_switch_to_mx(ctrl_dev); break; - case MSMTITANIUM_ID: - ret = msmtitanium_apm_switch_to_mx(ctrl_dev); + case MSM8953_ID: + ret = msm8953_apm_switch_to_mx(ctrl_dev); break; } @@ -741,8 +741,8 @@ static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) case MSM8996PRO_ID: ret = msm8996pro_apm_switch_to_apcc(ctrl_dev); break; - case MSMTITANIUM_ID: - ret = msmtitanium_apm_switch_to_apcc(ctrl_dev); + case MSM8953_ID: + ret = msm8953_apm_switch_to_apcc(ctrl_dev); break; } @@ -898,7 +898,7 @@ static void apm_debugfs_init(struct msm_apm_ctrl_dev *ctrl_dev) return; } - temp = debugfs_create_file("supply", S_IRUGO, ctrl_dev->debugfs, + temp = debugfs_create_file("supply", 0444, ctrl_dev->debugfs, ctrl_dev, &apm_supply_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("supply mode creation failed\n"); @@ -932,7 +932,7 @@ static void apm_debugfs_base_remove(void) #endif -static struct of_device_id msm_apm_match_table[] = { +static const struct of_device_id msm_apm_match_table[] = { { .compatible = "qcom,msm-apm", .data = (void *)(uintptr_t)MSM8996_ID, @@ -942,8 +942,8 @@ static struct of_device_id msm_apm_match_table[] = { .data = (void *)(uintptr_t)MSM8996PRO_ID, }, { - .compatible = "qcom,msmtitanium-apm", - .data = (void *)(uintptr_t)MSMTITANIUM_ID, + .compatible = "qcom,msm8953-apm", + .data = (void *)(uintptr_t)MSM8953_ID, }, {} }; @@ -967,10 +967,8 @@ static int msm_apm_probe(struct platform_device *pdev) return -ENODEV; ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); - if (!ctrl) { - dev_err(dev, "MSM APM controller memory allocation failed\n"); + if (!ctrl) return -ENOMEM; - } INIT_LIST_HEAD(&ctrl->list); spin_lock_init(&ctrl->lock); @@ -987,8 +985,8 @@ static int msm_apm_probe(struct platform_device *pdev) return ret; } break; - case MSMTITANIUM_ID: - ret = msmtitanium_apm_ctrl_init(pdev, ctrl); + case MSM8953_ID: + ret = msm8953_apm_ctrl_init(pdev, ctrl); if (ret) { dev_err(dev, "Failed to initialize APM controller device: ret=%d\n", ret); diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 38e822de34a7..a30ed90d6e92 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -530,7 +530,7 @@ static int msm_restart_probe(struct platform_device *pdev) pr_err("unable to map imem KASLR offset\n"); } - if (kaslr_imem_addr && scm_is_secure_device()) { + if (kaslr_imem_addr) { __raw_writel(0xdead4ead, kaslr_imem_addr); __raw_writel(KASLR_OFFSET_BIT_MASK & (kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4); @@ -602,7 +602,6 @@ skip_sysfs_create: scm_deassert_ps_hold_supported = true; #ifdef CONFIG_QCOM_DLOAD_MODE - download_mode = scm_is_secure_device(); set_dload_mode(download_mode); if (!download_mode) scm_disable_sdi(); diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c index 5f1b6b294b5f..34add97b55d2 100644 --- a/drivers/power/supply/qcom/battery.c +++ b/drivers/power/supply/qcom/battery.c @@ -42,6 +42,7 @@ struct pl_data { struct votable *fcc_votable; struct votable *fv_votable; struct votable *pl_disable_votable; + struct votable *pl_awake_votable; struct work_struct status_change_work; struct delayed_work pl_taper_work; struct power_supply *main_psy; @@ -82,7 +83,7 @@ enum { static void split_settled(struct pl_data *chip) { int slave_icl_pct; - int slave_ua; + int slave_ua = 0; union power_supply_propval pval = {0, }; int rc; @@ -94,11 +95,9 @@ static void split_settled(struct pl_data *chip) if (chip->pl_mode != POWER_SUPPLY_PARALLEL_USBIN_USBIN) return; - if (chip->main_psy) + if (!chip->main_psy) return; - slave_ua = 0; - if (!get_effective_result_locked(chip->pl_disable_votable)) { /* read the aicl settled value */ rc = power_supply_get_property(chip->main_psy, @@ -214,7 +213,7 @@ static void pl_taper_work(struct work_struct *work) if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) { pl_dbg(chip, PR_PARALLEL, "master is taper charging; reducing slave FCC\n"); - __pm_stay_awake(chip->pl_ws); + vote(chip->pl_awake_votable, TAPER_END_VOTER, true, 0); /* Reduce the taper percent by 25 percent */ chip->taper_pct = chip->taper_pct * TAPER_RESIDUAL_PCT / 100; rerun_election(chip->fcc_votable); @@ -231,7 +230,7 @@ static void pl_taper_work(struct work_struct *work) pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n"); done: - __pm_relax(chip->pl_ws); + vote(chip->pl_awake_votable, TAPER_END_VOTER, false, 0); } /********* @@ -375,15 +374,17 @@ static int pl_disable_vote_callback(struct votable *votable, if (!pl_disable) { /* enable */ rerun_election(chip->fv_votable); rerun_election(chip->fcc_votable); - - if (chip->pl_psy) { - pval.intval = 0; - rc = power_supply_set_property(chip->pl_psy, - POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval); - if (rc < 0) - pr_err("Couldn't change slave suspend state rc=%d\n", - rc); - } + /* + * Enable will be called with a valid pl_psy always. The + * PARALLEL_PSY_VOTER keeps it disabled unless a pl_psy + * is seen. + */ + pval.intval = 0; + rc = power_supply_set_property(chip->pl_psy, + POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval); + if (rc < 0) + pr_err("Couldn't change slave suspend state rc=%d\n", + rc); if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) split_settled(chip); @@ -406,6 +407,7 @@ static int pl_disable_vote_callback(struct votable *votable, if (chip->pl_mode == POWER_SUPPLY_PARALLEL_USBIN_USBIN) split_settled(chip); + /* pl_psy may be NULL while in the disable branch */ if (chip->pl_psy) { pval.intval = 1; rc = power_supply_set_property(chip->pl_psy, @@ -424,6 +426,20 @@ static int pl_disable_vote_callback(struct votable *votable, return 0; } +static int pl_awake_vote_callback(struct votable *votable, + void *data, int awake, const char *client) +{ + struct pl_data *chip = data; + + if (awake) + __pm_stay_awake(chip->pl_ws); + else + __pm_relax(chip->pl_ws); + + pr_debug("client: %s awake: %d\n", client, awake); + return 0; +} + static bool is_main_available(struct pl_data *chip) { if (!chip->main_psy) @@ -500,15 +516,6 @@ static void handle_main_charge_type(struct pl_data *chip) return; } - /* handle fast/taper charge entry */ - if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER - || pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) { - pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n"); - vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0); - chip->charge_type = pval.intval; - return; - } - /* handle taper charge entry */ if (chip->charge_type == POWER_SUPPLY_CHARGE_TYPE_FAST && (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER)) { @@ -518,6 +525,15 @@ static void handle_main_charge_type(struct pl_data *chip) return; } + /* handle fast/taper charge entry */ + if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER + || pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) { + pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n"); + vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0); + chip->charge_type = pval.intval; + return; + } + /* remember the new state only if it isn't any of the above */ chip->charge_type = pval.intval; } @@ -671,6 +687,14 @@ static int pl_init(void) vote(chip->pl_disable_votable, TAPER_END_VOTER, false, 0); vote(chip->pl_disable_votable, PARALLEL_PSY_VOTER, true, 0); + chip->pl_awake_votable = create_votable("PL_AWAKE", VOTE_SET_ANY, + pl_awake_vote_callback, + chip); + if (IS_ERR(chip->pl_awake_votable)) { + rc = PTR_ERR(chip->pl_disable_votable); + goto destroy_votable; + } + INIT_WORK(&chip->status_change_work, status_change_work); INIT_DELAYED_WORK(&chip->pl_taper_work, pl_taper_work); @@ -701,6 +725,7 @@ static int pl_init(void) unreg_notifier: power_supply_unreg_notifier(&chip->nb); destroy_votable: + destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); @@ -716,6 +741,7 @@ static void pl_deinit(void) struct pl_data *chip = the_chip; power_supply_unreg_notifier(&chip->nb); + destroy_votable(chip->pl_awake_votable); destroy_votable(chip->pl_disable_votable); destroy_votable(chip->fv_votable); destroy_votable(chip->fcc_votable); diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index d71e3afd8d42..0d3fcc2ede86 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -156,7 +156,8 @@ enum fg_sram_param_id { FG_SRAM_ESR_TIMER_CHG_INIT, FG_SRAM_SYS_TERM_CURR, FG_SRAM_CHG_TERM_CURR, - FG_SRAM_DELTA_SOC_THR, + FG_SRAM_DELTA_MSOC_THR, + FG_SRAM_DELTA_BSOC_THR, FG_SRAM_RECHARGE_SOC_THR, FG_SRAM_RECHARGE_VBATT_THR, FG_SRAM_KI_COEFF_MED_DISCHG, @@ -205,6 +206,7 @@ enum wa_flags { struct fg_dt_props { bool force_load_profile; bool hold_soc_while_full; + bool auto_recharge_soc; int cutoff_volt_mv; int empty_volt_mv; int vbatt_low_thr_mv; @@ -322,6 +324,7 @@ struct fg_chip { struct mutex bus_lock; struct mutex sram_rw_lock; struct mutex batt_avg_lock; + struct mutex charge_full_lock; u32 batt_soc_base; u32 batt_info_base; u32 mem_if_base; @@ -335,6 +338,9 @@ struct fg_chip { int last_soc; int last_batt_temp; int health; + int maint_soc; + int delta_soc; + int last_msoc; bool profile_available; bool profile_loaded; bool battery_missing; @@ -345,6 +351,7 @@ struct fg_chip { bool esr_fcc_ctrl_en; bool soc_reporting_ready; bool esr_flt_cold_temp_en; + bool bsoc_delta_irq_en; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 7ffa583ca01d..12f3d448c891 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -48,8 +48,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 DELTA_MSOC_THR_WORD 12 +#define DELTA_MSOC_THR_OFFSET 3 +#define DELTA_BSOC_THR_WORD 13 +#define DELTA_BSOC_THR_OFFSET 2 #define RECHARGE_SOC_THR_WORD 14 #define RECHARGE_SOC_THR_OFFSET 0 #define CHG_TERM_CURR_WORD 14 @@ -113,8 +115,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 DELTA_BSOC_THR_v2_WORD 12 +#define DELTA_BSOC_THR_v2_OFFSET 3 +#define DELTA_MSOC_THR_v2_WORD 13 +#define DELTA_MSOC_THR_v2_OFFSET 0 #define RECHARGE_SOC_THR_v2_WORD 14 #define RECHARGE_SOC_THR_v2_OFFSET 1 #define CHG_TERM_CURR_v2_WORD 15 @@ -143,6 +147,8 @@ static void fg_encode_current(struct fg_sram_param *sp, static void fg_encode_default(struct fg_sram_param *sp, enum fg_sram_param_id id, int val, u8 *buf); +static struct fg_irq_info fg_irqs[FG_IRQ_MAX]; + #define PARAM(_id, _addr_word, _addr_byte, _len, _num, _den, _offset, \ _enc, _dec) \ [FG_SRAM_##_id] = { \ @@ -188,8 +194,10 @@ static struct fg_sram_param pmi8998_v1_sram_params[] = { 1000000, 122070, 0, fg_encode_current, NULL), PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1, 100000, 390625, 0, fg_encode_current, NULL), - PARAM(DELTA_SOC_THR, DELTA_SOC_THR_WORD, DELTA_SOC_THR_OFFSET, 1, 2048, - 100, 0, fg_encode_default, NULL), + PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, 1, + 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, 1, + 2048, 100, 0, fg_encode_default, NULL), PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_WORD, RECHARGE_SOC_THR_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), PARAM(ESR_TIMER_DISCHG_MAX, ESR_TIMER_DISCHG_MAX_WORD, @@ -248,8 +256,10 @@ static struct fg_sram_param pmi8998_v2_sram_params[] = { 1000000, 122070, 0, fg_encode_current, NULL), PARAM(CHG_TERM_CURR, CHG_TERM_CURR_v2_WORD, CHG_TERM_CURR_v2_OFFSET, 1, 100000, 390625, 0, fg_encode_current, NULL), - PARAM(DELTA_SOC_THR, DELTA_SOC_THR_v2_WORD, DELTA_SOC_THR_v2_OFFSET, 1, - 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_v2_WORD, DELTA_MSOC_THR_v2_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), + PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_v2_WORD, DELTA_BSOC_THR_v2_OFFSET, + 1, 2048, 100, 0, fg_encode_default, NULL), PARAM(RECHARGE_SOC_THR, RECHARGE_SOC_THR_v2_WORD, RECHARGE_SOC_THR_v2_OFFSET, 1, 256, 100, 0, fg_encode_default, NULL), @@ -684,6 +694,20 @@ static int fg_get_msoc_raw(struct fg_chip *chip, int *val) return 0; } +#define FULL_CAPACITY 100 +#define FULL_SOC_RAW 255 +static int fg_get_msoc(struct fg_chip *chip, int *msoc) +{ + int rc; + + rc = fg_get_msoc_raw(chip, msoc); + if (rc < 0) + return rc; + + *msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW); + return 0; +} + static bool is_batt_empty(struct fg_chip *chip) { u8 status; @@ -705,7 +729,7 @@ static bool is_batt_empty(struct fg_chip *chip) return false; } - rc = fg_get_msoc_raw(chip, &msoc); + rc = fg_get_msoc(chip, &msoc); if (!rc) pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status, vbatt_uv, msoc); @@ -770,9 +794,8 @@ static bool is_debug_batt_id(struct fg_chip *chip) return false; } -#define FULL_CAPACITY 100 -#define FULL_SOC_RAW 255 #define DEBUG_BATT_SOC 67 +#define BATT_MISS_SOC 50 #define EMPTY_SOC 0 static int fg_get_prop_capacity(struct fg_chip *chip, int *val) { @@ -783,6 +806,16 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } + if (chip->fg_restarting) { + *val = chip->last_soc; + return 0; + } + + if (chip->battery_missing) { + *val = BATT_MISS_SOC; + return 0; + } + if (is_batt_empty(chip)) { *val = EMPTY_SOC; return 0; @@ -793,11 +826,14 @@ static int fg_get_prop_capacity(struct fg_chip *chip, int *val) return 0; } - rc = fg_get_msoc_raw(chip, &msoc); + rc = fg_get_msoc(chip, &msoc); if (rc < 0) return rc; - *val = DIV_ROUND_CLOSEST(msoc * FULL_CAPACITY, FULL_SOC_RAW); + if (chip->delta_soc > 0) + *val = chip->maint_soc; + else + *val = msoc; return 0; } @@ -1386,6 +1422,36 @@ static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip) return 0; } +static int fg_set_recharge_voltage(struct fg_chip *chip, int voltage_mv) +{ + u8 buf; + int rc; + + if (chip->dt.auto_recharge_soc) + return 0; + + /* This configuration is available only for pmicobalt v2.0 and above */ + if (chip->wa_flags & PMI8998_V1_REV_WA) + return 0; + + fg_dbg(chip, FG_STATUS, "Setting recharge voltage to %dmV\n", + voltage_mv); + fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, voltage_mv, &buf); + rc = fg_sram_write(chip, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word, + chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte, + &buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing recharge_vbatt_thr, rc=%d\n", + rc); + return rc; + } + + return 0; +} + +#define AUTO_RECHG_VOLT_LOW_LIMIT_MV 3700 static int fg_charge_full_update(struct fg_chip *chip) { union power_supply_propval prop = {0, }; @@ -1398,11 +1464,22 @@ static int fg_charge_full_update(struct fg_chip *chip) if (!batt_psy_initialized(chip)) return 0; + mutex_lock(&chip->charge_full_lock); + if (!chip->charge_done && chip->bsoc_delta_irq_en) { + disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = false; + } else if (chip->charge_done && !chip->bsoc_delta_irq_en) { + enable_irq(fg_irqs[BSOC_DELTA_IRQ].irq); + enable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = true; + } + 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; + goto out; } chip->health = prop.intval; @@ -1412,33 +1489,77 @@ static int fg_charge_full_update(struct fg_chip *chip) 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; + goto out; } /* We need 2 most significant bytes here */ bsoc = (u32)bsoc >> 16; - rc = fg_get_prop_capacity(chip, &msoc); + rc = fg_get_msoc(chip, &msoc); if (rc < 0) { - pr_err("Error in getting capacity, rc=%d\n", rc); - return rc; + pr_err("Error in getting msoc, rc=%d\n", rc); + goto out; } - fg_dbg(chip, FG_STATUS, "msoc: %d health: %d status: %d\n", msoc, - chip->health, chip->charge_status); - if (chip->charge_done) { - if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) + fg_dbg(chip, FG_STATUS, "msoc: %d bsoc: %x health: %d status: %d full: %d\n", + msoc, bsoc, chip->health, chip->charge_status, + chip->charge_full); + if (chip->charge_done && !chip->charge_full) { + if (msoc >= 99 && chip->health == POWER_SUPPLY_HEALTH_GOOD) { + fg_dbg(chip, FG_STATUS, "Setting charge_full to true\n"); chip->charge_full = true; - else + /* + * Lower the recharge voltage so that VBAT_LT_RECHG + * signal will not be asserted soon. + */ + rc = fg_set_recharge_voltage(chip, + AUTO_RECHG_VOLT_LOW_LIMIT_MV); + if (rc < 0) { + pr_err("Error in reducing recharge voltage, rc=%d\n", + rc); + goto out; + } + } 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); + } + } else if ((bsoc >> 8) <= recharge_soc && chip->charge_full) { + chip->delta_soc = FULL_CAPACITY - msoc; + + /* + * We're spreading out the delta SOC over every 10% change + * in monotonic SOC. We cannot spread more than 9% in the + * range of 0-100 skipping the first 10%. + */ + if (chip->delta_soc > 9) { + chip->delta_soc = 0; + chip->maint_soc = 0; + } else { + chip->maint_soc = FULL_CAPACITY; + chip->last_msoc = msoc; + } + chip->charge_full = false; + + /* + * Raise the recharge voltage so that VBAT_LT_RECHG signal + * will be asserted soon as battery SOC had dropped below + * the recharge SOC threshold. + */ + rc = fg_set_recharge_voltage(chip, + chip->dt.recharge_volt_thr_mv); + if (rc < 0) { + pr_err("Error in setting recharge voltage, rc=%d\n", + rc); + goto out; + } + fg_dbg(chip, FG_STATUS, "bsoc: %d recharge_soc: %d delta_soc: %d\n", + bsoc >> 8, recharge_soc, chip->delta_soc); + } else { + goto out; } if (!chip->charge_full) - return 0; + goto out; /* * During JEITA conditions, charge_full can happen early. FULL_SOC @@ -1449,18 +1570,20 @@ static int fg_charge_full_update(struct fg_chip *chip) FG_IMA_ATOMIC); if (rc < 0) { pr_err("failed to write full_soc rc=%d\n", rc); - return rc; + goto out; } 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; + goto out; } fg_dbg(chip, FG_STATUS, "Set charge_full to true @ soc %d\n", msoc); - return 0; +out: + mutex_unlock(&chip->charge_full_lock); + return rc; } #define RCONN_CONFIG_BIT BIT(0) @@ -1539,13 +1662,16 @@ static int fg_rconn_config(struct fg_chip *chip) static int fg_set_recharge_soc(struct fg_chip *chip, int recharge_soc) { - u8 buf[4]; + u8 buf; int rc; - fg_encode(chip->sp, FG_SRAM_RECHARGE_SOC_THR, recharge_soc, buf); + if (!chip->dt.auto_recharge_soc) + return 0; + + 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].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); @@ -1559,6 +1685,9 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip) { int rc, msoc, recharge_soc, new_recharge_soc = 0; + if (!chip->dt.auto_recharge_soc) + return 0; + recharge_soc = chip->dt.recharge_soc_thr; /* * If the input is present and charging had been terminated, adjust @@ -1568,13 +1697,12 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip) 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); + rc = fg_get_msoc(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) @@ -2062,7 +2190,6 @@ wait: goto wait; } else if (rc <= 0) { pr_err("wait for soc_ready timed out rc=%d\n", rc); - goto out; } rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0); @@ -2285,7 +2412,6 @@ reschedule: msecs_to_jiffies(BATT_AVG_POLL_PERIOD_MS)); } -#define DECI_TAU_SCALE 13 #define HOURS_TO_SECONDS 3600 #define OCV_SLOPE_UV 10869 #define MILLI_UNIT 1000 @@ -2294,7 +2420,7 @@ static int fg_get_time_to_full(struct fg_chip *chip, int *val) { int rc, ibatt_avg, vbatt_avg, rbatt, msoc, ocv_cc2cv, full_soc, act_cap_uah; - s32 i_cc2cv, soc_cc2cv, ln_val; + s32 i_cc2cv, soc_cc2cv, ln_val, centi_tau_scale; s64 t_predicted_cc = 0, t_predicted_cv = 0; if (chip->bp.float_volt_uv <= 0) { @@ -2417,15 +2543,20 @@ skip_cc_estimate: /* CV estimate starts here */ if (chip->charge_type >= POWER_SUPPLY_CHARGE_TYPE_TAPER) - ln_val = ibatt_avg / abs(chip->dt.sys_term_curr_ma); + ln_val = ibatt_avg / (abs(chip->dt.sys_term_curr_ma) + 200); + else + ln_val = i_cc2cv / (abs(chip->dt.sys_term_curr_ma) + 200); + + if (msoc < 95) + centi_tau_scale = 100; else - ln_val = i_cc2cv / abs(chip->dt.sys_term_curr_ma); + centi_tau_scale = 20 * (100 - msoc); fg_dbg(chip, FG_TTF, "ln_in=%d\n", ln_val); rc = fg_lerp(fg_ln_table, ARRAY_SIZE(fg_ln_table), ln_val, &ln_val); fg_dbg(chip, FG_TTF, "ln_out=%d\n", ln_val); t_predicted_cv = div_s64((s64)act_cap_uah * rbatt, MICRO_UNIT); - t_predicted_cv = div_s64(t_predicted_cv * DECI_TAU_SCALE, 10); + t_predicted_cv = div_s64(t_predicted_cv * centi_tau_scale, 100); t_predicted_cv = div_s64(t_predicted_cv * ln_val, MILLI_UNIT); t_predicted_cv = div_s64(t_predicted_cv * HOURS_TO_SECONDS, MICRO_UNIT); fg_dbg(chip, FG_TTF, "t_predicted_cv=%lld\n", t_predicted_cv); @@ -2479,6 +2610,48 @@ static int fg_get_time_to_empty(struct fg_chip *chip, int *val) return 0; } +static int fg_update_maint_soc(struct fg_chip *chip) +{ + int rc = 0, msoc; + + mutex_lock(&chip->charge_full_lock); + if (chip->delta_soc <= 0) + goto out; + + rc = fg_get_msoc(chip, &msoc); + if (rc < 0) { + pr_err("Error in getting msoc, rc=%d\n", rc); + goto out; + } + + if (msoc > chip->maint_soc) { + /* + * When the monotonic SOC goes above maintenance SOC, we should + * stop showing the maintenance SOC. + */ + chip->delta_soc = 0; + chip->maint_soc = 0; + } else if (msoc <= chip->last_msoc) { + /* MSOC is decreasing. Decrease maintenance SOC as well */ + chip->maint_soc -= 1; + if (!(msoc % 10)) { + /* + * Reduce the maintenance SOC additionally by 1 whenever + * it crosses a SOC multiple of 10. + */ + chip->maint_soc -= 1; + chip->delta_soc -= 1; + } + } + + fg_dbg(chip, FG_IRQ, "msoc: %d last_msoc: %d maint_soc: %d delta_soc: %d\n", + msoc, chip->last_msoc, chip->maint_soc, chip->delta_soc); + chip->last_msoc = msoc; +out: + mutex_unlock(&chip->charge_full_lock); + return rc; +} + /* PSY CALLBACKS STAY HERE */ static int fg_psy_get_property(struct power_supply *psy, @@ -2490,13 +2663,13 @@ static int fg_psy_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: - if (chip->fg_restarting) - pval->intval = chip->last_soc; - else - rc = fg_get_prop_capacity(chip, &pval->intval); + rc = fg_get_prop_capacity(chip, &pval->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: - rc = fg_get_battery_voltage(chip, &pval->intval); + if (chip->battery_missing) + pval->intval = 3700000; + else + rc = fg_get_battery_voltage(chip, &pval->intval); break; case POWER_SUPPLY_PROP_CURRENT_NOW: rc = fg_get_battery_current(chip, &pval->intval); @@ -2749,15 +2922,27 @@ static int fg_hw_init(struct fg_chip *chip) } if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) { - fg_encode(chip->sp, FG_SRAM_DELTA_SOC_THR, + fg_encode(chip->sp, FG_SRAM_DELTA_MSOC_THR, + chip->dt.delta_soc_thr, buf); + rc = fg_sram_write(chip, + chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_word, + chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte, + buf, chip->sp[FG_SRAM_DELTA_MSOC_THR].len, + FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in writing delta_msoc_thr, rc=%d\n", rc); + return rc; + } + + fg_encode(chip->sp, FG_SRAM_DELTA_BSOC_THR, chip->dt.delta_soc_thr, buf); rc = fg_sram_write(chip, - chip->sp[FG_SRAM_DELTA_SOC_THR].addr_word, - chip->sp[FG_SRAM_DELTA_SOC_THR].addr_byte, - buf, chip->sp[FG_SRAM_DELTA_SOC_THR].len, + chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_word, + chip->sp[FG_SRAM_DELTA_BSOC_THR].addr_byte, + buf, chip->sp[FG_SRAM_DELTA_BSOC_THR].len, FG_IMA_DEFAULT); if (rc < 0) { - pr_err("Error in writing delta_soc_thr, rc=%d\n", rc); + pr_err("Error in writing delta_bsoc_thr, rc=%d\n", rc); return rc; } } @@ -2770,18 +2955,11 @@ static int fg_hw_init(struct fg_chip *chip) } } - /* This configuration is available only for pmicobalt v2.0 and above */ - if (!(chip->wa_flags & PMI8998_V1_REV_WA) && - chip->dt.recharge_volt_thr_mv > 0) { - fg_encode(chip->sp, FG_SRAM_RECHARGE_VBATT_THR, - chip->dt.recharge_volt_thr_mv, buf); - rc = fg_sram_write(chip, - chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_word, - chip->sp[FG_SRAM_RECHARGE_VBATT_THR].addr_byte, - buf, chip->sp[FG_SRAM_RECHARGE_VBATT_THR].len, - FG_IMA_DEFAULT); + if (chip->dt.recharge_volt_thr_mv > 0) { + rc = fg_set_recharge_voltage(chip, + chip->dt.recharge_volt_thr_mv); if (rc < 0) { - pr_err("Error in writing recharge_vbatt_thr, rc=%d\n", + pr_err("Error in setting recharge_voltage, rc=%d\n", rc); return rc; } @@ -3048,7 +3226,20 @@ static irqreturn_t fg_soc_update_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) +static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data) +{ + struct fg_chip *chip = data; + int rc; + + fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq); + rc = fg_charge_full_update(chip); + if (rc < 0) + pr_err("Error in charge_full_update, rc=%d\n", rc); + + return IRQ_HANDLED; +} + +static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) { struct fg_chip *chip = data; int rc; @@ -3068,6 +3259,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data) if (rc < 0) pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc); + rc = fg_update_maint_soc(chip); + if (rc < 0) + pr_err("Error in updating maint_soc, rc=%d\n", rc); + if (batt_psy_initialized(chip)) power_supply_changed(chip->batt_psy); @@ -3122,12 +3317,13 @@ static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = { }, [MSOC_DELTA_IRQ] = { .name = "msoc-delta", - .handler = fg_delta_soc_irq_handler, + .handler = fg_delta_msoc_irq_handler, .wakeable = true, }, [BSOC_DELTA_IRQ] = { .name = "bsoc-delta", - .handler = fg_dummy_irq_handler, + .handler = fg_delta_bsoc_irq_handler, + .wakeable = true, }, [SOC_READY_IRQ] = { .name = "soc-ready", @@ -3485,6 +3681,9 @@ static int fg_parse_dt(struct fg_chip *chip) else chip->dt.recharge_volt_thr_mv = temp; + chip->dt.auto_recharge_soc = of_property_read_bool(node, + "qcom,fg-auto-recharge-soc"); + rc = of_property_read_u32(node, "qcom,fg-rsense-sel", &temp); if (rc < 0) chip->dt.rsense_sel = SRC_SEL_BATFET_SMB; @@ -3687,6 +3886,7 @@ static int fg_gen3_probe(struct platform_device *pdev) mutex_init(&chip->cyc_ctr.lock); mutex_init(&chip->cl.lock); mutex_init(&chip->batt_avg_lock); + mutex_init(&chip->charge_full_lock); init_completion(&chip->soc_update); init_completion(&chip->soc_ready); INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work); @@ -3742,6 +3942,13 @@ static int fg_gen3_probe(struct platform_device *pdev) if (fg_irqs[SOC_UPDATE_IRQ].irq) disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq); + /* Keep BSOC_DELTA_IRQ irq disabled until we require it */ + if (fg_irqs[BSOC_DELTA_IRQ].irq) { + disable_irq_wake(fg_irqs[BSOC_DELTA_IRQ].irq); + disable_irq_nosync(fg_irqs[BSOC_DELTA_IRQ].irq); + chip->bsoc_delta_irq_en = false; + } + rc = fg_debugfs_create(chip); if (rc < 0) { dev_err(chip->dev, "Error in creating debugfs entries, rc:%d\n", diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c index c4cc541a0a3e..078bbaaad5a2 100644 --- a/drivers/power/supply/qcom/qpnp-qnovo.c +++ b/drivers/power/supply/qcom/qpnp-qnovo.c @@ -110,8 +110,7 @@ struct qnovo_dt_props { }; enum { - QNOVO_ERASE_OFFSET_WA_BIT = BIT(0), - QNOVO_NO_ERR_STS_BIT = BIT(1), + QNOVO_NO_ERR_STS_BIT = BIT(0), }; struct chg_props { @@ -315,7 +314,6 @@ static int qnovo_check_chg_version(struct qnovo *chip) if ((chip->pmic_rev_id->pmic_subtype == PMI8998_SUBTYPE) && (chip->pmic_rev_id->rev4 < PMI8998_V2P0_REV4)) { - chip->wa_flags |= QNOVO_ERASE_OFFSET_WA_BIT; chip->wa_flags |= QNOVO_NO_ERR_STS_BIT; } @@ -447,6 +445,8 @@ static struct param_info params[] = { .num_regs = 1, .reg_to_unit_multiplier = 1, .reg_to_unit_divider = 1, + .min_val = 0, + .max_val = 255, .units_str = "pulses", }, [VLIM1] = { @@ -1187,7 +1187,7 @@ static int qnovo_hw_init(struct qnovo *chip) u8 iadc_offset_external, iadc_offset_internal; u8 iadc_gain_external, iadc_gain_internal; u8 vadc_offset, vadc_gain; - u8 buf[2] = {0, 0}; + u8 val; vote(chip->disable_votable, USER_VOTER, 1, 0); @@ -1241,13 +1241,39 @@ static int qnovo_hw_init(struct qnovo *chip) chip->v_gain_mega = 1000000000 + (s64)vadc_gain * GAIN_LSB_FACTOR; chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000); - if (chip->wa_flags & QNOVO_ERASE_OFFSET_WA_BIT) { - rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_0, buf, 2); - if (rc < 0) { - pr_err("Couldn't erase offset rc = %d\n", rc); - return rc; - } + val = 0; + rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc bitsteam control rc = %d\n", rc); + return rc; + } + + rc = qnovo_read(chip, QNOVO_TR_IADC_OFFSET_0, &val, 1); + if (rc < 0) { + pr_err("Couldn't read iadc offset rc = %d\n", rc); + return rc; + } + + val *= -1; + rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_0, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc offset rc = %d\n", rc); + return rc; + } + + rc = qnovo_read(chip, QNOVO_TR_IADC_OFFSET_1, &val, 1); + if (rc < 0) { + pr_err("Couldn't read iadc offset rc = %d\n", rc); + return rc; } + + val *= -1; + rc = qnovo_write(chip, QNOVO_TR_IADC_OFFSET_1, &val, 1); + if (rc < 0) { + pr_err("Couldn't write iadc offset rc = %d\n", rc); + return rc; + } + return 0; } diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index dea932ae37ad..f8171ecc47f3 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -620,7 +620,7 @@ static int smb2_usb_main_get_prop(struct power_supply *psy, rc = smblib_get_prop_fcc_delta(chg, val); break; default: - pr_err("get prop %d is not supported in usb-main\n", psp); + pr_debug("get prop %d is not supported in usb-main\n", psp); rc = -EINVAL; break; } @@ -1305,7 +1305,22 @@ static int smb2_init_hw(struct smb2 *chip) smblib_get_charge_param(chg, &chg->param.dc_icl, &chip->dt.dc_icl_ua); - chg->otg_cl_ua = chip->dt.otg_cl_ua; + /* set a slower soft start setting for OTG */ + rc = smblib_masked_write(chg, DC_ENG_SSUPPLY_CFG2_REG, + ENG_SSUPPLY_IVREF_OTG_SS_MASK, OTG_SS_SLOW); + if (rc < 0) { + pr_err("Couldn't set otg soft start rc=%d\n", rc); + return rc; + } + + /* set OTG current limit */ + rc = smblib_set_charge_param(chg, &chg->param.otg_cl, + chip->dt.otg_cl_ua); + if (rc < 0) { + pr_err("Couldn't set otg current limit rc=%d\n", rc); + return rc; + } + chg->dcp_icl_ua = chip->dt.usb_icl_ua; chg->boost_threshold_ua = chip->dt.boost_threshold_ua; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 022ed49ce6eb..ee5b5a51465b 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -505,7 +505,7 @@ static int smblib_notifier_call(struct notifier_block *nb, schedule_work(&chg->bms_update_work); } - if (!chg->pl.psy && !strcmp(psy->desc->name, "usb-parallel")) + if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel")) chg->pl.psy = psy; return NOTIFY_OK; @@ -762,20 +762,6 @@ out: return rc; } -#define MICRO_250MA 250000 -static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua) -{ - int rc = 0; - - rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_cl_ua); - if (rc < 0) { - smblib_err(chg, "Couldn't set otg current limit rc=%d\n", rc); - return rc; - } - - return rc; -} - static int smblib_dc_icl_vote_callback(struct votable *votable, void *data, int icl_ua, const char *client) { @@ -955,22 +941,33 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable, * VCONN REGULATOR * * *****************/ +#define MAX_OTG_SS_TRIES 2 static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); u8 otg_stat, stat4; - int rc = 0; + int rc = 0, i; if (!chg->external_vconn) { - rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); - return rc; + /* + * Hardware based OTG soft start should complete within 1ms, so + * wait for 2ms in the worst case. + */ + for (i = 0; i < MAX_OTG_SS_TRIES; ++i) { + usleep_range(1000, 1100); + rc = smblib_read(chg, OTG_STATUS_REG, &otg_stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read OTG status rc=%d\n", + rc); + return rc; + } + + if (otg_stat & BOOST_SOFTSTART_DONE_BIT) + break; } - if ((otg_stat & OTG_STATE_MASK) != OTG_STATE_ENABLED) { - smblib_err(chg, "Couldn't enable VCONN; OTG is not ready otg_stat=0x%02x\n", - otg_stat); + if (!(otg_stat & BOOST_SOFTSTART_DONE_BIT)) { + smblib_err(chg, "Couldn't enable VCONN; OTG soft start failed\n"); return -EAGAIN; } } @@ -985,6 +982,7 @@ static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev) return rc; } + smblib_dbg(chg, PR_OTG, "enabling VCONN\n"); stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT; rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT, @@ -1002,7 +1000,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (chg->vconn_en) goto unlock; @@ -1011,7 +1009,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev) chg->vconn_en = true; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1020,6 +1018,7 @@ static int _smblib_vconn_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; + smblib_dbg(chg, PR_OTG, "disabling VCONN\n"); rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, VCONN_EN_VALUE_BIT, 0); if (rc < 0) @@ -1033,7 +1032,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (!chg->vconn_en) goto unlock; @@ -1042,7 +1041,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev) chg->vconn_en = false; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1051,9 +1050,9 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int ret; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); ret = chg->vconn_en; - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return ret; } @@ -1061,14 +1060,12 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) * OTG REGULATOR * *****************/ -#define MAX_SOFTSTART_TRIES 2 static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); - u8 stat; - int rc = 0; - int tries = MAX_SOFTSTART_TRIES; + int rc; + smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, ENG_BUCKBOOST_HALT1_8_MODE_BIT); @@ -1078,34 +1075,13 @@ static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) return rc; } + smblib_dbg(chg, PR_OTG, "enabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); if (rc < 0) { smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc); return rc; } - /* waiting for boost readiness, usually ~1ms, 2ms in worst case */ - do { - usleep_range(1000, 1100); - - rc = smblib_read(chg, OTG_STATUS_REG, &stat); - if (rc < 0) { - smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", - rc); - return rc; - } - if (stat & BOOST_SOFTSTART_DONE_BIT) { - smblib_otg_cl_config(chg, chg->otg_cl_ua); - break; - } - } while (--tries); - - if (tries == 0) { - smblib_err(chg, "Timeout waiting for boost softstart rc=%d\n", - rc); - return -ETIMEDOUT; - } - return rc; } @@ -1114,7 +1090,7 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (chg->otg_en) goto unlock; @@ -1123,7 +1099,7 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) chg->otg_en = true; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1131,32 +1107,23 @@ static int _smblib_vbus_regulator_disable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); int rc; - u8 stat; - if (!chg->external_vconn) { - rc = smblib_read(chg, RID_CC_CONTROL_7_0_REG, &stat); + if (!chg->external_vconn && chg->vconn_en) { + smblib_dbg(chg, PR_OTG, "Killing VCONN before disabling OTG\n"); + rc = _smblib_vconn_regulator_disable(rdev); if (rc < 0) - smblib_err(chg, "Couldn't read RID_CC_CONTROL_7_0 rc=%d\n", - rc); - - /* check if VCONN is enabled on either CC pin */ - if (stat & VCONN_EN_CC_MASK) { - smblib_dbg(chg, PR_MISC, "Killing VCONN before disabling OTG\n"); - rc = _smblib_vconn_regulator_disable(rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", - rc); - } + smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); } + smblib_dbg(chg, PR_OTG, "disabling OTG\n"); rc = smblib_write(chg, CMD_OTG_REG, 0); if (rc < 0) { smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc); return rc; } - smblib_otg_cl_config(chg, MICRO_250MA); - + smblib_dbg(chg, PR_OTG, "start 1 in 8 mode\n"); + rc = smblib_write(chg, CMD_OTG_REG, 0); rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0); if (rc < 0) { @@ -1172,7 +1139,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int rc = 0; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); if (!chg->otg_en) goto unlock; @@ -1181,7 +1148,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev) chg->otg_en = false; unlock: - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return rc; } @@ -1190,9 +1157,9 @@ int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev) struct smb_charger *chg = rdev_get_drvdata(rdev); int ret; - mutex_lock(&chg->otg_overcurrent_lock); + mutex_lock(&chg->otg_oc_lock); ret = chg->otg_en; - mutex_unlock(&chg->otg_overcurrent_lock); + mutex_unlock(&chg->otg_oc_lock); return ret; } @@ -1955,6 +1922,29 @@ int smblib_get_pe_start(struct smb_charger *chg, return 0; } +int smblib_get_prop_connector_therm_zone(struct smb_charger *chg, + union power_supply_propval *val) +{ + int rc, i; + u8 stat; + + rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat); + if (rc < 0) { + smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n", + rc); + return rc; + } + + i = fls((stat & TEMP_RANGE_MASK) >> TEMP_RANGE_SHIFT) - 1; + if (i < 0) { + smblib_err(chg, "TEMP_RANGE is invalid\n"); + return -EINVAL; + } + + val->intval = i; + return 0; +} + /******************* * USB PSY SETTERS * * *****************/ @@ -2467,50 +2457,9 @@ irqreturn_t smblib_handle_otg_overcurrent(int irq, void *data) return IRQ_HANDLED; } - if (!(stat & OTG_OVERCURRENT_RT_STS_BIT)) - return IRQ_HANDLED; - - smblib_err(chg, "over-current detected on VBUS\n"); - if (!chg->vbus_vreg || !chg->vbus_vreg->rdev) - return IRQ_HANDLED; - - mutex_lock(&chg->otg_overcurrent_lock); - if (!chg->external_vconn && chg->vconn_en) { - rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); - } - - rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc); + if (stat & OTG_OVERCURRENT_RT_STS_BIT) + schedule_work(&chg->otg_oc_work); - /* - * VBUS must be disabled after OC to be ready for the next insertion. - * If the maximum number of attempts have been reached then don't try - * to re-enable. - */ - if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) { - smblib_err(chg, "OTG failed to enable after %d attempts\n", - chg->otg_attempts - 1); - goto unlock; - } - - /* allow the attached device to discharge */ - msleep(250); - - rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc); - - if (!chg->external_vconn && chg->vconn_en) { - rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); - } - -unlock: - mutex_unlock(&chg->otg_overcurrent_lock); return IRQ_HANDLED; } @@ -3094,41 +3043,6 @@ irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg) return IRQ_HANDLED; } -static void smblib_handle_vconn_overcurrent(struct smb_charger *chg) -{ - int rc; - - smblib_err(chg, "over-current detected on VCONN\n"); - if (!chg->vconn_vreg || !chg->vconn_vreg->rdev) - return; - - mutex_lock(&chg->otg_overcurrent_lock); - rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); - - /* - * VCONN must be disabled after OC to be ready for the next insertion. - * If the maximum number of attempts have been reached then don't try - * to re-enable. - */ - if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { - smblib_err(chg, "VCONN failed to enable after %d attempts\n", - chg->vconn_attempts - 1); - goto unlock; - } - - /* allow the attached device to discharge */ - msleep(250); - - rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); - if (rc < 0) - smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); - -unlock: - mutex_unlock(&chg->otg_overcurrent_lock); -} - irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) { struct smb_irq_data *irq_data = data; @@ -3168,7 +3082,7 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) irq_data->name); if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT) - smblib_handle_vconn_overcurrent(chg); + schedule_work(&chg->vconn_oc_work); power_supply_changed(chg->usb_psy); smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4); @@ -3362,10 +3276,213 @@ rerun: schedule_work(&chg->rdstd_cc2_detach_work); } +static void smblib_otg_oc_exit(struct smb_charger *chg, bool success) +{ + int rc; + + chg->otg_attempts = 0; + if (!success) { + smblib_err(chg, "OTG soft start failed\n"); + chg->otg_en = false; + } + + smblib_dbg(chg, PR_OTG, "enabling VBUS < 1V check\n"); + rc = smblib_masked_write(chg, OTG_CFG_REG, + QUICKSTART_OTG_FASTROLESWAP_BIT, 0); + if (rc < 0) + smblib_err(chg, "Couldn't enable VBUS < 1V check rc=%d\n", rc); + + if (!chg->external_vconn && chg->vconn_en) { + chg->vconn_attempts = 0; + if (success) { + rc = _smblib_vconn_regulator_enable( + chg->vconn_vreg->rdev); + if (rc < 0) + smblib_err(chg, "Couldn't enable VCONN rc=%d\n", + rc); + } else { + chg->vconn_en = false; + } + } +} + +#define MAX_OC_FALLING_TRIES 10 +static void smblib_otg_oc_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + otg_oc_work); + int rc, i; + u8 stat; + + if (!chg->vbus_vreg || !chg->vbus_vreg->rdev) + return; + + smblib_err(chg, "over-current detected on VBUS\n"); + mutex_lock(&chg->otg_oc_lock); + if (!chg->otg_en) + goto unlock; + + smblib_dbg(chg, PR_OTG, "disabling VBUS < 1V check\n"); + smblib_masked_write(chg, OTG_CFG_REG, + QUICKSTART_OTG_FASTROLESWAP_BIT, + QUICKSTART_OTG_FASTROLESWAP_BIT); + + /* + * If 500ms has passed and another over-current interrupt has not + * triggered then it is likely that the software based soft start was + * successful and the VBUS < 1V restriction should be re-enabled. + */ + schedule_delayed_work(&chg->otg_ss_done_work, msecs_to_jiffies(500)); + + rc = _smblib_vbus_regulator_disable(chg->vbus_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't disable VBUS rc=%d\n", rc); + goto unlock; + } + + if (++chg->otg_attempts > OTG_MAX_ATTEMPTS) { + cancel_delayed_work_sync(&chg->otg_ss_done_work); + smblib_err(chg, "OTG failed to enable after %d attempts\n", + chg->otg_attempts - 1); + smblib_otg_oc_exit(chg, false); + goto unlock; + } + + /* + * The real time status should go low within 10ms. Poll every 1-2ms to + * minimize the delay when re-enabling OTG. + */ + for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) { + usleep_range(1000, 2000); + rc = smblib_read(chg, OTG_BASE + INT_RT_STS_OFFSET, &stat); + if (rc >= 0 && !(stat & OTG_OVERCURRENT_RT_STS_BIT)) + break; + } + + if (i >= MAX_OC_FALLING_TRIES) { + cancel_delayed_work_sync(&chg->otg_ss_done_work); + smblib_err(chg, "OTG OC did not fall after %dms\n", + 2 * MAX_OC_FALLING_TRIES); + smblib_otg_oc_exit(chg, false); + goto unlock; + } + + smblib_dbg(chg, PR_OTG, "OTG OC fell after %dms\n", 2 * i + 1); + rc = _smblib_vbus_regulator_enable(chg->vbus_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't enable VBUS rc=%d\n", rc); + goto unlock; + } + +unlock: + mutex_unlock(&chg->otg_oc_lock); +} + +static void smblib_vconn_oc_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + vconn_oc_work); + int rc, i; + u8 stat; + + smblib_err(chg, "over-current detected on VCONN\n"); + if (!chg->vconn_vreg || !chg->vconn_vreg->rdev) + return; + + mutex_lock(&chg->otg_oc_lock); + rc = _smblib_vconn_regulator_disable(chg->vconn_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't disable VCONN rc=%d\n", rc); + goto unlock; + } + + if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { + smblib_err(chg, "VCONN failed to enable after %d attempts\n", + chg->otg_attempts - 1); + chg->vconn_en = false; + chg->vconn_attempts = 0; + goto unlock; + } + + /* + * The real time status should go low within 10ms. Poll every 1-2ms to + * minimize the delay when re-enabling OTG. + */ + for (i = 0; i < MAX_OC_FALLING_TRIES; ++i) { + usleep_range(1000, 2000); + rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat); + if (rc >= 0 && !(stat & TYPEC_VCONN_OVERCURR_STATUS_BIT)) + break; + } + + if (i >= MAX_OC_FALLING_TRIES) { + smblib_err(chg, "VCONN OC did not fall after %dms\n", + 2 * MAX_OC_FALLING_TRIES); + chg->vconn_en = false; + chg->vconn_attempts = 0; + goto unlock; + } + + smblib_dbg(chg, PR_OTG, "VCONN OC fell after %dms\n", 2 * i + 1); + if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) { + smblib_err(chg, "VCONN failed to enable after %d attempts\n", + chg->vconn_attempts - 1); + chg->vconn_en = false; + goto unlock; + } + + rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev); + if (rc < 0) { + smblib_err(chg, "Couldn't enable VCONN rc=%d\n", rc); + goto unlock; + } + +unlock: + mutex_unlock(&chg->otg_oc_lock); +} + +static void smblib_otg_ss_done_work(struct work_struct *work) +{ + struct smb_charger *chg = container_of(work, struct smb_charger, + otg_ss_done_work.work); + int rc; + bool success = false; + u8 stat; + + mutex_lock(&chg->otg_oc_lock); + rc = smblib_read(chg, OTG_STATUS_REG, &stat); + if (rc < 0) + smblib_err(chg, "Couldn't read OTG status rc=%d\n", rc); + else if (stat & BOOST_SOFTSTART_DONE_BIT) + success = true; + + smblib_otg_oc_exit(chg, success); + mutex_unlock(&chg->otg_oc_lock); +} + static int smblib_create_votables(struct smb_charger *chg) { int rc = 0; + chg->fcc_votable = find_votable("FCC"); + if (!chg->fcc_votable) { + rc = -EPROBE_DEFER; + return rc; + } + + chg->fv_votable = find_votable("FV"); + if (!chg->fv_votable) { + rc = -EPROBE_DEFER; + return rc; + } + + chg->pl_disable_votable = find_votable("PL_DISABLE"); + if (!chg->pl_disable_votable) { + rc = -EPROBE_DEFER; + return rc; + } + vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); + chg->usb_suspend_votable = create_votable("USB_SUSPEND", VOTE_SET_ANY, smblib_usb_suspend_vote_callback, chg); @@ -3390,18 +3507,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->fcc_votable = find_votable("FCC"); - if (!chg->fcc_votable) { - rc = -EPROBE_DEFER; - return rc; - } - - chg->fv_votable = find_votable("FV"); - if (!chg->fv_votable) { - rc = -EPROBE_DEFER; - return rc; - } - chg->usb_icl_votable = create_votable("USB_ICL", VOTE_MIN, smblib_usb_icl_vote_callback, chg); @@ -3441,13 +3546,6 @@ static int smblib_create_votables(struct smb_charger *chg) return rc; } - chg->pl_disable_votable = find_votable("PL_DISABLE"); - if (!chg->pl_disable_votable) { - rc = -EPROBE_DEFER; - return rc; - } - vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0); - chg->chg_disable_votable = create_votable("CHG_DISABLE", VOTE_SET_ANY, smblib_chg_disable_vote_callback, chg); @@ -3541,12 +3639,15 @@ int smblib_init(struct smb_charger *chg) int rc = 0; mutex_init(&chg->write_lock); - mutex_init(&chg->otg_overcurrent_lock); + mutex_init(&chg->otg_oc_lock); INIT_WORK(&chg->bms_update_work, bms_update_work); INIT_WORK(&chg->rdstd_cc2_detach_work, rdstd_cc2_detach_work); INIT_DELAYED_WORK(&chg->hvdcp_detect_work, smblib_hvdcp_detect_work); INIT_DELAYED_WORK(&chg->step_soc_req_work, step_soc_req_work); INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work); + INIT_WORK(&chg->otg_oc_work, smblib_otg_oc_work); + INIT_WORK(&chg->vconn_oc_work, smblib_vconn_oc_work); + INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work); chg->fake_capacity = -EINVAL; switch (chg->mode) { @@ -3566,8 +3667,7 @@ int smblib_init(struct smb_charger *chg) } chg->bms_psy = power_supply_get_by_name("bms"); - chg->pl.psy = power_supply_get_by_name("usb-parallel"); - + chg->pl.psy = power_supply_get_by_name("parallel"); break; case PARALLEL_SLAVE: break; diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index b3fce23c6508..cda4b80939ec 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -24,6 +24,7 @@ enum print_reason { PR_REGISTER = BIT(1), PR_MISC = BIT(2), PR_PARALLEL = BIT(3), + PR_OTG = BIT(4), }; #define DEFAULT_VOTER "DEFAULT_VOTER" @@ -135,6 +136,9 @@ struct smb_iio { struct iio_channel *usbin_i_chan; struct iio_channel *usbin_v_chan; struct iio_channel *batt_i_chan; + struct iio_channel *connector_temp_thr1_chan; + struct iio_channel *connector_temp_thr2_chan; + struct iio_channel *connector_temp_thr3_chan; }; struct reg_info { @@ -158,7 +162,7 @@ struct smb_charger { /* locks */ struct mutex write_lock; struct mutex ps_change_lock; - struct mutex otg_overcurrent_lock; + struct mutex otg_oc_lock; /* power supplies */ struct power_supply *batt_psy; @@ -204,6 +208,9 @@ struct smb_charger { struct delayed_work ps_change_timeout_work; struct delayed_work step_soc_req_work; struct delayed_work clear_hdc_work; + struct work_struct otg_oc_work; + struct work_struct vconn_oc_work; + struct delayed_work otg_ss_done_work; /* cached status */ int voltage_min_uv; @@ -214,7 +221,6 @@ struct smb_charger { int system_temp_level; int thermal_levels; int *thermal_mitigation; - int otg_cl_ua; int dcp_icl_ua; int fake_capacity; bool step_chg_enabled; @@ -360,6 +366,8 @@ int smblib_get_prop_charger_temp(struct smb_charger *chg, union power_supply_propval *val); int smblib_get_prop_charger_temp_max(struct smb_charger *chg, union power_supply_propval *val); +int smblib_get_prop_connector_therm_zone(struct smb_charger *chg, + union power_supply_propval *val); int smblib_set_prop_pd_current_max(struct smb_charger *chg, const union power_supply_propval *val); int smblib_set_prop_usb_current_max(struct smb_charger *chg, diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h index 5f74e27c7978..b5de39de995a 100644 --- a/drivers/power/supply/qcom/smb-reg.h +++ b/drivers/power/supply/qcom/smb-reg.h @@ -366,7 +366,9 @@ enum { #define OTG_CURRENT_LIMIT_MASK GENMASK(2, 0) #define OTG_CFG_REG (OTG_BASE + 0x53) -#define OTG_RESERVED_MASK GENMASK(7, 4) +#define OTG_RESERVED_MASK GENMASK(7, 6) +#define DIS_OTG_ON_TLIM_BIT BIT(5) +#define QUICKSTART_OTG_FASTROLESWAP_BIT BIT(4) #define INCREASE_DFP_TIME_BIT BIT(3) #define ENABLE_OTG_IN_DEBUG_MODE_BIT BIT(2) #define OTG_EN_SRC_CFG_BIT BIT(1) @@ -793,6 +795,10 @@ enum { ZIN_ICL_HV_MAX_MV = 11000, }; +#define DC_ENG_SSUPPLY_CFG2_REG (DCIN_BASE + 0xC1) +#define ENG_SSUPPLY_IVREF_OTG_SS_MASK GENMASK(2, 0) +#define OTG_SS_SLOW 0x3 + #define DC_ENG_SSUPPLY_CFG3_REG (DCIN_BASE + 0xC2) #define ENG_SSUPPLY_HI_CAP_BIT BIT(6) #define ENG_SSUPPLY_HI_RES_BIT BIT(5) @@ -817,6 +823,8 @@ enum { #define TEMP_RANGE_STATUS_7_BIT BIT(7) #define THERM_REG_ACTIVE_BIT BIT(6) #define TLIM_BIT BIT(5) +#define TEMP_RANGE_MASK GENMASK(4, 1) +#define TEMP_RANGE_SHIFT 1 #define ALERT_LEVEL_BIT BIT(4) #define TEMP_ABOVE_RANGE_BIT BIT(3) #define TEMP_WITHIN_RANGE_BIT BIT(2) diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c index ae15fef6c3a6..9287b7c37b97 100644 --- a/drivers/power/supply/qcom/smb138x-charger.c +++ b/drivers/power/supply/qcom/smb138x-charger.c @@ -10,18 +10,21 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) "SMB138X: %s: " fmt, __func__ + #include <linux/device.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/regmap.h> -#include <linux/power_supply.h> +#include <linux/iio/consumer.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/power_supply.h> +#include <linux/regmap.h> #include <linux/regulator/driver.h> -#include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> #include <linux/qpnp/qpnp-revid.h> #include "smb-reg.h" #include "smb-lib.h" @@ -89,6 +92,8 @@ struct smb_dt_props { int fcc_ua; int usb_icl_ua; int dc_icl_ua; + int chg_temp_max_mdegc; + int connector_temp_max_mdegc; }; struct smb138x { @@ -132,6 +137,18 @@ static int smb138x_parse_dt(struct smb138x *chip) if (rc < 0) chip->dt.dc_icl_ua = SMB138X_DEFAULT_ICL_UA; + rc = of_property_read_u32(node, + "qcom,charger-temp-max-mdegc", + &chip->dt.chg_temp_max_mdegc); + if (rc < 0) + chip->dt.chg_temp_max_mdegc = 80000; + + rc = of_property_read_u32(node, + "qcom,connector-temp-max-mdegc", + &chip->dt.chg_temp_max_mdegc); + if (rc < 0) + chip->dt.connector_temp_max_mdegc = 105000; + return 0; } @@ -415,6 +432,7 @@ static enum power_supply_property smb138x_parallel_props[] = { POWER_SUPPLY_PROP_CHARGER_TEMP_MAX, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_PARALLEL_MODE, + POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, }; static int smb138x_parallel_get_prop(struct power_supply *psy, @@ -467,6 +485,9 @@ static int smb138x_parallel_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_PARALLEL_MODE: val->intval = POWER_SUPPLY_PARALLEL_MID_MID; break; + case POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE: + rc = smblib_get_prop_connector_therm_zone(chg, val); + break; default: pr_err("parallel power supply get prop %d not supported\n", prop); @@ -658,6 +679,138 @@ static int smb138x_init_vconn_regulator(struct smb138x *chip) * HARDWARE INITIALIZATION * ***************************/ +#define MDEGC_3 3000 +#define MDEGC_15 15000 +static int smb138x_init_slave_hw(struct smb138x *chip) +{ + struct smb_charger *chg = &chip->chg; + int rc; + + if (chip->wa_flags & OOB_COMP_WA_BIT) { + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, + ENG_SDCDC_SEL_OOB_VTH_BIT, + ENG_SDCDC_SEL_OOB_VTH_BIT); + if (rc < 0) { + pr_err("Couldn't configure the OOB comp threshold rc = %d\n", + rc); + return rc; + } + + rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, + DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); + if (rc < 0) { + pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n", + rc); + return rc; + } + } + + /* enable watchdog bark and bite interrupts, and disable the watchdog */ + rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT + | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT + | BARK_WDOG_INT_EN_BIT, + BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog rc=%d\n", rc); + return rc; + } + + /* disable charging when watchdog bites */ + rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT, + BITE_WDOG_DISABLE_CHARGING_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + return rc; + } + + /* suspend parallel charging */ + rc = smb138x_set_parallel_suspend(chip, true); + if (rc < 0) { + pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + return rc; + } + + /* initialize FCC to 0 */ + rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); + if (rc < 0) { + pr_err("Couldn't set 0 FCC rc=%d\n", rc); + return rc; + } + + /* enable the charging path */ + rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG, + CHARGING_ENABLE_CMD_BIT, + CHARGING_ENABLE_CMD_BIT); + if (rc < 0) { + pr_err("Couldn't enable charging rc=%d\n", rc); + return rc; + } + + /* configure charge enable for software control; active high */ + rc = smblib_masked_write(chg, CHGR_CFG2_REG, + CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); + if (rc < 0) { + pr_err("Couldn't configure charge enable source rc=%d\n", + rc); + return rc; + } + + /* enable parallel current sensing */ + rc = smblib_masked_write(chg, CFG_REG, + VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT); + if (rc < 0) { + pr_err("Couldn't enable parallel current sensing rc=%d\n", + rc); + return rc; + } + + /* enable stacked diode */ + rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable stacked diode rc=%d\n", rc); + return rc; + } + + /* initialize charger temperature threshold */ + rc = iio_write_channel_processed(chg->iio.temp_max_chan, + chip->dt.chg_temp_max_mdegc); + if (rc < 0) { + pr_err("Couldn't set charger temp threshold rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr1_chan, + chip->dt.connector_temp_max_mdegc); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold1 rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr2_chan, + chip->dt.connector_temp_max_mdegc + MDEGC_3); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold2 rc=%d\n", rc); + return rc; + } + + rc = iio_write_channel_processed(chg->iio.connector_temp_thr3_chan, + chip->dt.connector_temp_max_mdegc + MDEGC_15); + if (rc < 0) { + pr_err("Couldn't set connector temp threshold3 rc=%d\n", rc); + return rc; + } + + rc = smblib_write(chg, THERMREG_SRC_CFG_REG, + THERMREG_SKIN_ADC_SRC_EN_BIT); + if (rc < 0) { + pr_err("Couldn't enable connector thermreg source rc=%d\n", rc); + return rc; + } + + return 0; +} + static int smb138x_init_hw(struct smb138x *chip) { struct smb_charger *chg = &chip->chg; @@ -681,15 +834,14 @@ static int smb138x_init_hw(struct smb138x *chip) rc = smblib_masked_write(chg, CHGR_CFG2_REG, CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure charge enable source rc=%d\n", rc); + pr_err("Couldn't configure charge enable source rc=%d\n", rc); return rc; } /* enable the charging path */ rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); + pr_err("Couldn't enable charging rc=%d\n", rc); return rc; } @@ -701,8 +853,7 @@ static int smb138x_init_hw(struct smb138x *chip) TYPEC_CCSTATE_CHANGE_INT_EN_BIT | TYPEC_VBUS_ERROR_INT_EN_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure Type-C interrupts rc=%d\n", rc); + pr_err("Couldn't configure Type-C interrupts rc=%d\n", rc); return rc; } @@ -711,16 +862,14 @@ static int smb138x_init_hw(struct smb138x *chip) VCONN_EN_SRC_BIT | VCONN_EN_VALUE_BIT, VCONN_EN_SRC_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure VCONN for SW control rc=%d\n", rc); + pr_err("Couldn't configure VCONN for SW control rc=%d\n", rc); return rc; } /* configure VBUS for software control */ rc = smblib_masked_write(chg, OTG_CFG_REG, OTG_EN_SRC_CFG_BIT, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure VBUS for SW control rc=%d\n", rc); + pr_err("Couldn't configure VBUS for SW control rc=%d\n", rc); return rc; } @@ -728,8 +877,7 @@ static int smb138x_init_hw(struct smb138x *chip) rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure power role for DRP rc=%d\n", rc); + pr_err("Couldn't configure power role for DRP rc=%d\n", rc); return rc; } @@ -738,16 +886,16 @@ static int smb138x_init_hw(struct smb138x *chip) ENG_SDCDC_SEL_OOB_VTH_BIT, ENG_SDCDC_SEL_OOB_VTH_BIT); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the oob comp threh rc = %d\n", rc); + pr_err("Couldn't configure the OOB comp threshold rc = %d\n", + rc); return rc; } rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); + pr_err("Couldn't configure the sdcdc cfg 6 reg rc = %d\n", + rc); return rc; } } @@ -795,6 +943,23 @@ static int smb138x_setup_wa_flags(struct smb138x *chip) * DETERMINE INITIAL STATUS * ****************************/ +static irqreturn_t smb138x_handle_temperature_change(int irq, void *data) +{ + struct smb_irq_data *irq_data = data; + struct smb138x *chip = irq_data->parent_data; + + power_supply_changed(chip->parallel_psy); + return IRQ_HANDLED; +} + +static int smb138x_determine_initial_slave_status(struct smb138x *chip) +{ + struct smb_irq_data irq_data = {chip, "determine-initial-status"}; + + smb138x_handle_temperature_change(0, &irq_data); + return 0; +} + static int smb138x_determine_initial_status(struct smb138x *chip) { struct smb_irq_data irq_data = {chip, "determine-initial-status"}; @@ -802,7 +967,6 @@ static int smb138x_determine_initial_status(struct smb138x *chip) smblib_handle_usb_plugin(0, &irq_data); smblib_handle_usb_typec_change(0, &irq_data); smblib_handle_usb_source_change(0, &irq_data); - return 0; } @@ -971,7 +1135,7 @@ static const struct smb138x_irq_info smb138x_irqs[] = { }, { .name = "temperature-change", - .handler = smblib_handle_debug, + .handler = smb138x_handle_temperature_change, }, { .name = "switcher-power-ok", @@ -1144,95 +1308,54 @@ static int smb138x_slave_probe(struct smb138x *chip) goto cleanup; } - if (chip->wa_flags & OOB_COMP_WA_BIT) { - rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG2, - ENG_SDCDC_SEL_OOB_VTH_BIT, - ENG_SDCDC_SEL_OOB_VTH_BIT); - if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the oob comp threh rc = %d\n", rc); - goto cleanup; - } - - rc = smblib_masked_write(chg, SMB2CHG_MISC_ENG_SDCDC_CFG6, - DEAD_TIME_MASK, HIGH_DEAD_TIME_MASK); - if (rc < 0) { - dev_err(chg->dev, - "Couldn't configure the sdcdc cfg 6 reg rc = %d\n", rc); - goto cleanup; - } - } - - /* enable watchdog bark and bite interrupts, and disable the watchdog */ - rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT - | WDOG_TIMER_EN_ON_PLUGIN_BIT | BITE_WDOG_INT_EN_BIT - | BARK_WDOG_INT_EN_BIT, - BITE_WDOG_INT_EN_BIT | BARK_WDOG_INT_EN_BIT); - if (rc < 0) { - pr_err("Couldn't configure the watchdog rc=%d\n", rc); + chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max"); + if (IS_ERR(chg->iio.temp_max_chan)) { + rc = PTR_ERR(chg->iio.temp_max_chan); goto cleanup; } - /* disable charging when watchdog bites */ - rc = smblib_masked_write(chg, SNARL_BARK_BITE_WD_CFG_REG, - BITE_WDOG_DISABLE_CHARGING_CFG_BIT, - BITE_WDOG_DISABLE_CHARGING_CFG_BIT); - if (rc < 0) { - pr_err("Couldn't configure the watchdog bite rc=%d\n", rc); + chg->iio.connector_temp_thr1_chan = iio_channel_get(chg->dev, + "connector_temp_thr1"); + if (IS_ERR(chg->iio.connector_temp_thr1_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr1_chan); goto cleanup; } - /* suspend parallel charging */ - rc = smb138x_set_parallel_suspend(chip, true); - if (rc < 0) { - pr_err("Couldn't suspend parallel charging rc=%d\n", rc); + chg->iio.connector_temp_thr2_chan = iio_channel_get(chg->dev, + "connector_temp_thr2"); + if (IS_ERR(chg->iio.connector_temp_thr2_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr2_chan); goto cleanup; } - /* initialize FCC to 0 */ - rc = smblib_set_charge_param(chg, &chg->param.fcc, 0); - if (rc < 0) { - pr_err("Couldn't set 0 FCC rc=%d\n", rc); + chg->iio.connector_temp_thr3_chan = iio_channel_get(chg->dev, + "connector_temp_thr3"); + if (IS_ERR(chg->iio.connector_temp_thr3_chan)) { + rc = PTR_ERR(chg->iio.connector_temp_thr3_chan); goto cleanup; } - /* enable the charging path */ - rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG, - CHARGING_ENABLE_CMD_BIT, - CHARGING_ENABLE_CMD_BIT); + rc = smb138x_parse_dt(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable charging rc=%d\n", rc); + pr_err("Couldn't parse device tree rc=%d\n", rc); goto cleanup; } - /* configure charge enable for software control; active high */ - rc = smblib_masked_write(chg, CHGR_CFG2_REG, - CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0); + rc = smb138x_init_slave_hw(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't configure charge enable source rc=%d\n", - rc); + pr_err("Couldn't initialize hardware rc=%d\n", rc); goto cleanup; } - /* enable parallel current sensing */ - rc = smblib_masked_write(chg, CFG_REG, - VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT); + rc = smb138x_init_parallel_psy(chip); if (rc < 0) { - dev_err(chg->dev, "Couldn't enable parallel current sensing rc=%d\n", - rc); + pr_err("Couldn't initialize parallel psy rc=%d\n", rc); goto cleanup; } - /* enable stacked diode */ - rc = smblib_write(chg, SMB2CHG_DC_TM_SREFGEN, STACKED_DIODE_EN_BIT); + rc = smb138x_determine_initial_slave_status(chip); if (rc < 0) { - pr_err("Couldn't enable stacked diode rc=%d\n", rc); - return rc; - } - - rc = smb138x_init_parallel_psy(chip); - if (rc < 0) { - pr_err("Couldn't initialize parallel psy rc=%d\n", rc); + pr_err("Couldn't determine initial status rc=%d\n", rc); goto cleanup; } @@ -1312,6 +1435,12 @@ static int smb138x_probe(struct platform_device *pdev) goto cleanup; } + if (rc < 0) { + if (rc != -EPROBE_DEFER) + pr_err("Couldn't probe SMB138X rc=%d\n", rc); + goto cleanup; + } + pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode); return rc; diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 40e1afdfc286..b5e44b237ed8 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -310,13 +310,14 @@ config PWM_RCAR will be called pwm-rcar. config PWM_QPNP + tristate "Qualcomm Technologies, Inc. QPNP LPG/PWM support" depends on SPMI - tristate "Qualcomm QPNP LPG/PWM support" - help - This driver supports PWM/LPG devices in Qualcomm PMIC chips which - comply with QPNP. QPNP is a SPMI based PMIC implementation. These - devices support Pulse Width Modulation output with user generated - patterns. They share a lookup table with size of 64 entries. + help + This driver supports PWM/LPG devices in Qualcomm Technologies, Inc. + PMIC chips which comply with QPNP. QPNP is an SPMI based PMIC + implementation. These devices support Pulse Width Modulation output + with user generated patterns. They share a lookup table with size of + 64 entries. config PWM_RENESAS_TPU tristate "Renesas TPU PWM support" diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c index 6d0c1fbe566b..d57bf2f3b80c 100644 --- a/drivers/pwm/pwm-qpnp.c +++ b/drivers/pwm/pwm-qpnp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -10,7 +10,7 @@ * GNU General Public License for more details. */ /* - * Qualcomm QPNP Pulse Width Modulation (PWM) driver + * Qualcomm Technologies, Inc. QPNP Pulse Width Modulation (PWM) driver * * The HW module is also called LPG (Light Pattern Generator). */ @@ -382,6 +382,7 @@ static int qpnp_set_control(struct qpnp_pwm_chip *chip, bool pwm_hi, bool pwm_lo, bool pwm_out, bool pwm_src, bool ramp_gen) { int value; + value = (ramp_gen << QPNP_PWM_EN_RAMP_GEN_SHIFT) | (pwm_src << QPNP_PWM_SRC_SELECT_SHIFT) | (pwm_lo << QPNP_EN_PWM_LO_SHIFT) | @@ -476,7 +477,7 @@ static void qpnp_lpg_calc_period(enum time_level tm_lvl, n = 6; if (tm_lvl == LVL_USEC) { - if (period_value < ((unsigned)(-1) / NSEC_PER_USEC)) { + if (period_value < ((unsigned int)(-1) / NSEC_PER_USEC)) { period_n = (period_value * NSEC_PER_USEC) >> n; } else { if (supported_sizes == QPNP_PWM_SIZE_7_8_BIT) @@ -499,7 +500,7 @@ static void qpnp_lpg_calc_period(enum time_level tm_lvl, chip->channel_id, n); } - min_err = last_err = (unsigned)(-1); + min_err = last_err = (unsigned int)(-1); best_m = 0; best_clk = 0; best_div = 0; @@ -1233,7 +1234,7 @@ static int _pwm_config(struct qpnp_pwm_chip *chip, } pr_debug("duty/period=%u/%u %s: pwm_value=%d (of %d)\n", - (unsigned)duty_value, (unsigned)period_value, + (unsigned int)duty_value, (unsigned int)period_value, (tm_lvl == LVL_USEC) ? "usec" : "nsec", pwm_config->pwm_value, 1 << period->pwm_size); @@ -1290,7 +1291,7 @@ after_table_write: QPNP_SET_PAUSE_CNT(lut_config->lut_pause_hi_cnt, lut_params.lut_pause_hi, ramp_step_ms); if (lut_config->lut_pause_hi_cnt > PM_PWM_MAX_PAUSE_CNT) - lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT; + lut_config->lut_pause_hi_cnt = PM_PWM_MAX_PAUSE_CNT; lut_config->ramp_step_ms = ramp_step_ms; @@ -1320,8 +1321,7 @@ static int _pwm_enable(struct qpnp_pwm_chip *chip) chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED) { rc = qpnp_lpg_configure_pwm_state(chip, QPNP_PWM_ENABLE); } else if (!(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) { - rc = qpnp_lpg_configure_lut_state(chip, - QPNP_LUT_ENABLE); + rc = qpnp_lpg_configure_lut_state(chip, QPNP_LUT_ENABLE); } if (!rc) @@ -1368,7 +1368,7 @@ static int qpnp_pwm_config(struct pwm_chip *pwm_chip, struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip); int prev_period_us = chip->pwm_config.pwm_period; - if ((unsigned)period_ns < PM_PWM_PERIOD_MIN * NSEC_PER_USEC) { + if ((unsigned int)period_ns < PM_PWM_PERIOD_MIN * NSEC_PER_USEC) { pr_err("Invalid pwm handle or parameters\n"); return -EINVAL; } @@ -1403,6 +1403,7 @@ static int qpnp_pwm_enable(struct pwm_chip *pwm_chip, { int rc; struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip); + rc = _pwm_enable(chip); if (rc) pr_err("Failed to enable PWM channel: %d\n", chip->channel_id); @@ -1487,7 +1488,7 @@ int pwm_change_mode(struct pwm_device *pwm, enum pm_pwm_mode mode) return rc; } -EXPORT_SYMBOL_GPL(pwm_change_mode); +EXPORT_SYMBOL(pwm_change_mode); /** * pwm_config_period - change PWM period @@ -1592,7 +1593,7 @@ out_unlock: spin_unlock_irqrestore(&chip->lpg_lock, flags); return rc; } -EXPORT_SYMBOL_GPL(pwm_config_pwm_value); +EXPORT_SYMBOL(pwm_config_pwm_value); /** * pwm_config_us - change a PWM device configuration @@ -1608,8 +1609,8 @@ int pwm_config_us(struct pwm_device *pwm, int duty_us, int period_us) if (pwm == NULL || IS_ERR(pwm) || duty_us > period_us || - (unsigned)period_us > PM_PWM_PERIOD_MAX || - (unsigned)period_us < PM_PWM_PERIOD_MIN) { + (unsigned int)period_us > PM_PWM_PERIOD_MAX || + (unsigned int)period_us < PM_PWM_PERIOD_MIN) { pr_err("Invalid pwm handle or parameters\n"); return -EINVAL; } @@ -1622,10 +1623,11 @@ int pwm_config_us(struct pwm_device *pwm, int duty_us, int period_us) qpnp_lpg_calc_period(LVL_USEC, period_us, chip); qpnp_lpg_save_period(chip); chip->pwm_config.pwm_period = period_us; - if ((unsigned)period_us > (unsigned)(-1) / NSEC_PER_USEC) + if ((unsigned int)period_us > + (unsigned int)(-1) / NSEC_PER_USEC) pwm->period = 0; else - pwm->period = (unsigned)period_us * NSEC_PER_USEC; + pwm->period = (unsigned int)period_us * NSEC_PER_USEC; } rc = _pwm_config(chip, LVL_USEC, duty_us, period_us); @@ -1679,8 +1681,8 @@ int pwm_lut_config(struct pwm_device *pwm, int period_us, return -EINVAL; } - if ((unsigned)period_us > PM_PWM_PERIOD_MAX || - (unsigned)period_us < PM_PWM_PERIOD_MIN) { + if ((unsigned int)period_us > PM_PWM_PERIOD_MAX || + (unsigned int)period_us < PM_PWM_PERIOD_MIN) { pr_err("Period out of range\n"); return -EINVAL; } @@ -1702,7 +1704,7 @@ int pwm_lut_config(struct pwm_device *pwm, int period_us, return rc; } -EXPORT_SYMBOL_GPL(pwm_lut_config); +EXPORT_SYMBOL(pwm_lut_config); static int qpnp_parse_pwm_dt_config(struct device_node *of_pwm_node, struct device_node *of_parent, struct qpnp_pwm_chip *chip) @@ -1738,14 +1740,6 @@ static int qpnp_parse_pwm_dt_config(struct device_node *of_pwm_node, return rc; } -#define qpnp_check_optional_dt_bindings(func) \ -do { \ - rc = func; \ - if (rc && rc != -EINVAL) \ - goto out; \ - rc = 0; \ -} while (0) - static int qpnp_parse_lpg_dt_config(struct device_node *of_lpg_node, struct device_node *of_parent, struct qpnp_pwm_chip *chip) { @@ -1778,44 +1772,58 @@ static int qpnp_parse_lpg_dt_config(struct device_node *of_lpg_node, return -EINVAL; } - duty_pct_list = kzalloc(sizeof(u32) * list_size, GFP_KERNEL); - - if (!duty_pct_list) { - pr_err("kzalloc failed on duty_pct_list\n"); + duty_pct_list = kcalloc(list_size, sizeof(*duty_pct_list), GFP_KERNEL); + if (!duty_pct_list) return -ENOMEM; - } rc = of_property_read_u32_array(of_lpg_node, "qcom,duty-percents", duty_pct_list, list_size); if (rc) { - pr_err("invalid or missing property:\n"); - pr_err("qcom,duty-pcts-list\n"); - kfree(duty_pct_list); - return rc; + pr_err("invalid or missing property: qcom,duty-pcts-list\n"); + goto out; } /* Read optional properties */ - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,ramp-step-duration", &lut_config->ramp_step_ms)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pause-hi", &lut_config->lut_pause_hi_cnt)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pause-lo", &lut_config->lut_pause_lo_cnt)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-ramp-direction", - (u32 *)&lut_config->ramp_direction)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-pattern-repeat", - (u32 *)&lut_config->pattern_repeat)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-ramp-toggle", - (u32 *)&lut_config->ramp_toggle)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-enable-pause-hi", - (u32 *)&lut_config->enable_pause_hi)); - qpnp_check_optional_dt_bindings(of_property_read_u32(of_lpg_node, - "qcom,lpg-lut-enable-pause-lo", - (u32 *)&lut_config->enable_pause_lo)); + rc = of_property_read_u32(of_lpg_node, "qcom,ramp-step-duration", + &lut_config->ramp_step_ms); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pause-hi", + &lut_config->lut_pause_hi_cnt); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pause-lo", + &lut_config->lut_pause_lo_cnt); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-ramp-direction", + (u32 *)&lut_config->ramp_direction); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-pattern-repeat", + (u32 *)&lut_config->pattern_repeat); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-ramp-toggle", + (u32 *)&lut_config->ramp_toggle); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-enable-pause-hi", + (u32 *)&lut_config->enable_pause_hi); + if (rc && rc != -EINVAL) + goto out; + + rc = of_property_read_u32(of_lpg_node, "qcom,lpg-lut-enable-pause-lo", + (u32 *)&lut_config->enable_pause_lo); + if (rc && rc != -EINVAL) + goto out; + rc = 0; qpnp_set_lut_params(&lut_params, lut_config, start_idx, list_size); @@ -1877,7 +1885,7 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, struct qpnp_pwm_chip *chip) { int rc, enable, lut_entry_size, list_size, i; - const char *lable; + const char *label; const __be32 *prop; u32 size; struct device_node *node; @@ -1992,12 +2000,10 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, lut_entry_size = sizeof(u8); } - lut_config->duty_pct_list = kzalloc(lpg_config->lut_size * + lut_config->duty_pct_list = kcalloc(lpg_config->lut_size, lut_entry_size, GFP_KERNEL); - if (!lut_config->duty_pct_list) { - pr_err("can not allocate duty pct list\n"); + if (!lut_config->duty_pct_list) return -ENOMEM; - } rc = of_property_read_u32(of_node, "qcom,ramp-index", &lut_config->ramp_index); @@ -2038,18 +2044,18 @@ static int qpnp_parse_dt_config(struct platform_device *pdev, } for_each_child_of_node(of_node, node) { - rc = of_property_read_string(node, "label", &lable); + rc = of_property_read_string(node, "label", &label); if (rc) { - dev_err(&pdev->dev, "%s: Missing lable property\n", + dev_err(&pdev->dev, "%s: Missing label property\n", __func__); goto out; } - if (!strncmp(lable, "pwm", 3)) { + if (!strcmp(label, "pwm")) { rc = qpnp_parse_pwm_dt_config(node, of_node, chip); if (rc) goto out; found_pwm_subnode = 1; - } else if (!strncmp(lable, "lpg", 3) && + } else if (!strcmp(label, "lpg") && !(chip->flags & QPNP_PWM_LUT_NOT_SUPPORTED)) { rc = qpnp_parse_lpg_dt_config(node, of_node, chip); if (rc) @@ -2102,10 +2108,9 @@ static int qpnp_pwm_probe(struct platform_device *pdev) int rc; pwm_chip = kzalloc(sizeof(*pwm_chip), GFP_KERNEL); - if (pwm_chip == NULL) { - pr_err("kzalloc() failed.\n"); + if (pwm_chip == NULL) return -ENOMEM; - } + pwm_chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!pwm_chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -2169,7 +2174,7 @@ static int qpnp_pwm_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_LPG_DRIVER_NAME, }, {} }; diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 8d54ece776e2..e5ba63171eba 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -807,42 +807,43 @@ config REGULATOR_RPM_SMD application processor over SMD. config REGULATOR_QPNP + tristate "Qualcomm Technologies, Inc. QPNP regulator support" depends on SPMI - tristate "Qualcomm QPNP regulator support" help - This driver supports voltage regulators in Qualcomm PMIC chips which - comply with QPNP. QPNP is a SPMI based PMIC implementation. These - chips provide several different varieties of LDO and switching - regulators. They also provide voltage switches and boost regulators. + This driver supports voltage regulators in Qualcomm Technologies, Inc. + PMIC chips which comply with QPNP. QPNP is a SPMI based PMIC + implementation. These chips provide several different varieties of + LDO and switching regulators. They also provide voltage switches and + boost regulators. config REGULATOR_QPNP_LABIBB + tristate "Qualcomm Technologies, Inc. QPNP LAB/IBB regulator support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP LAB/IBB regulator support" help - This driver supports voltage regulators in Qualcomm Technologies, Inc + This driver supports voltage regulators in Qualcomm Technologies, Inc. PMIC chips which comply with QPNP LAB/IBB regulators. QPNP LAB and IBB - are SPMI based PMIC implementation. LAB regulator can be used as a + are SPMI based PMIC implementations. LAB regulator can be used as a regular positive boost regulator. IBB can be used as a regular negative boost regulator. LAB/IBB regulators can also be used together for LCD or AMOLED. config REGULATOR_QPNP_LCDB + tristate "Qualcomm Technologies, Inc. QPNP LCDB support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP LCDB support" help - Supports the LCDB module in the Qualcomm Technologies, Inc - QPNP PMIC. Exposes regulators to control the positive and + Supports the LCDB module in the Qualcomm Technologies, Inc. + QPNP PMICs. Exposes regulators to control the positive and negative voltage bias for the LCD display panel. It also allows configurability for the various bias-voltage parameters. config REGULATOR_QPNP_OLEDB + tristate "Qualcomm Technologies, Inc. QPNP OLEDB regulator support" depends on SPMI - tristate "Qualcomm Technologies, Inc QPNP OLEDB regulator support" help - This driver supports the OLEDB(AVDD bias) signal for AMOLED panel in Qualcomm - Technologies, Inc QPNP PMIC. It exposes the OLED voltage configuration - via the regulator framework. The configurable range of this bias is - 5V to 8.1V. + This driver supports the OLEDB (AVDD bias) signal for AMOLED panel in + Qualcomm Technologies, Inc. QPNP PMICs. It exposes the OLED voltage + configuration via the regulator framework. The configurable range of + this bias is 5 V to 8.1 V. config REGULATOR_SPM bool "SPM regulator driver" @@ -950,19 +951,18 @@ config REGULATOR_KRYO depends on OF help Some MSM designs have CPUs that can be directly powered from a common - voltage rail via a Block Head Switch (BHS) or an LDO whose output voltage - can be configured for use when certain power constraints are met. - Say yes to support management of LDO and BHS modes for the clusters in the - CPU subsystem. + voltage rail via a Block Head Switch (BHS) or an LDO whose output + voltage can be configured for use when certain power constraints are + met. Say yes to support management of LDO and BHS modes for the + clusters in the CPU subsystem. config REGULATOR_MEM_ACC - tristate "QTI Memory accelerator regulator driver" - help - Say y here to enable the memory accelerator driver for Qualcomm - Technologies (QTI) chips. The accelerator controls delays applied - for memory accesses. - This driver configures the power-mode (corner) for the memory - accelerator. + tristate "QTI Memory accelerator regulator driver" + help + Say y here to enable the memory accelerator driver for Qualcomm + Technologies, Inc. (QTI) chips. The accelerator controls delays + applied for memory accesses. This driver configures the power-mode + (corner) for the memory accelerator. config REGULATOR_PROXY_CONSUMER bool "Boot time regulator proxy consumer support" diff --git a/drivers/regulator/cpr3-hmss-regulator.c b/drivers/regulator/cpr3-hmss-regulator.c index 091780525207..77e8bf4b9895 100644 --- a/drivers/regulator/cpr3-hmss-regulator.c +++ b/drivers/regulator/cpr3-hmss-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1232,7 +1232,7 @@ static int cpr3_hmss_kvreg_init(struct cpr3_regulator *vreg) scnprintf(kvreg_name_buf, MAX_VREG_NAME_SIZE, "vdd-thread%d-ldo-supply", id); - if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf , NULL)) + if (!of_find_property(ctrl->dev->of_node, kvreg_name_buf, NULL)) return 0; else if (!of_find_property(node, "qcom,ldo-min-headroom-voltage", NULL)) return 0; @@ -1675,7 +1675,7 @@ static int cpr3_hmss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cpr_regulator_match_table[] = { +static const struct of_device_id cpr_regulator_match_table[] = { { .compatible = "qcom,cpr3-msm8996-v1-hmss-regulator", .data = (void *)(uintptr_t)1 diff --git a/drivers/regulator/cpr3-mmss-regulator.c b/drivers/regulator/cpr3-mmss-regulator.c index 1070a34073e4..41032dd3c15a 100644 --- a/drivers/regulator/cpr3-mmss-regulator.c +++ b/drivers/regulator/cpr3-mmss-regulator.c @@ -1088,7 +1088,7 @@ static int cpr3_mmss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cpr_regulator_match_table[] = { +static const struct of_device_id cpr_regulator_match_table[] = { { .compatible = "qcom,cpr3-msm8996-v1-mmss-regulator", .data = (void *)(uintptr_t)1, diff --git a/drivers/regulator/cpr3-regulator.c b/drivers/regulator/cpr3-regulator.c index 6775152f2623..c51ed182ba96 100644 --- a/drivers/regulator/cpr3-regulator.c +++ b/drivers/regulator/cpr3-regulator.c @@ -1622,8 +1622,6 @@ static void cpr3_regulator_set_target_quot(struct cpr3_thread *thread) } thread->last_closed_loop_aggr_corner = thread->aggr_corner; - - return; } /** @@ -1647,8 +1645,8 @@ static void cpr3_update_vreg_closed_loop_volt(struct cpr3_regulator *vreg, if (vreg->last_closed_loop_corner == CPR3_REGULATOR_CORNER_INVALID) return; - else - corner = &vreg->corner[vreg->last_closed_loop_corner]; + + corner = &vreg->corner[vreg->last_closed_loop_corner]; if (vreg->thread->last_closed_loop_aggr_corner.ro_mask == CPR3_RO_MASK || !vreg->aggregated) { @@ -4195,7 +4193,7 @@ static int cpr3_regulator_update_ctrl_state(struct cpr3_controller *ctrl) * Return: 0 on success, errno on failure */ static int cpr3_regulator_set_voltage(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); struct cpr3_controller *ctrl = vreg->thread->ctrl; @@ -4264,7 +4262,7 @@ static int cpr3_regulator_get_voltage(struct regulator_dev *rdev) * Return: voltage corner value offset by CPR3_CORNER_OFFSET */ static int cpr3_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct cpr3_regulator *vreg = rdev_get_drvdata(rdev); @@ -4964,11 +4962,11 @@ static struct dentry *debugfs_create_int(const char *name, umode_t mode, struct dentry *parent, int *value) { /* if there are no write bits set, make read only */ - if (!(mode & S_IWUGO)) + if (!(mode & 0222)) return debugfs_create_file(name, mode, parent, value, &fops_int_ro); /* if there are no read bits set, make write only */ - if (!(mode & S_IRUGO)) + if (!(mode & 0444)) return debugfs_create_file(name, mode, parent, value, &fops_int_wo); @@ -5225,21 +5223,21 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, struct cpr3_debug_corner_info *info; struct dentry *temp; - temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "floor_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, floor_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "floor_volt debugfs file creation failed\n"); return; } - temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "ceiling_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, ceiling_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ceiling_volt debugfs file creation failed\n"); return; } - temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "open_loop_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, open_loop_volt)); if (IS_ERR_OR_NULL(temp)) { @@ -5247,7 +5245,7 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, return; } - temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", S_IRUGO, + temp = cpr3_debugfs_create_corner_int(vreg, "last_volt", 0444, corner_dir, index, offsetof(struct cpr3_corner, last_volt)); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "last_volt debugfs file creation failed\n"); @@ -5262,8 +5260,8 @@ static void cpr3_regulator_debugfs_corner_add(struct cpr3_regulator *vreg, info->index = index; info->corner = vreg->corner; - temp = debugfs_create_file("target_quots", S_IRUGO, corner_dir, - info, &cpr3_debug_quot_fops); + temp = debugfs_create_file("target_quots", 0444, corner_dir, info, + &cpr3_debug_quot_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "target_quots debugfs file creation failed\n"); return; @@ -5361,21 +5359,21 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_int("speed_bin_fuse", S_IRUGO, vreg_dir, + temp = debugfs_create_int("speed_bin_fuse", 0444, vreg_dir, &vreg->speed_bin_fuse); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "speed_bin_fuse debugfs file creation failed\n"); return; } - temp = debugfs_create_int("cpr_rev_fuse", S_IRUGO, vreg_dir, + temp = debugfs_create_int("cpr_rev_fuse", 0444, vreg_dir, &vreg->cpr_rev_fuse); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "cpr_rev_fuse debugfs file creation failed\n"); return; } - temp = debugfs_create_int("fuse_combo", S_IRUGO, vreg_dir, + temp = debugfs_create_int("fuse_combo", 0444, vreg_dir, &vreg->fuse_combo); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "fuse_combo debugfs file creation failed\n"); @@ -5383,15 +5381,15 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, } if (vreg->ldo_regulator) { - temp = debugfs_create_file("ldo_mode", S_IRUGO, vreg_dir, - vreg, &cpr3_debug_ldo_mode_fops); + temp = debugfs_create_file("ldo_mode", 0444, vreg_dir, vreg, + &cpr3_debug_ldo_mode_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ldo_mode debugfs file creation failed\n"); return; } temp = debugfs_create_file("ldo_mode_allowed", - S_IRUGO | S_IWUSR, vreg_dir, vreg, + 0644, vreg_dir, vreg, &cpr3_debug_ldo_mode_allowed_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "ldo_mode_allowed debugfs file creation failed\n"); @@ -5399,7 +5397,7 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, } } - temp = debugfs_create_int("corner_count", S_IRUGO, vreg_dir, + temp = debugfs_create_int("corner_count", 0444, vreg_dir, &vreg->corner_count); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "corner_count debugfs file creation failed\n"); @@ -5412,8 +5410,8 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_file("index", S_IRUGO | S_IWUSR, corner_dir, - vreg, &cpr3_debug_corner_index_fops); + temp = debugfs_create_file("index", 0644, corner_dir, vreg, + &cpr3_debug_corner_index_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "index debugfs file creation failed\n"); return; @@ -5428,8 +5426,8 @@ static void cpr3_regulator_debugfs_vreg_add(struct cpr3_regulator *vreg, return; } - temp = debugfs_create_file("index", S_IRUGO, corner_dir, - vreg, &cpr3_debug_current_corner_index_fops); + temp = debugfs_create_file("index", 0444, corner_dir, vreg, + &cpr3_debug_current_corner_index_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(vreg, "index debugfs file creation failed\n"); return; @@ -5470,7 +5468,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("floor_volt", 0444, aggr_dir, &thread->aggr_corner.floor_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr floor_volt debugfs file creation failed\n", @@ -5478,7 +5476,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir, &thread->aggr_corner.ceiling_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr ceiling_volt debugfs file creation failed\n", @@ -5486,7 +5484,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir, &thread->aggr_corner.open_loop_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr open_loop_volt debugfs file creation failed\n", @@ -5494,7 +5492,7 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) return; } - temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("last_volt", 0444, aggr_dir, &thread->aggr_corner.last_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u aggr last_volt debugfs file creation failed\n", @@ -5511,8 +5509,8 @@ static void cpr3_regulator_debugfs_thread_add(struct cpr3_thread *thread) info->index = index; info->corner = &thread->aggr_corner; - temp = debugfs_create_file("target_quots", S_IRUGO, aggr_dir, - info, &cpr3_debug_quot_fops); + temp = debugfs_create_file("target_quots", 0444, aggr_dir, info, + &cpr3_debug_quot_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread %u target_quots debugfs file creation failed\n", thread->thread_id); @@ -5869,7 +5867,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) return; } - temp = debugfs_create_file("cpr_closed_loop_enable", S_IRUGO | S_IWUSR, + temp = debugfs_create_file("cpr_closed_loop_enable", 0644, ctrl->debugfs, ctrl, &cpr3_debug_closed_loop_enable_fops); if (IS_ERR_OR_NULL(temp)) { @@ -5878,8 +5876,8 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } if (ctrl->supports_hw_closed_loop) { - temp = debugfs_create_file("use_hw_closed_loop", - S_IRUGO | S_IWUSR, ctrl->debugfs, ctrl, + temp = debugfs_create_file("use_hw_closed_loop", 0644, + ctrl->debugfs, ctrl, &cpr3_debug_hw_closed_loop_enable_fops); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "use_hw_closed_loop debugfs file creation failed\n"); @@ -5887,7 +5885,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } } - temp = debugfs_create_int("thread_count", S_IRUGO, ctrl->debugfs, + temp = debugfs_create_int("thread_count", 0444, ctrl->debugfs, &ctrl->thread_count); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "thread_count debugfs file creation failed\n"); @@ -5895,7 +5893,7 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) } if (ctrl->apm) { - temp = debugfs_create_int("apm_threshold_volt", S_IRUGO, + temp = debugfs_create_int("apm_threshold_volt", 0444, ctrl->debugfs, &ctrl->apm_threshold_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "apm_threshold_volt debugfs file creation failed\n"); @@ -5905,28 +5903,28 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) if (ctrl->aging_required || ctrl->aging_succeeded || ctrl->aging_failed) { - temp = debugfs_create_int("aging_adj_volt", S_IRUGO, + temp = debugfs_create_int("aging_adj_volt", 0444, ctrl->debugfs, &ctrl->aging_ref_adjust_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_adj_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_succeeded", S_IRUGO, + temp = debugfs_create_file("aging_succeeded", 0444, ctrl->debugfs, &ctrl->aging_succeeded, &fops_bool_ro); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_succeeded debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_failed", S_IRUGO, + temp = debugfs_create_file("aging_failed", 0444, ctrl->debugfs, &ctrl->aging_failed, &fops_bool_ro); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aging_failed debugfs file creation failed\n"); return; } - temp = debugfs_create_file("aging_trigger", S_IWUSR, + temp = debugfs_create_file("aging_trigger", 0200, ctrl->debugfs, ctrl, &cpr3_debug_trigger_aging_measurement_fops); if (IS_ERR_OR_NULL(temp)) { @@ -5941,28 +5939,28 @@ static void cpr3_regulator_debugfs_ctrl_add(struct cpr3_controller *ctrl) return; } - temp = debugfs_create_int("floor_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("floor_volt", 0444, aggr_dir, &ctrl->aggr_corner.floor_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr floor_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("ceiling_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("ceiling_volt", 0444, aggr_dir, &ctrl->aggr_corner.ceiling_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr ceiling_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("open_loop_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("open_loop_volt", 0444, aggr_dir, &ctrl->aggr_corner.open_loop_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr open_loop_volt debugfs file creation failed\n"); return; } - temp = debugfs_create_int("last_volt", S_IRUGO, aggr_dir, + temp = debugfs_create_int("last_volt", 0444, aggr_dir, &ctrl->aggr_corner.last_volt); if (IS_ERR_OR_NULL(temp)) { cpr3_err(ctrl, "aggr last_volt debugfs file creation failed\n"); diff --git a/drivers/regulator/cpr3-regulator.h b/drivers/regulator/cpr3-regulator.h index f0230b8ae2e5..7dae23ca0e70 100644 --- a/drivers/regulator/cpr3-regulator.h +++ b/drivers/regulator/cpr3-regulator.h @@ -36,9 +36,9 @@ struct cpr3_thread; * from 0 to 63. bit_start must be less than or equal to bit_end. */ struct cpr3_fuse_param { - unsigned row; - unsigned bit_start; - unsigned bit_end; + unsigned int row; + unsigned int bit_start; + unsigned int bit_end; }; /* Each CPR3 sensor has 16 ring oscillators */ @@ -1021,7 +1021,6 @@ static inline int cpr3_limit_open_loop_voltages(struct cpr3_regulator *vreg) static inline void cpr3_open_loop_voltage_as_ceiling( struct cpr3_regulator *vreg) { - return; } static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) @@ -1031,7 +1030,6 @@ static inline int cpr3_limit_floor_voltages(struct cpr3_regulator *vreg) static inline void cpr3_print_quots(struct cpr3_regulator *vreg) { - return; } static inline int cpr3_adjust_fused_open_loop_voltages( diff --git a/drivers/regulator/cpr4-apss-regulator.c b/drivers/regulator/cpr4-apss-regulator.c index 737511e250f1..cfc09ba9f8da 100644 --- a/drivers/regulator/cpr4-apss-regulator.c +++ b/drivers/regulator/cpr4-apss-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1402,7 +1402,7 @@ static int cpr4_apss_regulator_remove(struct platform_device *pdev) return cpr3_regulator_unregister(ctrl); } -static struct of_device_id cpr4_regulator_match_table[] = { +static const struct of_device_id cpr4_regulator_match_table[] = { { .compatible = "qcom,cpr4-msm8953-apss-regulator", }, {} }; diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c index 0472ce13197b..f21800e00d80 100644 --- a/drivers/regulator/cprh-kbss-regulator.c +++ b/drivers/regulator/cprh-kbss-regulator.c @@ -2007,7 +2007,7 @@ static int cprh_kbss_regulator_resume(struct platform_device *pdev) } /* Data corresponds to the SoC revision */ -static struct of_device_id cprh_regulator_match_table[] = { +static const struct of_device_id cprh_regulator_match_table[] = { { .compatible = "qcom,cprh-msm8998-v1-kbss-regulator", .data = (void *)(uintptr_t)MSM8998_V1_SOC_ID, diff --git a/drivers/regulator/kryo-regulator.c b/drivers/regulator/kryo-regulator.c index cf7830469db5..fd853e7323bb 100644 --- a/drivers/regulator/kryo-regulator.c +++ b/drivers/regulator/kryo-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -333,7 +333,7 @@ static int kryo_regulator_is_enabled(struct regulator_dev *rdev) } static int kryo_regulator_set_voltage(struct regulator_dev *rdev, - int min_volt, int max_volt, unsigned *selector) + int min_volt, int max_volt, unsigned int *selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); int rc; @@ -400,7 +400,7 @@ static int kryo_regulator_get_bypass(struct regulator_dev *rdev, } static int kryo_regulator_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); @@ -411,7 +411,7 @@ static int kryo_regulator_list_voltage(struct regulator_dev *rdev, } static int kryo_regulator_retention_set_voltage(struct regulator_dev *rdev, - int min_volt, int max_volt, unsigned *selector) + int min_volt, int max_volt, unsigned int *selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); int rc; @@ -499,7 +499,7 @@ static int kryo_regulator_retention_get_bypass(struct regulator_dev *rdev, } static int kryo_regulator_retention_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct kryo_regulator *kvreg = rdev_get_drvdata(rdev); @@ -624,7 +624,7 @@ static void kryo_debugfs_init(struct kryo_regulator *kvreg) return; } - temp = debugfs_create_file("mode", S_IRUGO, kvreg->debugfs, + temp = debugfs_create_file("mode", 0444, kvreg->debugfs, kvreg, &kryo_dbg_mode_fops); if (IS_ERR_OR_NULL(temp)) { @@ -989,10 +989,8 @@ static int kryo_regulator_probe(struct platform_device *pdev) init_data->constraints.input_uV = init_data->constraints.max_uV; kvreg = devm_kzalloc(dev, sizeof(*kvreg), GFP_KERNEL); - if (!kvreg) { - dev_err(dev, "memory allocation failed\n"); + if (!kvreg) return -ENOMEM; - } rc = kryo_regulator_init_data(pdev, kvreg); if (rc) { @@ -1073,7 +1071,7 @@ static int kryo_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id kryo_regulator_match_table[] = { +static const struct of_device_id kryo_regulator_match_table[] = { { .compatible = "qcom,kryo-regulator", }, {} }; diff --git a/drivers/regulator/mem-acc-regulator.c b/drivers/regulator/mem-acc-regulator.c index c693969b19b6..4c03decda95a 100644 --- a/drivers/regulator/mem-acc-regulator.c +++ b/drivers/regulator/mem-acc-regulator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -269,7 +269,7 @@ static void update_acc_reg(struct mem_acc_regulator *mem_acc_vreg, int corner) } static int mem_acc_regulator_set_voltage(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct mem_acc_regulator *mem_acc_vreg = rdev_get_drvdata(rdev); int i; @@ -333,10 +333,8 @@ static int __mem_acc_sel_init(struct mem_acc_regulator *mem_acc_vreg, mem_acc_vreg->acc_sel_mask[mem_type] = devm_kzalloc(mem_acc_vreg->dev, mem_acc_vreg->num_acc_sel[mem_type] * sizeof(u32), GFP_KERNEL); - if (!mem_acc_vreg->acc_sel_mask[mem_type]) { - pr_err("Unable to allocate memory for mem_type=%d\n", mem_type); + if (!mem_acc_vreg->acc_sel_mask[mem_type]) return -ENOMEM; - } for (i = 0; i < mem_acc_vreg->num_acc_sel[mem_type]; i++) { bit = mem_acc_vreg->acc_sel_bit_pos[mem_type][i]; @@ -355,8 +353,8 @@ static int mem_acc_sel_init(struct mem_acc_regulator *mem_acc_vreg) if (mem_acc_vreg->mem_acc_supported[i]) { rc = __mem_acc_sel_init(mem_acc_vreg, i); if (rc) { - pr_err("Unable to intialize mem_type=%d rc=%d\n", - i, rc); + pr_err("Unable to initialize mem_type=%d rc=%d\n", + i, rc); return rc; } } @@ -523,15 +521,15 @@ static int mem_acc_custom_data_init(struct platform_device *pdev, if (!res || !res->start) { pr_debug("%s resource missing\n", custom_apc_addr_str); return -EINVAL; - } else { - len = res->end - res->start + 1; - mem_acc_vreg->acc_custom_addr[mem_type] = - devm_ioremap(mem_acc_vreg->dev, res->start, len); - if (!mem_acc_vreg->acc_custom_addr[mem_type]) { - pr_err("Unable to map %s %pa\n", custom_apc_addr_str, - &res->start); - return -EINVAL; - } + } + + len = res->end - res->start + 1; + mem_acc_vreg->acc_custom_addr[mem_type] = + devm_ioremap(mem_acc_vreg->dev, res->start, len); + if (!mem_acc_vreg->acc_custom_addr[mem_type]) { + pr_err("Unable to map %s %pa\n", + custom_apc_addr_str, &res->start); + return -EINVAL; } rc = populate_acc_data(mem_acc_vreg, custom_apc_data_str, @@ -1190,7 +1188,7 @@ static int mem_acc_init(struct platform_device *pdev, rc = mem_acc_sel_init(mem_acc_vreg); if (rc) { - pr_err("Unable to intialize mem_acc_sel reg rc=%d\n", rc); + pr_err("Unable to initialize mem_acc_sel reg rc=%d\n", rc); return rc; } @@ -1307,19 +1305,16 @@ static int mem_acc_regulator_probe(struct platform_device *pdev) if (!init_data) { pr_err("regulator init data is missing\n"); return -EINVAL; - } else { - init_data->constraints.input_uV - = init_data->constraints.max_uV; - init_data->constraints.valid_ops_mask - |= REGULATOR_CHANGE_VOLTAGE; } + init_data->constraints.input_uV = init_data->constraints.max_uV; + init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; + mem_acc_vreg = devm_kzalloc(&pdev->dev, sizeof(*mem_acc_vreg), GFP_KERNEL); - if (!mem_acc_vreg) { - pr_err("Can't allocate mem_acc_vreg memory\n"); + if (!mem_acc_vreg) return -ENOMEM; - } + mem_acc_vreg->dev = &pdev->dev; rc = mem_acc_init(pdev, mem_acc_vreg); @@ -1361,7 +1356,7 @@ static int mem_acc_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id mem_acc_regulator_match_table[] = { +static const struct of_device_id mem_acc_regulator_match_table[] = { { .compatible = "qcom,mem-acc-regulator", }, {} }; diff --git a/drivers/regulator/msm_gfx_ldo.c b/drivers/regulator/msm_gfx_ldo.c index 265ca9ed5258..2800607b5b31 100644 --- a/drivers/regulator/msm_gfx_ldo.c +++ b/drivers/regulator/msm_gfx_ldo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -42,7 +42,7 @@ #define LDO_VREF_SET_REG 0x18 #define UPDATE_VREF_BIT BIT(31) #define SEL_RST_BIT BIT(16) -#define VREF_VAL_MASK GENMASK(6 , 0) +#define VREF_VAL_MASK GENMASK(6, 0) #define PWRSWITCH_CTRL_REG 0x1C #define LDO_CLAMP_IO_BIT BIT(31) @@ -95,9 +95,9 @@ enum voltage_handling { }; struct fuse_param { - unsigned row; - unsigned bit_start; - unsigned bit_end; + unsigned int row; + unsigned int bit_start; + unsigned int bit_end; }; struct ldo_config { @@ -665,7 +665,7 @@ static int switch_mode_to_bhs(struct msm_gfx_ldo *ldo_vreg) } static int msm_gfx_ldo_set_corner(struct regulator_dev *rdev, - int corner, int corner_max, unsigned *selector) + int corner, int corner_max, unsigned int *selector) { struct msm_gfx_ldo *ldo_vreg = rdev_get_drvdata(rdev); int rc = 0, mem_acc_corner, new_uv; @@ -860,7 +860,7 @@ fail: } static int msm_gfx_ldo_set_voltage(struct regulator_dev *rdev, - int new_uv, int max_uv, unsigned *selector) + int new_uv, int max_uv, unsigned int *selector) { struct msm_gfx_ldo *ldo_vreg = rdev_get_drvdata(rdev); int rc = 0; @@ -1444,22 +1444,22 @@ static void msm_gfx_ldo_debugfs_init(struct msm_gfx_ldo *ldo_vreg) return; } - temp = debugfs_create_file("debug_info", S_IRUGO, ldo_vreg->debugfs, + temp = debugfs_create_file("debug_info", 0444, ldo_vreg->debugfs, ldo_vreg, &msm_gfx_ldo_debug_info_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("debug_info node creation failed\n"); return; } - temp = debugfs_create_file("ldo_voltage", S_IRUGO | S_IWUSR, - ldo_vreg->debugfs, ldo_vreg, &ldo_voltage_fops); + temp = debugfs_create_file("ldo_voltage", 0644, ldo_vreg->debugfs, + ldo_vreg, &ldo_voltage_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("ldo_voltage node creation failed\n"); return; } - temp = debugfs_create_file("ldo_mode_disable", S_IRUGO | S_IWUSR, - ldo_vreg->debugfs, ldo_vreg, &ldo_mode_disable_fops); + temp = debugfs_create_file("ldo_mode_disable", 0644, ldo_vreg->debugfs, + ldo_vreg, &ldo_mode_disable_fops); if (IS_ERR_OR_NULL(temp)) { pr_err("ldo_mode_disable node creation failed\n"); return; diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index 40c62c355188..cf8f00085a0c 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -2365,7 +2365,7 @@ static int qpnp_lab_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lab_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc, new_uV; u8 val; @@ -3282,7 +3282,7 @@ static int qpnp_ibb_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_ibb_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; @@ -3648,12 +3648,10 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) u8 type, revision; int rc = 0; - labibb = devm_kzalloc(&pdev->dev, - sizeof(struct qpnp_labibb), GFP_KERNEL); - if (labibb == NULL) { - pr_err("labibb allocation failed.\n"); + labibb = devm_kzalloc(&pdev->dev, sizeof(*labibb), GFP_KERNEL); + if (labibb == NULL) return -ENOMEM; - } + labibb->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!labibb->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); @@ -3849,7 +3847,7 @@ static int qpnp_labibb_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_LABIBB_REGULATOR_DRIVER_NAME, }, { }, }; diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c index daa4e8e74d5b..a08ade61e057 100644 --- a/drivers/regulator/qpnp-lcdb-regulator.c +++ b/drivers/regulator/qpnp-lcdb-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -863,7 +863,7 @@ static int qpnp_lcdb_ldo_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev); @@ -934,7 +934,7 @@ static int qpnp_lcdb_ncp_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { int rc = 0; struct qpnp_lcdb *lcdb = rdev_get_drvdata(rdev); diff --git a/drivers/regulator/qpnp-oledb-regulator.c b/drivers/regulator/qpnp-oledb-regulator.c index 587538cca474..8d017fb55a3f 100644 --- a/drivers/regulator/qpnp-oledb-regulator.c +++ b/drivers/regulator/qpnp-oledb-regulator.c @@ -327,7 +327,7 @@ static int qpnp_oledb_regulator_is_enabled(struct regulator_dev *rdev) } static int qpnp_oledb_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { u8 val; int rc = 0; diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c index 17865857df03..bd706658348d 100644 --- a/drivers/regulator/qpnp-regulator.c +++ b/drivers/regulator/qpnp-regulator.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -45,7 +45,7 @@ enum { static int qpnp_vreg_debug_mask; module_param_named( - debug_mask, qpnp_vreg_debug_mask, int, S_IRUSR | S_IWUSR + debug_mask, qpnp_vreg_debug_mask, int, 0600 ); #define vreg_err(vreg, fmt, ...) \ @@ -302,7 +302,7 @@ struct qpnp_voltage_range { int step_uV; int set_point_min_uV; int set_point_max_uV; - unsigned n_voltages; + unsigned int n_voltages; u8 range_sel; }; @@ -313,7 +313,7 @@ struct qpnp_voltage_range { struct qpnp_voltage_set_points { struct qpnp_voltage_range *range; int count; - unsigned n_voltages; + unsigned int n_voltages; }; struct qpnp_regulator_mapping { @@ -381,7 +381,7 @@ struct qpnp_regulator { { \ .range = _ranges, \ .count = ARRAY_SIZE(_ranges), \ -}; +} /* * These tables contain the physically available PMIC regulator voltage setpoint @@ -730,7 +730,7 @@ static int qpnp_regulator_common_disable(struct regulator_dev *rdev) */ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, int min_uV, int max_uV, int *range_sel, int *voltage_sel, - unsigned *selector) + unsigned int *selector) { struct qpnp_voltage_range *range = NULL; int uV = min_uV; @@ -781,9 +781,9 @@ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, (uV - vreg->set_points->range[i].set_point_min_uV) / vreg->set_points->range[i].step_uV; break; - } else { - *selector += vreg->set_points->range[i].n_voltages; } + + *selector += vreg->set_points->range[i].n_voltages; } if (*selector >= vreg->set_points->n_voltages) @@ -794,7 +794,7 @@ static int qpnp_regulator_select_voltage_same_range(struct qpnp_regulator *vreg, static int qpnp_regulator_select_voltage(struct qpnp_regulator *vreg, int min_uV, int max_uV, int *range_sel, int *voltage_sel, - unsigned *selector) + unsigned int *selector) { struct qpnp_voltage_range *range; int uV = min_uV; @@ -872,7 +872,7 @@ static int qpnp_regulator_delay_for_slewing(struct qpnp_regulator *vreg, } static int qpnp_regulator_common_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel, voltage_old = 0; @@ -958,7 +958,7 @@ static int qpnp_regulator_common_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_single_range_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel; @@ -995,7 +995,7 @@ static int qpnp_regulator_single_range_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_ult_lo_smps_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel; @@ -1065,7 +1065,7 @@ static int qpnp_regulator_ult_lo_smps_get_voltage(struct regulator_dev *rdev) } static int qpnp_regulator_common_list_voltage(struct regulator_dev *rdev, - unsigned selector) + unsigned int selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int uV = 0; @@ -1079,16 +1079,16 @@ static int qpnp_regulator_common_list_voltage(struct regulator_dev *rdev, uV = selector * vreg->set_points->range[i].step_uV + vreg->set_points->range[i].set_point_min_uV; break; - } else { - selector -= vreg->set_points->range[i].n_voltages; } + + selector -= vreg->set_points->range[i].n_voltages; } return uV; } static int qpnp_regulator_common2_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct qpnp_regulator *vreg = rdev_get_drvdata(rdev); int rc, range_sel, voltage_sel, voltage_old = 0; @@ -1280,8 +1280,6 @@ static void qpnp_regulator_vs_ocp_work(struct work_struct *work) = container_of(dwork, struct qpnp_regulator, ocp_work); qpnp_regulator_vs_clear_ocp(vreg); - - return; } static irqreturn_t qpnp_regulator_vs_ocp_isr(int irq, void *data) @@ -1418,8 +1416,7 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev, pc_mode_label[5] = mode_reg & QPNP_COMMON_MODE_FOLLOW_HW_EN0_MASK ? '0' : '_'; - pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, " - "alt_mode=%s\n", + pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, alt_mode=%s\n", action_label, vreg->rdesc.name, enable_label, uV, mode_label, pc_enable_label, pc_mode_label); break; @@ -1440,8 +1437,7 @@ static void qpnp_vreg_show_state(struct regulator_dev *rdev, pc_mode_label[6] = mode_reg & QPNP_COMMON_MODE_FOLLOW_HW_EN0_MASK ? '0' : '_'; - pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, " - "alt_mode=%s\n", + pr_info("%s %-11s: %s, v=%7d uV, mode=%s, pc_en=%s, alt_mode=%s\n", action_label, vreg->rdesc.name, enable_label, uV, mode_label, pc_enable_label, pc_mode_label); break; @@ -2165,7 +2161,7 @@ static int qpnp_regulator_get_dt_config(struct platform_device *pdev, return rc; } -static struct of_device_id spmi_match_table[]; +static const struct of_device_id spmi_match_table[]; #define MAX_NAME_LEN 127 @@ -2256,8 +2252,6 @@ static int qpnp_regulator_probe(struct platform_device *pdev) reg_name = kzalloc(strnlen(pdata->init_data.constraints.name, MAX_NAME_LEN) + 1, GFP_KERNEL); if (!reg_name) { - dev_err(&pdev->dev, "%s: Can't allocate regulator name\n", - __func__); kfree(vreg); return -ENOMEM; } @@ -2362,7 +2356,7 @@ static int qpnp_regulator_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = QPNP_REGULATOR_DRIVER_NAME, }, {} }; @@ -2422,8 +2416,7 @@ int __init qpnp_regulator_init(void) if (has_registered) return 0; - else - has_registered = true; + has_registered = true; qpnp_regulator_set_point_init(); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index ef3ff5e16e86..50ca3c33f942 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1592,13 +1592,13 @@ config RTC_DRV_MOXART will be called rtc-moxart config RTC_DRV_QPNP - tristate "Qualcomm QPNP PMIC RTC" - depends on SPMI && OF_SPMI && MSM_QPNP_INT + tristate "Qualcomm Technologies, Inc. QPNP PMIC RTC" + depends on SPMI help - Say Y here if you want to support the Qualcomm QPNP PMIC RTC. - - To compile this driver as a module, choose M here: the - module will be called qpnp-rtc. + This enables support for the RTC found on Qualcomm Technologies, Inc. + QPNP PMIC chips. This driver supports using the PMIC RTC peripheral + to wake a mobile device up from suspend or to wake it up from power- + off. config RTC_DRV_MT6397 tristate "Mediatek Real Time Clock driver" @@ -1610,15 +1610,6 @@ config RTC_DRV_MT6397 If you want to use Mediatek(R) RTC interface, select Y or M here. -config RTC_DRV_QPNP - tristate "Qualcomm QPNP PMIC RTC" - depends on SPMI - help - Say Y here if you want to support the Qualcomm QPNP PMIC RTC. - - To compile this driver as a module, choose M here: the - module will be called qpnp-rtc. - config RTC_DRV_XGENE tristate "APM X-Gene RTC" depends on HAS_IOMEM diff --git a/drivers/rtc/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c index 1b74b94796ba..a2c004e0f7fd 100644 --- a/drivers/rtc/qpnp-rtc.c +++ b/drivers/rtc/qpnp-rtc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -50,9 +50,9 @@ /* Module parameter to control power-on-alarm */ bool poweron_alarm; +EXPORT_SYMBOL(poweron_alarm); module_param(poweron_alarm, bool, 0644); MODULE_PARM_DESC(poweron_alarm, "Enable/Disable power-on alarm"); -EXPORT_SYMBOL(poweron_alarm); /* rtc driver internal structure */ struct qpnp_rtc { @@ -138,7 +138,7 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) * | BYTE[3] | BYTE[2] | BYTE[1] | BYTE[0] | * ---------------------------------------------- * - * RTC has four 8 bit registers for writting time in seconds: + * RTC has four 8 bit registers for writing time in seconds: * WDATA[3], WDATA[2], WDATA[1], WDATA[0] * * Write to the RTC registers should be done in following order @@ -149,7 +149,7 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) * * Write BYTE[0] of time to RTC WDATA[0] register * - * Clearing BYTE[0] and writting in the end will prevent any + * Clearing BYTE[0] and writing in the end will prevent any * unintentional overflow from WDATA[0] to higher bytes during the * write operation */ @@ -162,9 +162,8 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) rc = qpnp_write_wrapper(rtc_dd, &rtc_ctrl_reg, rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1); if (rc) { - dev_err(dev, - "Disabling of RTC control reg failed" - " with error:%d\n", rc); + dev_err(dev, "Disabling of RTC control reg failed with error:%d\n", + rc); goto rtc_rw_fail; } rtc_dd->rtc_ctrl_reg = rtc_ctrl_reg; @@ -201,9 +200,8 @@ qpnp_rtc_set_time(struct device *dev, struct rtc_time *tm) rc = qpnp_write_wrapper(rtc_dd, &rtc_ctrl_reg, rtc_dd->rtc_base + REG_OFFSET_RTC_CTRL, 1); if (rc) { - dev_err(dev, - "Enabling of RTC control reg failed" - " with error:%d\n", rc); + dev_err(dev, "Enabling of RTC control reg failed with error:%d\n", + rc); goto rtc_rw_fail; } rtc_dd->rtc_ctrl_reg = rtc_ctrl_reg; @@ -417,11 +415,19 @@ rtc_rw_fail: return rc; } -static struct rtc_class_ops qpnp_rtc_ops = { +static const struct rtc_class_ops qpnp_rtc_ro_ops = { + .read_time = qpnp_rtc_read_time, + .set_alarm = qpnp_rtc_set_alarm, + .read_alarm = qpnp_rtc_read_alarm, + .alarm_irq_enable = qpnp_rtc_alarm_irq_enable, +}; + +static const struct rtc_class_ops qpnp_rtc_rw_ops = { .read_time = qpnp_rtc_read_time, .set_alarm = qpnp_rtc_set_alarm, .read_alarm = qpnp_rtc_read_alarm, .alarm_irq_enable = qpnp_rtc_alarm_irq_enable, + .set_time = qpnp_rtc_set_time, }; static irqreturn_t qpnp_alarm_trigger(int irq, void *dev_id) @@ -465,6 +471,7 @@ rtc_alarm_handled: static int qpnp_rtc_probe(struct platform_device *pdev) { + const struct rtc_class_ops *rtc_ops = &qpnp_rtc_ro_ops; int rc; u8 subtype; struct qpnp_rtc *rtc_dd; @@ -578,13 +585,13 @@ static int qpnp_rtc_probe(struct platform_device *pdev) } if (rtc_dd->rtc_write_enable == true) - qpnp_rtc_ops.set_time = qpnp_rtc_set_time; + rtc_ops = &qpnp_rtc_rw_ops; dev_set_drvdata(&pdev->dev, rtc_dd); /* Register the RTC device */ rtc_dd->rtc = rtc_device_register("qpnp_rtc", &pdev->dev, - &qpnp_rtc_ops, THIS_MODULE); + rtc_ops, THIS_MODULE); if (IS_ERR(rtc_dd->rtc)) { dev_err(&pdev->dev, "%s: RTC registration failed (%ld)\n", __func__, PTR_ERR(rtc_dd->rtc)); @@ -676,7 +683,7 @@ fail_alarm_disable: } } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-rtc", }, @@ -707,4 +714,4 @@ static void __exit qpnp_rtc_exit(void) module_exit(qpnp_rtc_exit); MODULE_DESCRIPTION("SMPI PMIC RTC driver"); -MODULE_LICENSE("GPL V2"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 4a315d8f5534..1e5970b31404 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -37,12 +37,14 @@ config MSM_SMEM inter-processor communication. config QPNP_HAPTIC - tristate "Haptic support for QPNP PMIC" + tristate "Haptic support for QPNP PMIC" depends on ARCH_QCOM - help - This option enables device driver support for the Haptic - on the Qualcomm Technologies' QPNP PMICs. It uses the android - timed-output framework. + help + This option enables device driver support for the haptic peripheral + found on Qualcomm Technologies, Inc. QPNP PMICs. The haptic + peripheral is capable of driving both LRA and ERM vibrators. This + module provides haptic feedback for user actions such as a long press + on the touch screen. It uses the Android timed-output framework. config MSM_SMD depends on MSM_SMEM diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c index f2d2aece6846..14cf10b92122 100644 --- a/drivers/soc/qcom/glink_smem_native_xprt.c +++ b/drivers/soc/qcom/glink_smem_native_xprt.c @@ -678,10 +678,15 @@ static void process_rx_data(struct edge_info *einfo, uint16_t cmd_id, } else if (intent->data == NULL) { if (einfo->intentless) { intent->data = kmalloc(cmd.frag_size, GFP_ATOMIC); - if (!intent->data) + if (!intent->data) { err = true; - else + GLINK_ERR( + "%s: atomic alloc fail ch %d liid %d size %d\n", + __func__, rcid, intent_id, + cmd.frag_size); + } else { intent->intent_size = cmd.frag_size; + } } else { GLINK_ERR( "%s: intent for ch %d liid %d has no data buff\n", diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c index 4d94e6446505..5e2dbc8b1d20 100644 --- a/drivers/soc/qcom/glink_ssr.c +++ b/drivers/soc/qcom/glink_ssr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -339,6 +339,7 @@ void close_ch_worker(struct work_struct *work) BUG_ON(!ss_info->cb_data); kfree(ss_info->cb_data); + ss_info->cb_data = NULL; kfree(close_work); } diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 16ee98d8e4e0..7c08c28aeda8 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1724,19 +1724,21 @@ static int icnss_call_driver_probe(struct icnss_priv *priv) out: icnss_hw_power_off(priv); - penv->ops = NULL; return ret; } -static int icnss_call_driver_reinit(struct icnss_priv *priv) +static int icnss_pd_restart_complete(struct icnss_priv *priv) { - int ret = 0; + int ret; + + clear_bit(ICNSS_PD_RESTART, &priv->state); + icnss_pm_relax(priv); if (!priv->ops || !priv->ops->reinit) goto out; if (!test_bit(ICNSS_DRIVER_PROBED, &penv->state)) - goto out; + goto call_probe; icnss_pr_dbg("Calling driver reinit state: 0x%lx\n", priv->state); @@ -1751,18 +1753,14 @@ static int icnss_call_driver_reinit(struct icnss_priv *priv) } out: - clear_bit(ICNSS_PD_RESTART, &priv->state); - - icnss_pm_relax(priv); - return 0; +call_probe: + return icnss_call_driver_probe(priv); + out_power_off: icnss_hw_power_off(priv); - clear_bit(ICNSS_PD_RESTART, &priv->state); - - icnss_pm_relax(priv); return ret; } @@ -1787,7 +1785,7 @@ static int icnss_driver_event_fw_ready_ind(void *data) } if (test_bit(ICNSS_PD_RESTART, &penv->state)) - ret = icnss_call_driver_reinit(penv); + ret = icnss_pd_restart_complete(penv); else ret = icnss_call_driver_probe(penv); diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index eaeb8d4776fe..2244c64d28af 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -171,7 +171,11 @@ int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev) ret = do_elf_ramdump(ramdump_dev, ramdump_segs, count); kfree(ramdump_segs); - if (!ret && desc->subsys_vmid > 0) + if (ret) + pil_err(desc, "%s: Ramdump collection failed for subsys %s rc:%d\n", + __func__, desc->name, ret); + + if (desc->subsys_vmid > 0) ret = pil_assign_mem_to_subsys(desc, priv->region_start, (priv->region_end - priv->region_start)); diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c index 45ac48eb2241..19974b61ec1c 100644 --- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c +++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. +/* Copyright (c) 2016-2017 The Linux Foundation. * All rights reserved. * * This program is free software; you can redistribute it and/or modify @@ -17,7 +17,6 @@ #include <linux/uaccess.h> #include <linux/spinlock.h> #include <linux/mutex.h> -#include <linux/list.h> #include <linux/sched.h> #include <linux/wait.h> #include <linux/errno.h> @@ -34,16 +33,10 @@ #define APR_MAXIMUM_NUM_OF_RETRIES 2 struct apr_tx_buf { - struct list_head list; struct apr_pkt_priv pkt_priv; char buf[APR_MAX_BUF]; }; -struct apr_buf_list { - struct list_head list; - spinlock_t lock; -}; - struct link_state { uint32_t dest; void *handle; @@ -52,7 +45,6 @@ struct link_state { }; static struct link_state link_state[APR_DEST_MAX]; -static struct apr_buf_list buf_list; static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = { { @@ -68,44 +60,37 @@ static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = { static struct apr_svc_ch_dev apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX]; -static struct apr_tx_buf *apr_get_free_buf(int len) +static struct apr_tx_buf *apr_alloc_buf(int len) { - struct apr_tx_buf *tx_buf; - unsigned long flags; if (len > APR_MAX_BUF) { pr_err("%s: buf too large [%d]\n", __func__, len); return ERR_PTR(-EINVAL); } - spin_lock_irqsave(&buf_list.lock, flags); - if (list_empty(&buf_list.list)) { - spin_unlock_irqrestore(&buf_list.lock, flags); - pr_err("%s: No buf available\n", __func__); - return ERR_PTR(-ENOMEM); - } - - tx_buf = list_first_entry(&buf_list.list, struct apr_tx_buf, list); - list_del(&tx_buf->list); - spin_unlock_irqrestore(&buf_list.lock, flags); - - return tx_buf; + return kzalloc(sizeof(struct apr_tx_buf), GFP_ATOMIC); } -static void apr_buf_add_tail(const void *buf) +static void apr_free_buf(const void *ptr) { - struct apr_tx_buf *list; - unsigned long flags; - if (!buf) + struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)ptr; + struct apr_tx_buf *tx_buf; + + if (!apr_pkt_priv) { + pr_err("%s: Invalid apr_pkt_priv\n", __func__); return; + } - spin_lock_irqsave(&buf_list.lock, flags); - list = container_of((void *)buf, struct apr_tx_buf, buf); - list_add_tail(&list->list, &buf_list.list); - spin_unlock_irqrestore(&buf_list.lock, flags); + if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) { + tx_buf = container_of((void *)apr_pkt_priv, + struct apr_tx_buf, pkt_priv); + pr_debug("%s: Freeing buffer %pK", __func__, tx_buf); + kfree(tx_buf); + } } + static int __apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, struct apr_pkt_priv *pkt_priv, int len) { @@ -137,7 +122,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, return -EINVAL; if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) { - tx_buf = apr_get_free_buf(len); + tx_buf = apr_alloc_buf(len); if (IS_ERR_OR_NULL(tx_buf)) { rc = -EINVAL; goto exit; @@ -160,7 +145,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data, if (rc < 0) { pr_err("%s: Unable to send the packet, rc:%d\n", __func__, rc); if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) - apr_buf_add_tail(pkt_data); + kfree(tx_buf); } exit: return rc; @@ -189,39 +174,17 @@ void apr_tal_notify_rx(void *handle, const void *priv, const void *pkt_priv, static void apr_tal_notify_tx_abort(void *handle, const void *priv, const void *pkt_priv) { - struct apr_pkt_priv *apr_pkt_priv_ptr = - (struct apr_pkt_priv *)pkt_priv; - struct apr_tx_buf *list_node; - - if (!apr_pkt_priv_ptr) { - pr_err("%s: Invalid pkt_priv\n", __func__); - return; - } - - pr_debug("%s: tx_abort received for apr_pkt_priv_ptr:%pK\n", - __func__, apr_pkt_priv_ptr); - - if (apr_pkt_priv_ptr->pkt_owner == APR_PKT_OWNER_DRIVER) { - list_node = container_of(apr_pkt_priv_ptr, - struct apr_tx_buf, pkt_priv); - apr_buf_add_tail(list_node->buf); - } + pr_debug("%s: tx_abort received for pkt_priv:%pK\n", + __func__, pkt_priv); + apr_free_buf(pkt_priv); } void apr_tal_notify_tx_done(void *handle, const void *priv, const void *pkt_priv, const void *ptr) { - struct apr_pkt_priv *apr_pkt_priv = (struct apr_pkt_priv *)pkt_priv; - - if (!pkt_priv || !ptr) { - pr_err("%s: Invalid pkt_priv or ptr\n", __func__); - return; - } - - pr_debug("%s: tx_done received\n", __func__); - - if (apr_pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) - apr_buf_add_tail(ptr); + pr_debug("%s: tx_done received for pkt_priv:%pK\n", + __func__, pkt_priv); + apr_free_buf(pkt_priv); } bool apr_tal_notify_rx_intent_req(void *handle, const void *priv, @@ -457,8 +420,6 @@ static struct glink_link_info lpass_link_info = { static int __init apr_tal_init(void) { int i, j, k; - struct apr_tx_buf *buf; - struct list_head *ptr, *next; for (i = 0; i < APR_DL_MAX; i++) { for (j = 0; j < APR_DEST_MAX; j++) { @@ -474,21 +435,6 @@ static int __init apr_tal_init(void) for (i = 0; i < APR_DEST_MAX; i++) init_waitqueue_head(&link_state[i].wait); - spin_lock_init(&buf_list.lock); - INIT_LIST_HEAD(&buf_list.list); - for (i = 0; i < APR_NUM_OF_TX_BUF; i++) { - buf = kzalloc(sizeof(struct apr_tx_buf), GFP_KERNEL); - if (!buf) { - pr_err("%s: Unable to allocate tx buf\n", __func__); - goto tx_buf_alloc_fail; - } - - INIT_LIST_HEAD(&buf->list); - spin_lock(&buf_list.lock); - list_add_tail(&buf->list, &buf_list.list); - spin_unlock(&buf_list.lock); - } - link_state[APR_DEST_MODEM].link_state = GLINK_LINK_STATE_DOWN; link_state[APR_DEST_MODEM].handle = glink_register_link_state_cb(&mpss_link_info, NULL); @@ -502,13 +448,5 @@ static int __init apr_tal_init(void) pr_err("%s: Unable to register lpass link state\n", __func__); return 0; - -tx_buf_alloc_fail: - list_for_each_safe(ptr, next, &buf_list.list) { - buf = list_entry(ptr, struct apr_tx_buf, list); - list_del(&buf->list); - kfree(buf); - } - return -ENOMEM; } device_initcall(apr_tal_init); diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c index 21387568fe53..39070561d7e4 100644 --- a/drivers/soc/qcom/qpnp-haptic.c +++ b/drivers/soc/qcom/qpnp-haptic.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -918,15 +918,16 @@ static ssize_t qpnp_hap_wf_samp_store(struct device *dev, struct timed_output_dev *timed_dev = dev_get_drvdata(dev); struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap, timed_dev); - int data; + int data, rc; if (index < 0 || index >= QPNP_HAP_WAV_SAMP_LEN) { dev_err(dev, "Invalid sample index(%d)\n", index); return -EINVAL; } - if (sscanf(buf, "%x", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 16, &data); + if (rc) + return rc; if (data < 0 || data > 0xff) { dev_err(dev, "Invalid sample wf_%d (%d)\n", index, data); @@ -1032,8 +1033,9 @@ static ssize_t qpnp_hap_wf_rep_store(struct device *dev, int data, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; if (data < QPNP_HAP_WAV_REP_MIN) data = QPNP_HAP_WAV_REP_MIN; @@ -1078,8 +1080,9 @@ static ssize_t qpnp_hap_wf_s_rep_store(struct device *dev, int data, rc, temp; u8 reg; - if (sscanf(buf, "%d", &data) != 1) - return -EINVAL; + rc = kstrtoint(buf, 10, &data); + if (rc) + return rc; if (data < QPNP_HAP_WAV_S_REP_MIN) data = QPNP_HAP_WAV_S_REP_MIN; @@ -1290,51 +1293,25 @@ static ssize_t qpnp_hap_ramp_test_data_show(struct device *dev, /* sysfs attributes */ static struct device_attribute qpnp_hap_attrs[] = { - __ATTR(wf_s0, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s0_show, - qpnp_hap_wf_s0_store), - __ATTR(wf_s1, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s1_show, - qpnp_hap_wf_s1_store), - __ATTR(wf_s2, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s2_show, - qpnp_hap_wf_s2_store), - __ATTR(wf_s3, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s3_show, - qpnp_hap_wf_s3_store), - __ATTR(wf_s4, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s4_show, - qpnp_hap_wf_s4_store), - __ATTR(wf_s5, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s5_show, - qpnp_hap_wf_s5_store), - __ATTR(wf_s6, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s6_show, - qpnp_hap_wf_s6_store), - __ATTR(wf_s7, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s7_show, - qpnp_hap_wf_s7_store), - __ATTR(wf_update, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_update_show, - qpnp_hap_wf_update_store), - __ATTR(wf_rep, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_rep_show, - qpnp_hap_wf_rep_store), - __ATTR(wf_s_rep, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_wf_s_rep_show, - qpnp_hap_wf_s_rep_store), - __ATTR(play_mode, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_play_mode_show, - qpnp_hap_play_mode_store), - __ATTR(dump_regs, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_dump_regs_show, - NULL), - __ATTR(ramp_test, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_ramp_test_data_show, - qpnp_hap_ramp_test_data_store), - __ATTR(min_max_test, (S_IRUGO | S_IWUSR | S_IWGRP), - qpnp_hap_min_max_test_data_show, - qpnp_hap_min_max_test_data_store), + __ATTR(wf_s0, 0664, qpnp_hap_wf_s0_show, qpnp_hap_wf_s0_store), + __ATTR(wf_s1, 0664, qpnp_hap_wf_s1_show, qpnp_hap_wf_s1_store), + __ATTR(wf_s2, 0664, qpnp_hap_wf_s2_show, qpnp_hap_wf_s2_store), + __ATTR(wf_s3, 0664, qpnp_hap_wf_s3_show, qpnp_hap_wf_s3_store), + __ATTR(wf_s4, 0664, qpnp_hap_wf_s4_show, qpnp_hap_wf_s4_store), + __ATTR(wf_s5, 0664, qpnp_hap_wf_s5_show, qpnp_hap_wf_s5_store), + __ATTR(wf_s6, 0664, qpnp_hap_wf_s6_show, qpnp_hap_wf_s6_store), + __ATTR(wf_s7, 0664, qpnp_hap_wf_s7_show, qpnp_hap_wf_s7_store), + __ATTR(wf_update, 0664, qpnp_hap_wf_update_show, + qpnp_hap_wf_update_store), + __ATTR(wf_rep, 0664, qpnp_hap_wf_rep_show, qpnp_hap_wf_rep_store), + __ATTR(wf_s_rep, 0664, qpnp_hap_wf_s_rep_show, qpnp_hap_wf_s_rep_store), + __ATTR(play_mode, 0664, qpnp_hap_play_mode_show, + qpnp_hap_play_mode_store), + __ATTR(dump_regs, 0664, qpnp_hap_dump_regs_show, NULL), + __ATTR(ramp_test, 0664, qpnp_hap_ramp_test_data_show, + qpnp_hap_ramp_test_data_store), + __ATTR(min_max_test, 0664, qpnp_hap_min_max_test_data_show, + qpnp_hap_min_max_test_data_store), }; static void calculate_lra_code(struct qpnp_hap *hap) @@ -1420,13 +1397,13 @@ static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer) if (val & AUTO_RES_ERR_BIT) { schedule_work(&hap->auto_res_err_work); return HRTIMER_NORESTART; - } else { - update_lra_frequency(hap); - currtime = ktime_get(); - hrtimer_forward(&hap->auto_res_err_poll_timer, currtime, - ktime_set(0, POLL_TIME_AUTO_RES_ERR_NS)); - return HRTIMER_RESTART; } + + update_lra_frequency(hap); + currtime = ktime_get(); + hrtimer_forward(&hap->auto_res_err_poll_timer, currtime, + ktime_set(0, POLL_TIME_AUTO_RES_ERR_NS)); + return HRTIMER_RESTART; } static void correct_auto_res_error(struct work_struct *auto_res_err_work) @@ -1595,19 +1572,23 @@ int qpnp_hap_play_byte(u8 data, bool on) return rc; if (!on) { - /* set the pwm back to original duty for normal operations */ - /* this is not required if standard interface is not used */ + /* + * Set the pwm back to original duty for normal operations. + * This is not required if standard interface is not used. + */ rc = pwm_config(hap->pwm_info.pwm_dev, hap->pwm_info.duty_us * NSEC_PER_USEC, hap->pwm_info.period_us * NSEC_PER_USEC); return rc; } - /* pwm values range from 0x00 to 0xff. The range from 0x00 to 0x7f - provides a postive amplitude in the sin wave form for 0 to 100%. - The range from 0x80 to 0xff provides a negative amplitude in the - sin wave form for 0 to 100%. Here the duty percentage is calculated - based on the incoming data to accommodate this. */ + /* + * pwm values range from 0x00 to 0xff. The range from 0x00 to 0x7f + * provides a postive amplitude in the sin wave form for 0 to 100%. + * The range from 0x80 to 0xff provides a negative amplitude in the + * sin wave form for 0 to 100%. Here the duty percentage is calculated + * based on the incoming data to accommodate this. + */ if (data <= QPNP_HAP_EXT_PWM_PEAK_DATA) duty_percent = QPNP_HAP_EXT_PWM_HALF_DUTY + ((data * QPNP_HAP_EXT_PWM_DATA_FACTOR) / 100); @@ -1675,6 +1656,7 @@ static int qpnp_hap_get_time(struct timed_output_dev *dev) if (hrtimer_active(&hap->hap_timer)) { ktime_t r = hrtimer_get_remaining(&hap->hap_timer); + return (int)ktime_to_us(r); } else { return 0; @@ -1709,6 +1691,7 @@ static enum hrtimer_restart qpnp_hap_test_timer(struct hrtimer *timer) static int qpnp_haptic_suspend(struct device *dev) { struct qpnp_hap *hap = dev_get_drvdata(dev); + hrtimer_cancel(&hap->hap_timer); cancel_work_sync(&hap->work); /* turn-off haptic */ @@ -1845,9 +1828,11 @@ static int qpnp_hap_config(struct qpnp_hap *hap) if (rc) return rc; - /* Configure RATE_CFG1 and RATE_CFG2 registers */ - /* Note: For ERM these registers act as play rate and - for LRA these represent resonance period */ + /* + * Configure RATE_CFG1 and RATE_CFG2 registers. + * Note: For ERM these registers act as play rate and + * for LRA these represent resonance period + */ if (hap->wave_play_rate_us < QPNP_HAP_WAV_PLAY_RATE_US_MIN) hap->wave_play_rate_us = QPNP_HAP_WAV_PLAY_RATE_US_MIN; else if (hap->wave_play_rate_us > QPNP_HAP_WAV_PLAY_RATE_US_MAX) @@ -2314,7 +2299,7 @@ static int qpnp_haptic_remove(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_match_table[] = { +static const struct of_device_id spmi_match_table[] = { { .compatible = "qcom,qpnp-haptic", }, { }, }; diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c index 9b71083e4f27..d91daa6a3456 100644 --- a/drivers/soc/qcom/spcom.c +++ b/drivers/soc/qcom/spcom.c @@ -316,6 +316,10 @@ static int spcom_create_predefined_channels_chardev(void) { int i; int ret; + static bool is_predefined_created; + + if (is_predefined_created) + return 0; for (i = 0; i < SPCOM_MAX_CHANNELS; i++) { const char *name = spcom_dev->predefined_ch_name[i]; @@ -330,6 +334,8 @@ static int spcom_create_predefined_channels_chardev(void) } } + is_predefined_created = true; + return 0; } @@ -1633,12 +1639,13 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, pr_err("fail to get ion handle.\n"); return -EINVAL; } + pr_debug("ion handle ok.\n"); /* Check if this ION buffer is already locked */ for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) { if (ch->ion_handle_table[i] == ion_handle) { - pr_debug("fd [%d] ion buf is already locked.\n", fd); + pr_err("fd [%d] ion buf is already locked.\n", fd); /* decrement back the ref count */ ion_free(spcom_dev->ion_client, ion_handle); return -EINVAL; @@ -1650,11 +1657,14 @@ static int spcom_handle_lock_ion_buf_command(struct spcom_channel *ch, if (ch->ion_handle_table[i] == NULL) { ch->ion_handle_table[i] = ion_handle; ch->ion_fd_table[i] = fd; - pr_debug("locked ion buf#[%d], fd [%d].\n", i, fd); + pr_debug("ch [%s] locked ion buf #%d, fd [%d].\n", + ch->name, i, fd); return 0; } } + pr_err("fd [%d] ion buf not found.\n", fd); + return -EFAULT; } @@ -1684,20 +1694,22 @@ static int spcom_unlock_ion_buf(struct spcom_channel *ch, int fd) /* unlock all ION buf */ for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) { if (ch->ion_handle_table[i] != NULL) { + pr_debug("unlocked ion buf #%d fd [%d].\n", + i, ch->ion_fd_table[i]); ion_free(ion_client, ch->ion_handle_table[i]); ch->ion_handle_table[i] = NULL; ch->ion_fd_table[i] = -1; - pr_debug("unlocked ion buf#[%d].\n", i); } } } else { /* unlock specific ION buf */ for (i = 0 ; i < ARRAY_SIZE(ch->ion_handle_table) ; i++) { if (ch->ion_fd_table[i] == fd) { + pr_debug("unlocked ion buf #%d fd [%d].\n", + i, ch->ion_fd_table[i]); ion_free(ion_client, ch->ion_handle_table[i]); ch->ion_handle_table[i] = NULL; ch->ion_fd_table[i] = -1; - pr_debug("unlocked ion buf#[%d].\n", i); found = true; break; } diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index b8360383a6d2..aa122340c717 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -406,19 +406,18 @@ config INTEL_PCH_THERMAL programmable trip points and other information. config THERMAL_QPNP - tristate "Qualcomm Plug-and-Play PMIC Temperature Alarm" - depends on THERMAL - depends on OF - depends on SPMI - help - This enables a thermal Sysfs driver for Qualcomm plug-and-play (QPNP) - PMIC devices. It shows up in Sysfs as a thermal zone with multiple - trip points. The temperature reported by the thermal zone reflects the - real time die temperature if an ADC is present or an estimate of the - temperature based upon the over temperature stage value if no ADC is - available. If allowed via compile time configuration; enabling the - thermal zone device via the mode file results in shifting PMIC over - temperature shutdown control from hardware to software. + tristate "Qualcomm Technologies, Inc. QPNP PMIC Temperature Alarm" + depends on OF && SPMI + help + This enables a thermal Sysfs driver for Qualcomm Technologies, Inc. + QPNP PMIC devices. It shows up in Sysfs as a thermal zone with + multiple trip points. The temperature reported by the thermal zone + reflects the real time die temperature if an ADC is present or an + estimate of the temperature based upon the over temperature stage + value if no ADC is available. If allowed via compile time + configuration; enabling the thermal zone device via the mode file + results in shifting PMIC over temperature shutdown control from + hardware to software. config THERMAL_QPNP_ADC_TM tristate "Qualcomm 8974 Thermal Monitor ADC Driver" diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c index 82a8e4e200ba..d59b9736c570 100644 --- a/drivers/thermal/msm-tsens.c +++ b/drivers/thermal/msm-tsens.c @@ -364,6 +364,7 @@ static int32_t get_tsens_sensor_for_client_id(struct tsens_tm_device *tmdev, if (!strcmp(id->compatible, "qcom,msm8996-tsens") || (!strcmp(id->compatible, "qcom,msm8998-tsens")) || (!strcmp(id->compatible, "qcom,sdm660-tsens")) || + (!strcmp(id->compatible, "qcom,sdm630-tsens")) || (!strcmp(id->compatible, "qcom,msmhamster-tsens"))) { while (i < tmdev->tsens_num_sensor && !id_found) { if (tmdev->sensor[i].sensor_client_id == @@ -494,6 +495,7 @@ int tsens_get_hw_id_mapping(int thermal_sensor_num, int *sensor_client_id) if (!strcmp(id->compatible, "qcom,msm8996-tsens") || (!strcmp(id->compatible, "qcom,msm8998-tsens")) || (!strcmp(id->compatible, "qcom,sdm660-tsens")) || + (!strcmp(id->compatible, "qcom,sdm630-tsens")) || (!strcmp(id->compatible, "qcom,msmhamster-tsens"))) { /* Assign client id's that is used to get the * controller and hw_sensor details diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c index 7758750516f8..4ebfc713cb28 100644 --- a/drivers/thermal/msm_lmh_dcvs.c +++ b/drivers/thermal/msm_lmh_dcvs.c @@ -68,6 +68,8 @@ _max = (_val) & 0x3FF; \ _max *= 19200; \ } while (0) +#define FREQ_KHZ_TO_HZ(_val) ((_val) * 1000) +#define FREQ_HZ_TO_KHZ(_val) ((_val) / 1000) enum lmh_hw_trips { LIMITS_TRIP_LO, @@ -114,6 +116,7 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw) uint32_t max_limit = 0, val = 0; struct device *cpu_dev = NULL; unsigned long freq_val; + struct dev_pm_opp *opp_entry; val = readl_relaxed(hw->osm_hw_reg); dcvsh_get_frequency(val, max_limit); @@ -124,11 +127,23 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw) goto notify_exit; } - freq_val = max_limit; + freq_val = FREQ_KHZ_TO_HZ(max_limit); rcu_read_lock(); - dev_pm_opp_find_freq_floor(cpu_dev, &freq_val); + opp_entry = dev_pm_opp_find_freq_floor(cpu_dev, &freq_val); + /* + * Hardware mitigation frequency can be lower than the lowest + * possible CPU frequency. In that case freq floor call will + * fail with -ERANGE and we need to match to the lowest + * frequency using freq_ceil. + */ + if (IS_ERR(opp_entry) && PTR_ERR(opp_entry) == -ERANGE) { + opp_entry = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_val); + if (IS_ERR(opp_entry)) + dev_err(cpu_dev, "frequency:%lu. opp error:%ld\n", + freq_val, PTR_ERR(opp_entry)); + } rcu_read_unlock(); - max_limit = freq_val; + max_limit = FREQ_HZ_TO_KHZ(freq_val); sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit); trace_lmh_dcvs_freq(cpumask_first(&hw->core_map), max_limit); diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c index 691c6c16532d..8c516da1d9ab 100644 --- a/drivers/thermal/qpnp-temp-alarm.c +++ b/drivers/thermal/qpnp-temp-alarm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -773,7 +773,7 @@ static const struct dev_pm_ops qpnp_tm_pm_ops = { #define QPNP_TM_PM_OPS NULL #endif -static struct of_device_id qpnp_tm_match_table[] = { +static const struct of_device_id qpnp_tm_match_table[] = { { .compatible = QPNP_TM_DRIVER_NAME, }, {} }; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0e73026711d6..9de5e06430e1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1021,6 +1021,8 @@ struct dwc3 { unsigned irq_event_count[MAX_INTR_STATS]; unsigned irq_dbg_index; + unsigned long l1_remote_wakeup_cnt; + wait_queue_head_t wait_linkstate; }; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 4b4978043d50..068b03a35bd5 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -1180,9 +1180,12 @@ static int dwc3_gadget_int_events_show(struct seq_file *s, void *unused) seq_printf(s, "%d\t", dwc->bh_completion_time[i]); seq_putc(s, '\n'); - seq_printf(s, "t_pwr evt irq : %lld\t", + seq_printf(s, "t_pwr evt irq : %lld\n", ktime_to_us(dwc->t_pwr_evt_irq)); + seq_printf(s, "l1_remote_wakeup_cnt : %lu\n", + dwc->l1_remote_wakeup_cnt); + spin_unlock_irqrestore(&dwc->lock, flags); return 0; } diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 2b910e09a80a..9cd87513619c 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -236,6 +236,8 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, unsigned long flags; int ret; + enum dwc3_link_state link_state; + u32 reg; spin_lock_irqsave(&dwc->lock, flags); if (!dep->endpoint.desc) { @@ -252,6 +254,18 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, goto out; } + /* if link stats is in L1 initiate remote wakeup before queuing req */ + if (dwc->speed != DWC3_DSTS_SUPERSPEED) { + link_state = dwc3_get_link_state(dwc); + /* in HS this link state is same as L1 */ + if (link_state == DWC3_LINK_STATE_U2) { + dwc->l1_remote_wakeup_cnt++; + reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg |= DWC3_DCTL_ULSTCHNG_RECOVERY; + dwc3_writel(dwc->regs, DWC3_DCTL, reg); + } + } + dwc3_trace(trace_dwc3_ep0, "queueing request %pK to %s length %d state '%s'", request, dep->name, request->length, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e2440b7efc58..88350e61f3bd 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1317,13 +1317,6 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) return 0; } -static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc) -{ - u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); - return DWC3_DSTS_USBLNKST(reg); -} - static bool dwc3_gadget_is_suspended(struct dwc3 *dwc) { if (atomic_read(&dwc->in_lpm) || diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 3abd6379164e..a21962c8f513 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -84,6 +84,14 @@ static inline void dwc3_gadget_move_request_queued(struct dwc3_request *req) list_move_tail(&req->list, &dep->req_queued); } +static inline enum dwc3_link_state dwc3_get_link_state(struct dwc3 *dwc) +{ + u32 reg; + + reg = dwc3_readl(dwc->regs, DWC3_DSTS); + return DWC3_DSTS_USBLNKST(reg); +} + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index d03678a02185..7f1ae5cf9909 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c @@ -25,6 +25,7 @@ int dwc3_host_init(struct dwc3 *dwc) struct platform_device *xhci; struct usb_xhci_pdata pdata; int ret; + struct device_node *node = dwc->dev->of_node; xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); if (!xhci) { @@ -52,6 +53,11 @@ int dwc3_host_init(struct dwc3 *dwc) pdata.usb3_lpm_capable = dwc->usb3_lpm_capable; + ret = of_property_read_u32(node, "xhci-imod-value", + &pdata.imod_interval); + if (ret) + pdata.imod_interval = 0; /* use default xhci.c value */ + ret = platform_device_add_data(xhci, &pdata, sizeof(pdata)); if (ret) { dev_err(dwc->dev, "couldn't add platform data to xHCI device\n"); diff --git a/drivers/usb/gadget/function/u_data_ipa.c b/drivers/usb/gadget/function/u_data_ipa.c index 6c18a04f6c1c..83a98f1196f8 100644 --- a/drivers/usb/gadget/function/u_data_ipa.c +++ b/drivers/usb/gadget/function/u_data_ipa.c @@ -402,6 +402,7 @@ static void ipa_data_connect_work(struct work_struct *w) if (!port->port_usb) { spin_unlock_irqrestore(&port->port_lock, flags); + usb_gadget_autopm_put_async(port->gadget); pr_err("%s(): port_usb is NULL.\n", __func__); return; } diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 1221a80e0bdc..05d96fd8c07c 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -138,6 +138,8 @@ static int xhci_plat_probe(struct platform_device *pdev) struct clk *clk; int ret; int irq; + u32 temp, imod; + unsigned long flags; if (usb_disabled()) return -ENODEV; @@ -256,6 +258,18 @@ static int xhci_plat_probe(struct platform_device *pdev) device_wakeup_enable(&xhci->shared_hcd->self.root_hub->dev); + /* override imod interval if specified */ + if (pdata && pdata->imod_interval) { + imod = pdata->imod_interval & ER_IRQ_INTERVAL_MASK; + spin_lock_irqsave(&xhci->lock, flags); + temp = readl_relaxed(&xhci->ir_set->irq_control); + temp &= ~ER_IRQ_INTERVAL_MASK; + temp |= imod; + writel_relaxed(temp, &xhci->ir_set->irq_control); + spin_unlock_irqrestore(&xhci->lock, flags); + dev_dbg(&pdev->dev, "%s: imod set to %u\n", __func__, imod); + } + ret = device_create_file(&pdev->dev, &dev_attr_config_imod); if (ret) dev_err(&pdev->dev, "%s: unable to create imod sysfs entry\n", diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index ed33743c9062..611750e209f9 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -243,6 +243,10 @@ static void *usbpd_ipc_log; #define MAX_VDM_RESPONSE_TIME 60 /* 2 * tVDMSenderResponse_max(30ms) */ #define MAX_VDM_BUSY_TIME 100 /* 2 * tVDMBusy (50ms) */ +#define PD_SNK_PDO_FIXED(prs, hc, uc, usb_comm, drs, volt, curr) \ + (((prs) << 29) | ((hc) << 28) | ((uc) << 27) | ((usb_comm) << 26) | \ + ((drs) << 25) | ((volt) << 10) | (curr)) + /* VDM header is the first 32-bit object following the 16-bit PD header */ #define VDM_HDR_SVID(hdr) ((hdr) >> 16) #define VDM_IS_SVDM(hdr) ((hdr) & 0x8000) @@ -273,7 +277,7 @@ static int min_sink_current = 900; module_param(min_sink_current, int, S_IRUSR | S_IWUSR); static const u32 default_src_caps[] = { 0x36019096 }; /* VSafe5V @ 1.5A */ -static const u32 default_snk_caps[] = { 0x2601905A }; /* 5V @ 900mA */ +static const u32 default_snk_caps[] = { 0x2601912C }; /* VSafe5V @ 3A */ struct vdm_tx { u32 data[7]; @@ -318,6 +322,9 @@ struct usbpd { bool peer_pr_swap; bool peer_dr_swap; + u32 sink_caps[7]; + int num_sink_caps; + struct power_supply *usb_psy; struct notifier_block psy_nb; @@ -1718,8 +1725,8 @@ static void usbpd_sm(struct work_struct *w) } } else if (IS_CTRL(rx_msg, MSG_GET_SINK_CAP)) { ret = pd_send_msg(pd, MSG_SINK_CAPABILITIES, - default_snk_caps, - ARRAY_SIZE(default_snk_caps), SOP_MSG); + pd->sink_caps, pd->num_sink_caps, + SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending Sink Caps\n"); usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET); @@ -1996,8 +2003,8 @@ static void usbpd_sm(struct work_struct *w) usbpd_set_state(pd, PE_SNK_EVALUATE_CAPABILITY); } else if (IS_CTRL(rx_msg, MSG_GET_SINK_CAP)) { ret = pd_send_msg(pd, MSG_SINK_CAPABILITIES, - default_snk_caps, - ARRAY_SIZE(default_snk_caps), SOP_MSG); + pd->sink_caps, pd->num_sink_caps, + SOP_MSG); if (ret) { usbpd_err(&pd->dev, "Error sending Sink Caps\n"); usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET); @@ -3157,6 +3164,44 @@ struct usbpd *usbpd_create(struct device *parent) pd->vconn_is_external = device_property_present(parent, "qcom,vconn-uses-external-source"); + pd->num_sink_caps = device_property_read_u32_array(parent, + "qcom,default-sink-caps", NULL, 0); + if (pd->num_sink_caps) { + int i; + u32 sink_caps[14]; + + if (pd->num_sink_caps % 2 || pd->num_sink_caps > 14) { + ret = -EINVAL; + usbpd_err(&pd->dev, "default-sink-caps must be be specified as voltage/current, max 7 pairs\n"); + goto put_psy; + } + + ret = device_property_read_u32_array(parent, + "qcom,default-sink-caps", sink_caps, + pd->num_sink_caps); + if (ret) { + usbpd_err(&pd->dev, "Error reading default-sink-caps\n"); + goto put_psy; + } + + pd->num_sink_caps /= 2; + + for (i = 0; i < pd->num_sink_caps; i++) { + int v = sink_caps[i * 2] / 50; + int c = sink_caps[i * 2 + 1] / 10; + + pd->sink_caps[i] = + PD_SNK_PDO_FIXED(0, 0, 0, 0, 0, v, c); + } + + /* First PDO includes additional capabilities */ + pd->sink_caps[0] |= PD_SNK_PDO_FIXED(1, 0, 0, 1, 1, 0, 0); + } else { + memcpy(pd->sink_caps, default_snk_caps, + sizeof(default_snk_caps)); + pd->num_sink_caps = ARRAY_SIZE(default_snk_caps); + } + /* * Register the Android dual-role class (/sys/class/dual_role_usb/). * The first instance should be named "otg_default" as that's what diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c index da6c68d43b53..fc89a2ea772e 100644 --- a/drivers/video/fbdev/msm/mdp3_ctrl.c +++ b/drivers/video/fbdev/msm/mdp3_ctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2147,8 +2147,10 @@ static int mdp3_ctrl_lut_config(struct msm_fb_data_type *mfd, dma = mdp3_session->dma; - if (cfg->cmap.start + cfg->cmap.len > MDP_LUT_SIZE) { - pr_err("Invalid arguments\n"); + if ((cfg->cmap.start > MDP_LUT_SIZE) || + (cfg->cmap.len > MDP_LUT_SIZE) || + (cfg->cmap.start + cfg->cmap.len > MDP_LUT_SIZE)) { + pr_err("Invalid arguments.\n"); return -EINVAL; } diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index f3c36c5c6b5a..af9dc7ce1730 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -129,6 +129,40 @@ static int mdss_dp_is_clk_prefix(const char *clk_prefix, const char *clk_name) return !strncmp(clk_name, clk_prefix, strlen(clk_prefix)); } +static int mdss_dp_parse_prop(struct platform_device *pdev, + struct mdss_dp_drv_pdata *dp_drv) +{ + int len = 0, i = 0; + const char *data; + + data = of_get_property(pdev->dev.of_node, + "qcom,aux-cfg-settings", &len); + if ((!data) || (len != AUX_CFG_LEN)) { + pr_err("%s:%d, Unable to read DP AUX CFG settings", + __func__, __LINE__); + return -EINVAL; + } + + for (i = 0; i < len; i++) + dp_drv->aux_cfg[i] = data[i]; + + data = of_get_property(pdev->dev.of_node, + "qcom,logical2physical-lane-map", &len); + if ((!data) || (len != DP_MAX_PHY_LN)) { + pr_debug("%s:%d, lane mapping not defined, use default", + __func__, __LINE__); + dp_drv->l_map[DP_PHY_LN0] = DP_ML0; + dp_drv->l_map[DP_PHY_LN1] = DP_ML1; + dp_drv->l_map[DP_PHY_LN2] = DP_ML2; + dp_drv->l_map[DP_PHY_LN3] = DP_ML3; + } else { + for (i = 0; i < len; i++) + dp_drv->l_map[i] = data[i]; + } + + return 0; +} + static int mdss_dp_init_clk_power_data(struct device *dev, struct mdss_dp_drv_pdata *pdata) { @@ -304,7 +338,25 @@ static int mdss_dp_clk_init(struct mdss_dp_drv_pdata *dp_drv, goto ctrl_get_error; } + dp_drv->pixel_clk_rcg = devm_clk_get(dev, "pixel_clk_rcg"); + if (IS_ERR(dp_drv->pixel_clk_rcg)) { + pr_debug("%s: Unable to get DP pixel clk RCG\n", + __func__); + dp_drv->pixel_clk_rcg = NULL; + } + + dp_drv->pixel_parent = devm_clk_get(dev, + "pixel_parent"); + if (IS_ERR(dp_drv->pixel_parent)) { + pr_debug("%s: Unable to get DP pixel RCG parent\n", + __func__); + dp_drv->pixel_parent = NULL; + } } else { + if (dp_drv->pixel_parent) + devm_clk_put(dev, dp_drv->pixel_parent); + if (dp_drv->pixel_clk_rcg) + devm_clk_put(dev, dp_drv->pixel_clk_rcg); msm_dss_put_clk(ctrl_power_data->clk_config, ctrl_power_data->num_clk); msm_dss_put_clk(core_power_data->clk_config, @@ -1151,10 +1203,9 @@ static inline void mdss_dp_ack_state(struct mdss_dp_drv_pdata *dp, int val) * given usb plug orientation. */ static int mdss_dp_get_lane_mapping(struct mdss_dp_drv_pdata *dp, - enum plug_orientation orientation, - struct lane_mapping *lane_map) + enum plug_orientation orientation, char *lane_map) { - int ret = 0; + int ret = 0, i = 0, j = 0; pr_debug("enter: orientation = %d\n", orientation); @@ -1164,22 +1215,35 @@ static int mdss_dp_get_lane_mapping(struct mdss_dp_drv_pdata *dp, goto exit; } - /* Set the default lane mapping */ - lane_map->lane0 = 2; - lane_map->lane1 = 3; - lane_map->lane2 = 1; - lane_map->lane3 = 0; - + /* For flip case, swap phy lanes with ML0 and ML3, ML1 and ML2 */ if (orientation == ORIENTATION_CC2) { - lane_map->lane0 = 1; - lane_map->lane1 = 0; - lane_map->lane2 = 2; - lane_map->lane3 = 3; + for (i = 0; i < DP_MAX_PHY_LN; i++) { + if (dp->l_map[i] == DP_ML0) { + for (j = 0; j < DP_MAX_PHY_LN; j++) { + if (dp->l_map[j] == DP_ML3) { + lane_map[i] = DP_ML3; + lane_map[j] = DP_ML0; + break; + } + } + } else if (dp->l_map[i] == DP_ML1) { + for (j = 0; j < DP_MAX_PHY_LN; j++) { + if (dp->l_map[j] == DP_ML2) { + lane_map[i] = DP_ML2; + lane_map[j] = DP_ML1; + break; + } + } + } + } + } else { + /* Normal orientation */ + for (i = 0; i < DP_MAX_PHY_LN; i++) + lane_map[i] = dp->l_map[i]; } pr_debug("lane0 = %d, lane1 = %d, lane2 =%d, lane3 =%d\n", - lane_map->lane0, lane_map->lane1, lane_map->lane2, - lane_map->lane3); + lane_map[0], lane_map[1], lane_map[2], lane_map[3]); exit: return ret; @@ -1212,6 +1276,9 @@ static int mdss_dp_enable_mainlink_clocks(struct mdss_dp_drv_pdata *dp) { int ret = 0; + if (dp->pixel_clk_rcg && dp->pixel_parent) + clk_set_parent(dp->pixel_clk_rcg, dp->pixel_parent); + mdss_dp_set_clock_rate(dp, "ctrl_link_clk", (dp->link_rate * DP_LINK_RATE_MULTIPLIER) / DP_KHZ_TO_HZ); @@ -1248,9 +1315,9 @@ static void mdss_dp_disable_mainlink_clocks(struct mdss_dp_drv_pdata *dp_drv) * configuration, output format and sink/panel timing information. */ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp, - struct lane_mapping *lane_map) + char *lane_map) { - mdss_dp_ctrl_lane_mapping(&dp->ctrl_io, *lane_map); + mdss_dp_ctrl_lane_mapping(&dp->ctrl_io, lane_map); mdss_dp_fill_link_cfg(dp); mdss_dp_mainlink_ctrl(&dp->ctrl_io, true); mdss_dp_config_ctrl(dp); @@ -1318,7 +1385,7 @@ end: static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) { int ret = 0; - struct lane_mapping ln_map; + char ln_map[4]; /* wait until link training is completed */ pr_debug("enter, lt_needed=%s\n", lt_needed ? "true" : "false"); @@ -1331,13 +1398,14 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) dp_init_panel_info(dp_drv, dp_drv->vic); ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, - &ln_map); + ln_map); if (ret) goto exit_loop; mdss_dp_phy_share_lane_config(&dp_drv->phy_io, dp_drv->orientation, - dp_drv->dpcd.max_lane_count); + dp_drv->dpcd.max_lane_count, + dp_drv->phy_reg_offset); if (lt_needed) { /* @@ -1352,7 +1420,7 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv, bool lt_needed) goto exit_loop; } - mdss_dp_configure_source_params(dp_drv, &ln_map); + mdss_dp_configure_source_params(dp_drv, ln_map); reinit_completion(&dp_drv->idle_comp); @@ -1385,7 +1453,7 @@ exit_loop: int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) { int ret = 0; - struct lane_mapping ln_map; + char ln_map[4]; /* wait until link training is completed */ mutex_lock(&dp_drv->train_mutex); @@ -1404,7 +1472,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) } mdss_dp_hpd_configure(&dp_drv->ctrl_io, true); - ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, &ln_map); + ret = mdss_dp_get_lane_mapping(dp_drv, dp_drv->orientation, ln_map); if (ret) goto exit; @@ -1419,7 +1487,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) } mdss_dp_phy_share_lane_config(&dp_drv->phy_io, dp_drv->orientation, - dp_drv->dpcd.max_lane_count); + dp_drv->dpcd.max_lane_count, dp_drv->phy_reg_offset); ret = mdss_dp_enable_mainlink_clocks(dp_drv); if (ret) @@ -1427,7 +1495,7 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv) reinit_completion(&dp_drv->idle_comp); - mdss_dp_configure_source_params(dp_drv, &ln_map); + mdss_dp_configure_source_params(dp_drv, ln_map); if (dp_drv->psm_enabled) { ret = mdss_dp_aux_send_psm_request(dp_drv, false); @@ -1689,7 +1757,8 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata) mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io), mdss_dp_get_phy_hw_version(&dp_drv->phy_io)); - mdss_dp_phy_aux_setup(&dp_drv->phy_io); + mdss_dp_phy_aux_setup(&dp_drv->phy_io, dp_drv->aux_cfg, + dp_drv->phy_reg_offset); mdss_dp_irq_enable(dp_drv); dp_drv->dp_initialized = true; @@ -2743,6 +2812,11 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev, return rc; } + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,phy-register-offset", &dp_drv->phy_reg_offset); + if (rc) + dp_drv->phy_reg_offset = 0; + rc = msm_dss_ioremap_byname(pdev, &dp_drv->tcsr_reg_io, "tcsr_regs"); if (rc) { @@ -3704,6 +3778,13 @@ static int mdss_dp_probe(struct platform_device *pdev) goto probe_err; } + ret = mdss_dp_parse_prop(pdev, dp_drv); + if (ret) { + DEV_ERR("DP properties parsing failed.ret=%d\n", + ret); + goto probe_err; + } + ret = mdss_dp_irq_setup(dp_drv); if (ret) goto probe_err; @@ -3759,18 +3840,33 @@ probe_err: void *mdss_dp_get_hdcp_data(struct device *dev) { - struct mdss_dp_drv_pdata *dp_drv = NULL; + struct mdss_dp_drv_pdata *dp; + struct msm_fb_data_type *mfd; + struct mdss_panel_data *pd; + struct fb_info *fbi = dev_get_drvdata(dev); - if (!dev) { - pr_err("%s:Invalid input\n", __func__); - return NULL; + if (!fbi) { + pr_err("invalid fbi\n"); + goto error; } - dp_drv = dev_get_drvdata(dev); - if (!dp_drv) { - pr_err("%s:Invalid dp driver\n", __func__); - return NULL; + + mfd = (struct msm_fb_data_type *)fbi->par; + if (!mfd) { + pr_err("invalid mfd\n"); + goto error; } - return dp_drv->hdcp.data; + + pd = dev_get_platdata(&mfd->pdev->dev); + if (!pd) { + pr_err("invalid panel_data\n"); + goto error; + } + + dp = container_of(pd, struct mdss_dp_drv_pdata, panel_data); + + return dp->hdcp.data; +error: + return NULL; } static inline bool dp_is_stream_shareable(struct mdss_dp_drv_pdata *dp_drv) diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index bf74a8a4d7df..d6f5d160aef2 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -36,6 +36,8 @@ #define AUX_CMD_MAX 16 #define AUX_CMD_I2C_MAX 128 +#define AUX_CFG_LEN 10 + #define EDP_PORT_MAX 1 #define EDP_SINK_CAP_LEN 16 @@ -460,6 +462,7 @@ struct mdss_dp_drv_pdata { struct dss_io_data dp_cc_io; struct dss_io_data qfprom_io; struct dss_io_data hdcp_io; + u32 phy_reg_offset; int base_size; unsigned char *mmss_cc_base; bool override_config; @@ -486,6 +489,10 @@ struct mdss_dp_drv_pdata { struct edp_edid edid; struct dpcd_cap dpcd; + /* DP Pixel clock RCG and PLL parent */ + struct clk *pixel_clk_rcg; + struct clk *pixel_parent; + /* regulators */ struct dss_module_power power_data[DP_MAX_PM]; struct dp_pinctrl_res pin_res; @@ -536,6 +543,10 @@ struct mdss_dp_drv_pdata { struct mdss_dp_event_data dp_event; struct task_struct *ev_thread; + /* dt settings */ + char l_map[4]; + u32 aux_cfg[AUX_CFG_LEN]; + struct workqueue_struct *workq; struct delayed_work hdcp_cb_work; spinlock_t lock; @@ -554,6 +565,21 @@ struct mdss_dp_drv_pdata { struct list_head attention_head; }; +enum dp_phy_lane_num { + DP_PHY_LN0 = 0, + DP_PHY_LN1 = 1, + DP_PHY_LN2 = 2, + DP_PHY_LN3 = 3, + DP_MAX_PHY_LN = 4, +}; + +enum dp_mainlink_lane_num { + DP_ML0 = 0, + DP_ML1 = 1, + DP_ML2 = 2, + DP_ML3 = 3, +}; + enum dp_lane_count { DP_LANE_COUNT_1 = 1, DP_LANE_COUNT_2 = 2, diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 1dcf83f094c1..3b9242448198 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -859,31 +859,38 @@ void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, pr_debug("dp_tu=0x%x\n", dp_tu); } -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map) +void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map) { u8 bits_per_lane = 2; - u32 lane_map = ((l_map.lane0 << (bits_per_lane * 0)) - | (l_map.lane1 << (bits_per_lane * 1)) - | (l_map.lane2 << (bits_per_lane * 2)) - | (l_map.lane3 << (bits_per_lane * 3))); + u32 lane_map = ((l_map[0] << (bits_per_lane * 0)) + | (l_map[1] << (bits_per_lane * 1)) + | (l_map[2] << (bits_per_lane * 2)) + | (l_map[3] << (bits_per_lane * 3))); pr_debug("%s: lane mapping reg = 0x%x\n", __func__, lane_map); writel_relaxed(lane_map, ctrl_io->base + DP_LOGICAL2PHYSCIAL_LANE_MAPPING); } -void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io) +void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io, u32 *aux_cfg, + u32 phy_reg_offset) { - writel_relaxed(0x3d, phy_io->base + DP_PHY_PD_CTL); - writel_relaxed(0x13, phy_io->base + DP_PHY_AUX_CFG1); - writel_relaxed(0x10, phy_io->base + DP_PHY_AUX_CFG3); - writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG4); - writel_relaxed(0x26, phy_io->base + DP_PHY_AUX_CFG5); - writel_relaxed(0x0a, phy_io->base + DP_PHY_AUX_CFG6); - writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG7); - writel_relaxed(0x8b, phy_io->base + DP_PHY_AUX_CFG8); - writel_relaxed(0x03, phy_io->base + DP_PHY_AUX_CFG9); - writel_relaxed(0x1f, phy_io->base + DP_PHY_AUX_INTERRUPT_MASK); + void __iomem *adjusted_phy_io_base = phy_io->base + phy_reg_offset; + + writel_relaxed(0x3d, adjusted_phy_io_base + DP_PHY_PD_CTL); + + /* DP AUX CFG register programming */ + writel_relaxed(aux_cfg[0], adjusted_phy_io_base + DP_PHY_AUX_CFG0); + writel_relaxed(aux_cfg[1], adjusted_phy_io_base + DP_PHY_AUX_CFG1); + writel_relaxed(aux_cfg[2], adjusted_phy_io_base + DP_PHY_AUX_CFG2); + writel_relaxed(aux_cfg[3], adjusted_phy_io_base + DP_PHY_AUX_CFG3); + writel_relaxed(aux_cfg[4], adjusted_phy_io_base + DP_PHY_AUX_CFG4); + writel_relaxed(aux_cfg[5], adjusted_phy_io_base + DP_PHY_AUX_CFG5); + writel_relaxed(aux_cfg[6], adjusted_phy_io_base + DP_PHY_AUX_CFG6); + writel_relaxed(aux_cfg[7], adjusted_phy_io_base + DP_PHY_AUX_CFG7); + writel_relaxed(aux_cfg[8], adjusted_phy_io_base + DP_PHY_AUX_CFG8); + writel_relaxed(aux_cfg[9], adjusted_phy_io_base + DP_PHY_AUX_CFG9); + + writel_relaxed(0x1f, adjusted_phy_io_base + DP_PHY_AUX_INTERRUPT_MASK); } int mdss_dp_irq_setup(struct mdss_dp_drv_pdata *dp_drv) @@ -1036,14 +1043,14 @@ u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp) } void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io, - u8 orientation, u8 ln_cnt) + u8 orientation, u8 ln_cnt, u32 phy_reg_offset) { u32 info = 0x0; info |= (ln_cnt & 0x0F); info |= ((orientation & 0x0F) << 4); pr_debug("Shared Info = 0x%x\n", info); - writel_relaxed(info, phy_io->base + DP_PHY_SPARE0); + writel_relaxed(info, phy_io->base + phy_reg_offset + DP_PHY_SPARE0); } void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io, char link_rate) @@ -1051,8 +1058,6 @@ void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io, char link_rate) u32 acr_ctrl = 0; u32 select = 0; - acr_ctrl = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_ACR_CTRL); - switch (link_rate) { case DP_LINK_RATE_162: select = 0; diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h index cb62d145960f..b3b15a3579fa 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.h +++ b/drivers/video/fbdev/msm/mdss_dp_util.h @@ -206,13 +206,6 @@ #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C) #define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020) -struct lane_mapping { - char lane0; - char lane1; - char lane2; - char lane3; -}; - struct edp_cmd { char read; /* 1 == read, 0 == write */ char i2c; /* 1 == i2c cmd, 0 == native cmd */ @@ -292,12 +285,12 @@ void mdss_dp_assert_phy_reset(struct dss_io_data *ctrl_io, bool assert); void mdss_dp_setup_tr_unit(struct dss_io_data *ctrl_io, u8 link_rate, u8 ln_cnt, u32 res, struct mdss_panel_info *pinfo); void mdss_dp_config_misc(struct mdss_dp_drv_pdata *dp, u32 bd, u32 cc); -void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io); +void mdss_dp_phy_aux_setup(struct dss_io_data *phy_io, u32 *aux_cfg, + u32 phy_reg_offset); void mdss_dp_hpd_configure(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_aux_ctrl(struct dss_io_data *ctrl_io, bool enable); void mdss_dp_mainlink_ctrl(struct dss_io_data *ctrl_io, bool enable); -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map); +void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, char *l_map); int mdss_dp_mainlink_ready(struct mdss_dp_drv_pdata *dp, u32 which); void mdss_dp_timing_cfg(struct dss_io_data *ctrl_io, struct mdss_panel_info *pinfo); @@ -311,10 +304,8 @@ void mdss_dp_sw_config_msa(struct dss_io_data *ctrl_io, void mdss_dp_usbpd_ext_capabilities(struct usbpd_dp_capabilities *dp_cap); void mdss_dp_usbpd_ext_dp_status(struct usbpd_dp_status *dp_status); u32 mdss_dp_usbpd_gen_config_pkt(struct mdss_dp_drv_pdata *dp); -void mdss_dp_ctrl_lane_mapping(struct dss_io_data *ctrl_io, - struct lane_mapping l_map); void mdss_dp_phy_share_lane_config(struct dss_io_data *phy_io, - u8 orientation, u8 ln_cnt); + u8 orientation, u8 ln_cnt, u32 phy_reg_offset); void mdss_dp_config_audio_acr_ctrl(struct dss_io_data *ctrl_io, char link_rate); void mdss_dp_audio_setup_sdps(struct dss_io_data *ctrl_io, u32 num_of_channels); diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c index 51745a9a59ac..c66d9f3b3a65 100644 --- a/drivers/video/fbdev/msm/mdss_dsi.c +++ b/drivers/video/fbdev/msm/mdss_dsi.c @@ -2183,6 +2183,21 @@ static int mdss_dsi_check_params(struct mdss_dsi_ctrl_pdata *ctrl, void *arg) return rc; } +static void mdss_dsi_avr_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata, + int enabled) +{ + u32 data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x10); + + /* DSI_VIDEO_MODE_CTRL */ + if (enabled) + data |= BIT(29); /* AVR_SUPPORT_ENABLED */ + else + data &= ~BIT(29); + + MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x10, data); + MDSS_XLOG(ctrl_pdata->ndx, enabled, data); +} + static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps) { int rc = 0; @@ -2700,6 +2715,9 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata, case MDSS_EVENT_DSI_TIMING_DB_CTRL: mdss_dsi_timing_db_ctrl(ctrl_pdata, (int)(unsigned long)arg); break; + case MDSS_EVENT_AVR_MODE: + mdss_dsi_avr_config(ctrl_pdata, (int)(unsigned long) arg); + break; default: pr_debug("%s: unhandled event=%d\n", __func__, event); break; diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c index abc56f5f352d..5804d88e5af5 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c @@ -22,6 +22,7 @@ #include <linux/types.h> #include <linux/hdcp_qseecom.h> #include <linux/msm_mdp.h> +#include <linux/msm_ext_display.h> #define REG_DUMP 0 @@ -414,7 +415,6 @@ static inline void hdmi_tx_cec_device_suspend(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_cec_device_suspend(fd, hdmi_ctrl->panel_suspend); } - static inline void hdmi_tx_send_cable_notification( struct hdmi_tx_ctrl *hdmi_ctrl, int val) { @@ -431,7 +431,7 @@ static inline void hdmi_tx_send_cable_notification( } } -static inline void hdmi_tx_set_audio_switch_node( +static inline void hdmi_tx_ack_state( struct hdmi_tx_ctrl *hdmi_ctrl, int val) { if (hdmi_ctrl && hdmi_ctrl->ext_audio_data.intf_ops.notify && @@ -440,47 +440,6 @@ static inline void hdmi_tx_set_audio_switch_node( val); } -static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl) -{ - u64 status = 0; - u32 wait_for_vote = 50; - struct dss_io_data *io = NULL; - - if (!hdmi_ctrl) { - DEV_ERR("%s: invalid input\n", __func__); - return; - } - - io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO]; - if (!io->base) { - DEV_ERR("%s: core io not inititalized\n", __func__); - return; - } - - /* - * wait for 5 sec max for audio engine to acknowledge if hdmi tx core - * can be safely turned off. Sleep for a reasonable time to make sure - * vote_hdmi_core_on variable is updated properly by audio. - */ - while (hdmi_ctrl->vote_hdmi_core_on && --wait_for_vote) - msleep(100); - - - if (!wait_for_vote) - DEV_ERR("%s: HDMI core still voted for power on\n", __func__); - - if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status, - (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US, - AUDIO_POLL_TIMEOUT_US)) - DEV_ERR("%s: Error turning off audio packet transmission.\n", - __func__); - - if (readl_poll_timeout(io->base + HDMI_AUDIO_CFG, status, - (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US, - AUDIO_POLL_TIMEOUT_US)) - DEV_ERR("%s: Error turning off audio engine.\n", __func__); -} - static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data( struct mdss_panel_data *mpd) { @@ -900,8 +859,7 @@ static ssize_t hdmi_tx_sysfs_wta_hpd(struct device *dev, hdmi_tx_config_5v(hdmi_ctrl, false); } else { hdmi_tx_hpd_off(hdmi_ctrl); - - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); } break; @@ -1589,7 +1547,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } if (hdmi_ctrl->hdcp1_use_sw_keys && hdmi_ctrl->hdcp14_present) @@ -1605,7 +1562,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_encryption_set(hdmi_ctrl) || !hdmi_tx_is_stream_shareable(hdmi_ctrl)) { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); rc = hdmi_tx_config_avmute(hdmi_ctrl, true); } @@ -1631,7 +1587,6 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } break; case HDCP_STATE_AUTH_ENC_1X: @@ -1641,9 +1596,7 @@ static void hdmi_tx_hdcp_cb_work(struct work_struct *work) if (hdmi_tx_is_panel_on(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { rc = hdmi_tx_config_avmute(hdmi_ctrl, false); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); } else { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); rc = hdmi_tx_config_avmute(hdmi_ctrl, true); } break; @@ -2373,7 +2326,8 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work) if (!hdmi_ctrl->hpd_initialized) { DEV_DBG("hpd not initialized\n"); - goto end; + mutex_unlock(&hdmi_ctrl->tx_lock); + return; } DEV_DBG("%s: %s\n", __func__, @@ -2386,16 +2340,11 @@ static void hdmi_tx_hpd_int_work(struct work_struct *work) pr_warn_ratelimited("%s: EDID read failed\n", __func__); hdmi_tx_update_deep_color(hdmi_ctrl); hdmi_tx_update_hdr_info(hdmi_ctrl); - - hdmi_tx_send_cable_notification(hdmi_ctrl, true); - } else { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - - hdmi_tx_send_cable_notification(hdmi_ctrl, false); } -end: + mutex_unlock(&hdmi_ctrl->tx_lock); + + hdmi_tx_send_cable_notification(hdmi_ctrl, hdmi_ctrl->hpd_state); } /* hdmi_tx_hpd_int_work */ static int hdmi_tx_check_capability(struct hdmi_tx_ctrl *hdmi_ctrl) @@ -3239,7 +3188,6 @@ static int hdmi_tx_power_on(struct hdmi_tx_ctrl *hdmi_ctrl) if (hdmi_ctrl->panel.infoframe && !hdmi_tx_is_encryption_set(hdmi_ctrl) && hdmi_tx_is_stream_shareable(hdmi_ctrl)) { - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1); hdmi_tx_config_avmute(hdmi_ctrl, false); } @@ -3845,20 +3793,6 @@ static int hdmi_tx_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl) goto end; } - if (hdmi_ctrl->sdev.state && - !hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) { - u32 timeout; - - reinit_completion(&hdmi_ctrl->hpd_int_done); - timeout = wait_for_completion_timeout( - &hdmi_ctrl->hpd_int_done, HZ/10); - if (!timeout && !hdmi_ctrl->hpd_state) { - DEV_DBG("%s: cable removed during suspend\n", __func__); - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - hdmi_tx_send_cable_notification(hdmi_ctrl, 0); - } - } end: return rc; } @@ -3906,14 +3840,6 @@ static int hdmi_tx_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl) hdmi_ctrl->timing_gen_on = true; - if (hdmi_ctrl->panel_suspend) { - DEV_DBG("%s: panel suspend has triggered\n", __func__); - - hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0); - hdmi_tx_wait_for_audio_engine(hdmi_ctrl); - hdmi_tx_send_cable_notification(hdmi_ctrl, 0); - } - return rc; } @@ -4003,6 +3929,55 @@ static int hdmi_tx_evt_handle_hdmi_ppm(struct hdmi_tx_ctrl *hdmi_ctrl) return hdmi_tx_update_ppm(hdmi_ctrl, ppm); } +static int hdmi_tx_pre_evt_handle_panel_off(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_tx_ack_state(hdmi_ctrl, false); + return 0; +} + +static int hdmi_tx_pre_evt_handle_update_fps(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_ctrl->dynamic_fps = (u32) (unsigned long)hdmi_ctrl->evt_arg; + queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work); + return 0; +} + +static int hdmi_tx_post_evt_handle_unblank(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + hdmi_tx_ack_state(hdmi_ctrl, true); + return 0; +} + +static int hdmi_tx_post_evt_handle_resume(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + if (!hdmi_ctrl->hpd_feature_on) + return 0; + + if (!hdmi_tx_hw_is_cable_connected(hdmi_ctrl)) { + u32 timeout; + + reinit_completion(&hdmi_ctrl->hpd_int_done); + timeout = wait_for_completion_timeout( + &hdmi_ctrl->hpd_int_done, HZ/10); + if (!timeout) { + pr_debug("cable removed during suspend\n"); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); + } + } + + return 0; +} + +static int hdmi_tx_post_evt_handle_panel_on(struct hdmi_tx_ctrl *hdmi_ctrl) +{ + if (hdmi_ctrl->panel_suspend) { + pr_debug("panel suspend has triggered\n"); + hdmi_tx_send_cable_notification(hdmi_ctrl, 0); + } + + return 0; +} + static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data, int event, void *arg) { @@ -4012,33 +3987,52 @@ static int hdmi_tx_event_handler(struct mdss_panel_data *panel_data, hdmi_tx_get_drvdata_from_panel_data(panel_data); if (!hdmi_ctrl) { - DEV_ERR("%s: invalid input\n", __func__); - rc = -EINVAL; - goto end; - } - - /* UPDATE FPS is called from atomic context */ - if (event == MDSS_EVENT_PANEL_UPDATE_FPS) { - hdmi_ctrl->dynamic_fps = (u32) (unsigned long)arg; - queue_work(hdmi_ctrl->workq, &hdmi_ctrl->fps_work); - return rc; + pr_err("%s: invalid input\n", __func__); + return -EINVAL; } - mutex_lock(&hdmi_ctrl->tx_lock); - hdmi_ctrl->evt_arg = arg; - DEV_DBG("%s: event = %s suspend=%d, hpd_feature=%d\n", __func__, + pr_debug("event = %s suspend=%d, hpd_feature=%d\n", mdss_panel_intf_event_to_string(event), hdmi_ctrl->panel_suspend, hdmi_ctrl->hpd_feature_on); + /* event handlers prior to tx_lock */ + handler = hdmi_ctrl->pre_evt_handler[event]; + if (handler) { + rc = handler(hdmi_ctrl); + if (rc) { + pr_err("pre handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + return rc; + } + } + + mutex_lock(&hdmi_ctrl->tx_lock); + handler = hdmi_ctrl->evt_handler[event]; - if (handler) + if (handler) { rc = handler(hdmi_ctrl); + if (rc) { + pr_err("handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + mutex_unlock(&hdmi_ctrl->tx_lock); + return rc; + } + } mutex_unlock(&hdmi_ctrl->tx_lock); -end: + + /* event handlers post to tx_lock */ + handler = hdmi_ctrl->post_evt_handler[event]; + if (handler) { + rc = handler(hdmi_ctrl); + if (rc) + pr_err("post handler failed: event = %s, rc = %d\n", + mdss_panel_intf_event_to_string(event), rc); + } + return rc; } @@ -4692,7 +4686,6 @@ static int hdmi_tx_init_event_handler(struct hdmi_tx_ctrl *hdmi_ctrl) return -EINVAL; handler = hdmi_ctrl->evt_handler; - handler[MDSS_EVENT_FB_REGISTERED] = hdmi_tx_evt_handle_register; handler[MDSS_EVENT_CHECK_PARAMS] = hdmi_tx_evt_handle_check_param; handler[MDSS_EVENT_RESUME] = hdmi_tx_evt_handle_resume; @@ -4704,7 +4697,17 @@ static int hdmi_tx_init_event_handler(struct hdmi_tx_ctrl *hdmi_ctrl) handler[MDSS_EVENT_PANEL_OFF] = hdmi_tx_evt_handle_panel_off; handler[MDSS_EVENT_CLOSE] = hdmi_tx_evt_handle_close; handler[MDSS_EVENT_DEEP_COLOR] = hdmi_tx_evt_handle_deep_color; - handler[MDSS_EVENT_UPDATE_PANEL_PPM] = hdmi_tx_evt_handle_hdmi_ppm; + handler[MDSS_EVENT_UPDATE_PANEL_PPM] = hdmi_tx_evt_handle_hdmi_ppm; + + handler = hdmi_ctrl->pre_evt_handler; + handler[MDSS_EVENT_PANEL_UPDATE_FPS] = + hdmi_tx_pre_evt_handle_update_fps; + handler[MDSS_EVENT_PANEL_OFF] = hdmi_tx_pre_evt_handle_panel_off; + + handler = hdmi_ctrl->post_evt_handler; + handler[MDSS_EVENT_UNBLANK] = hdmi_tx_post_evt_handle_unblank; + handler[MDSS_EVENT_RESUME] = hdmi_tx_post_evt_handle_resume; + handler[MDSS_EVENT_PANEL_ON] = hdmi_tx_post_evt_handle_panel_on; return 0; } diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.h b/drivers/video/fbdev/msm/mdss_hdmi_tx.h index 2a6a48a4e473..ca316a350238 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_tx.h +++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.h @@ -98,7 +98,6 @@ struct hdmi_tx_ctrl { struct mutex tx_lock; struct list_head cable_notify_handlers; struct kobject *kobj; - struct switch_dev sdev; struct workqueue_struct *workq; struct hdmi_util_ds_data ds_data; struct completion hpd_int_done; @@ -166,7 +165,10 @@ struct hdmi_tx_ctrl { char disp_switch_name[MAX_SWITCH_NAME_SIZE]; + /* pre/post is done in the context without tx_lock */ + hdmi_tx_evt_handler pre_evt_handler[MDSS_EVENT_MAX - 1]; hdmi_tx_evt_handler evt_handler[MDSS_EVENT_MAX - 1]; + hdmi_tx_evt_handler post_evt_handler[MDSS_EVENT_MAX - 1]; }; #endif /* __MDSS_HDMI_TX_H__ */ diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index fbbcc16f48b5..b65582f8e042 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -2138,6 +2138,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata) set_bit(MDSS_CAPS_3D_MUX_UNDERRUN_RECOVERY_SUPPORTED, mdata->mdss_caps_map); set_bit(MDSS_CAPS_QSEED3, mdata->mdss_caps_map); + set_bit(MDSS_CAPS_DEST_SCALER, mdata->mdss_caps_map); set_bit(MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED, mdata->mdss_caps_map); mdss_mdp_init_default_prefill_factors(mdata); @@ -4158,6 +4159,7 @@ static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev) static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) { struct mdss_data_type *mdata = platform_get_drvdata(pdev); + u32 npriority_lvl_nrt; int rc; mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev, @@ -4183,8 +4185,20 @@ static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) return; } - mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev, + npriority_lvl_nrt = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-vbif-qos-nrt-setting"); + + if (!npriority_lvl_nrt) { + pr_debug("no vbif nrt priorities found rt:%d\n", + mdata->npriority_lvl); + return; + } else if (npriority_lvl_nrt != mdata->npriority_lvl) { + /* driver expects same number for both nrt and rt */ + pr_err("invalid nrt settings nrt(%d) != rt(%d)\n", + npriority_lvl_nrt, mdata->npriority_lvl); + return; + } + if (mdata->npriority_lvl == MDSS_VBIF_QOS_REMAP_ENTRIES) { mdata->vbif_nrt_qos = kzalloc(sizeof(u32) * mdata->npriority_lvl, GFP_KERNEL); @@ -4202,7 +4216,7 @@ static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev) } } else { mdata->npriority_lvl = 0; - pr_debug("Invalid or no vbif qos nrt seting\n"); + pr_debug("Invalid or no vbif qos nrt setting\n"); } } diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index ffbf156e9eed..acb356fc681a 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -3614,6 +3614,7 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) u32 width, height; int split_fb, rc = 0; u32 max_mixer_width; + bool dsc_merge_enabled = 0; struct mdss_panel_info *pinfo; if (!ctl || !ctl->panel_data) { @@ -3738,15 +3739,15 @@ int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl) ctl->mixer_right = NULL; } - if (ctl->mixer_right) { - if (!is_dsc_compression(pinfo) || - (pinfo->dsc_enc_total == 1)) - ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE | - MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT; - } else { + dsc_merge_enabled = is_dsc_compression(pinfo) && + (pinfo->dsc_enc_total == 2); + + if (ctl->mixer_right && (!dsc_merge_enabled)) + ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE | + MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT; + else ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE | MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT); - } return 0; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c index b7f27b818eda..2a62ae5881b3 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c @@ -2031,6 +2031,19 @@ static int __mdss_mdp_wait4pingpong(struct mdss_mdp_cmd_ctx *ctx) return rc; } +static void __clear_ping_pong_callback(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_cmd_ctx *ctx) +{ + mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num); + mdss_mdp_set_intr_callback_nosync( + MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, + ctx->current_pp_num, NULL, NULL); + if (atomic_add_unless(&ctx->koff_cnt, -1, 0) + && mdss_mdp_cmd_do_notifier(ctx)) + mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT); +} + static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) { struct mdss_mdp_cmd_ctx *ctx; @@ -2047,7 +2060,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) pdata = ctl->panel_data; MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctl->roi_bkup.w, - ctl->roi_bkup.h); + ctl->roi_bkup.h, pdata->panel_info.panel_dead); pr_debug("%s: intf_num=%d ctx=%pK koff_cnt=%d\n", __func__, ctl->intf_num, ctx, atomic_read(&ctx->koff_cnt)); @@ -2073,6 +2086,13 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) mdss_mdp_cmd_pingpong_done(ctl); local_irq_restore(flags); rc = 1; + } else if (pdata->panel_info.panel_dead) { + /* + * if panel is reported dead, no need to wait for + * pingpong done, and don't report timeout + */ + MDSS_XLOG(0xdead); + __clear_ping_pong_callback(ctl, ctx); } rc = atomic_read(&ctx->koff_cnt) == 0; @@ -2098,15 +2118,7 @@ static int mdss_mdp_cmd_wait4pingpong(struct mdss_mdp_ctl *ctl, void *arg) ctx->pp_timeout_report_cnt++; rc = -EPERM; - mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num); - mdss_mdp_set_intr_callback_nosync( - MDSS_MDP_IRQ_TYPE_PING_PONG_COMP, - ctx->current_pp_num, NULL, NULL); - if (atomic_add_unless(&ctx->koff_cnt, -1, 0) - && mdss_mdp_cmd_do_notifier(ctx)) - mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT); - + __clear_ping_pong_callback(ctl, ctx); } else { rc = 0; ctx->pp_timeout_report_cnt = 0; diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c index 4efa38093557..663d63092ebf 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c @@ -106,6 +106,9 @@ static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx, static void mdss_mdp_fetch_end_config(struct mdss_mdp_video_ctx *ctx, struct mdss_mdp_ctl *ctl); +static void mdss_mdp_video_timegen_flush(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_video_ctx *sctx); + static void early_wakeup_dfps_update_work(struct work_struct *work); static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable); @@ -411,6 +414,8 @@ static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl, struct mdss_mdp_video_ctx *ctx) { struct mdss_data_type *mdata = ctl->mdata; + struct mdss_mdp_ctl *sctl = NULL; + struct mdss_mdp_video_ctx *sctx = NULL; if (test_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map)) { struct mdss_panel_data *pdata = ctl->panel_data; @@ -435,6 +440,17 @@ static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl, mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_VTOTAL, avr_vtotal); + /* + * Make sure config goes through + */ + wmb(); + + sctl = mdss_mdp_get_split_ctl(ctl); + if (sctl) + sctx = (struct mdss_mdp_video_ctx *) + sctl->intf_ctx[MASTER_CTX]; + mdss_mdp_video_timegen_flush(ctl, ctx); + MDSS_XLOG(pinfo->min_fps, pinfo->default_fps, avr_vtotal); } } @@ -461,8 +477,9 @@ static int mdss_mdp_video_avr_trigger_setup(struct mdss_mdp_ctl *ctl) } static void mdss_mdp_video_avr_ctrl_setup(struct mdss_mdp_video_ctx *ctx, - struct mdss_mdp_avr_info *avr_info, bool is_master, bool enable) + struct mdss_mdp_ctl *ctl, bool is_master, bool enable) { + struct mdss_mdp_avr_info *avr_info = &ctl->avr_info; u32 avr_ctrl = 0; u32 avr_mode = 0; @@ -475,9 +492,18 @@ static void mdss_mdp_video_avr_ctrl_setup(struct mdss_mdp_video_ctx *ctx, if (avr_mode == MDSS_MDP_AVR_ONE_SHOT) avr_mode |= (1 << 8); - if (is_master) + if (is_master) { mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_CONTROL, avr_ctrl); + /* + * When AVR is enabled, need to setup DSI Video mode control + */ + mdss_mdp_ctl_intf_event(ctl, + MDSS_EVENT_AVR_MODE, + (void *)(unsigned long) avr_ctrl, + CTL_INTF_EVENT_FLAG_DEFAULT); + } + mdp_video_write(ctx, MDSS_MDP_REG_INTF_AVR_MODE, avr_mode); pr_debug("intf:%d avr_mode:%x avr_ctrl:%x\n", @@ -1435,7 +1461,6 @@ static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps) } mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON); - /* * Need to disable AVR during DFPS update period. * Next commit will restore the AVR settings. @@ -1844,6 +1869,7 @@ static void mdss_mdp_handoff_programmable_fetch(struct mdss_mdp_ctl *ctl, struct mdss_mdp_video_ctx *ctx) { struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info; + u32 fetch_start_handoff, v_total_handoff, h_total_handoff; pinfo->prg_fet = 0; if (mdp_video_read(ctx, MDSS_MDP_REG_INTF_CONFIG) & BIT(31)) { @@ -2269,7 +2295,7 @@ static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable) pr_err("invalid master ctx\n"); return -EINVAL; } - mdss_mdp_video_avr_ctrl_setup(ctx, &ctl->avr_info, ctl->is_master, + mdss_mdp_video_avr_ctrl_setup(ctx, ctl, ctl->is_master, enable); if (is_pingpong_split(ctl->mfd)) { @@ -2278,7 +2304,7 @@ static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable) pr_err("invalid slave ctx\n"); return -EINVAL; } - mdss_mdp_video_avr_ctrl_setup(sctx, &ctl->avr_info, false, + mdss_mdp_video_avr_ctrl_setup(sctx, ctl, false, enable); } diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c index e1d2a947a77f..5b284e624c7f 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c +++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c @@ -125,6 +125,48 @@ static inline void mdp_wb_write(struct mdss_mdp_writeback_ctx *ctx, writel_relaxed(val, ctx->base + reg); } +static void mdss_mdp_qos_vbif_remapper_setup_wb(struct mdss_mdp_ctl *ctl, + struct mdss_mdp_writeback_ctx *ctx) +{ + u32 mask, reg_val, reg_val_lvl, reg_high, i, vbif_qos; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + bool is_nrt_vbif = (ctl->mixer_left && ctl->mixer_left->rotator_mode); + + if (!mdata->vbif_nrt_qos) + return; + + if (test_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map)) { + mutex_lock(&mdata->reg_lock); + for (i = 0; i < mdata->npriority_lvl; i++) { + reg_high = ((ctx->xin_id & 0x8) >> 3) * 4 + (i * 8); + + reg_val = MDSS_VBIF_READ(mdata, + MDSS_VBIF_QOS_RP_REMAP_BASE + + reg_high, is_nrt_vbif); + reg_val_lvl = MDSS_VBIF_READ(mdata, + MDSS_VBIF_QOS_LVL_REMAP_BASE + reg_high, + is_nrt_vbif); + + mask = 0x3 << (ctx->xin_id * 4); + vbif_qos = mdata->vbif_nrt_qos[i]; + + reg_val &= ~(mask); + reg_val |= vbif_qos << (ctx->xin_id * 4); + + reg_val_lvl &= ~(mask); + reg_val_lvl |= vbif_qos << (ctx->xin_id * 4); + + pr_debug("idx:%d xin:%d reg:0x%x val:0x%x lvl:0x%x\n", + i, ctx->xin_id, reg_high, reg_val, reg_val_lvl); + MDSS_VBIF_WRITE(mdata, MDSS_VBIF_QOS_RP_REMAP_BASE + + reg_high, reg_val, is_nrt_vbif); + MDSS_VBIF_WRITE(mdata, MDSS_VBIF_QOS_LVL_REMAP_BASE + + reg_high, reg_val_lvl, is_nrt_vbif); + } + mutex_unlock(&mdata->reg_lock); + } +} + static void mdss_mdp_set_qos_wb(struct mdss_mdp_ctl *ctl, struct mdss_mdp_writeback_ctx *ctx) { @@ -133,12 +175,15 @@ static void mdss_mdp_set_qos_wb(struct mdss_mdp_ctl *ctl, struct mdss_overlay_private *mdp5_data; struct mdss_data_type *mdata = mdss_mdp_get_mdata(); - if (false == test_bit(MDSS_QOS_WB_QOS, mdata->mdss_qos_map)) - return; - mdp5_data = mfd_to_mdp5_data(ctl->mfd); cwb = &mdp5_data->cwb; + if (!cwb->valid) + mdss_mdp_qos_vbif_remapper_setup_wb(ctl, ctx); + + if (false == test_bit(MDSS_QOS_WB_QOS, mdata->mdss_qos_map)) + return; + if (cwb->valid) wb_qos_setup = QOS_LUT_CWB_READ; else diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 9864d611e8e4..c49f4f2a4ad6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -4495,8 +4495,10 @@ static int mdss_bl_scale_config(struct msm_fb_data_type *mfd, mfd->bl_scale = data->scale; pr_debug("update scale = %d\n", mfd->bl_scale); - /* update current backlight to use new scaling*/ - mdss_fb_set_backlight(mfd, curr_bl); + /* Update current backlight to use new scaling, if it is not zero */ + if (curr_bl) + mdss_fb_set_backlight(mfd, curr_bl); + mutex_unlock(&mfd->bl_lock); return ret; } diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c index 563cb8be1a04..bd41cb9e025c 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c @@ -1011,8 +1011,10 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, u32 mask, reg_val, reg_val_lvl, i, vbif_qos; u32 reg_high; bool is_nrt_vbif = mdss_mdp_is_nrt_vbif_client(mdata, pipe); + u32 *vbif_qos_ptr = is_realtime ? mdata->vbif_rt_qos : + mdata->vbif_nrt_qos; - if (mdata->npriority_lvl == 0) + if ((mdata->npriority_lvl == 0) || !vbif_qos_ptr) return; if (test_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map)) { @@ -1028,8 +1030,7 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, is_nrt_vbif); mask = 0x3 << (pipe->xin_id * 4); - vbif_qos = is_realtime ? - mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i]; + vbif_qos = vbif_qos_ptr[i]; reg_val &= ~(mask); reg_val |= vbif_qos << (pipe->xin_id * 4); @@ -1053,8 +1054,7 @@ static void mdss_mdp_qos_vbif_remapper_setup(struct mdss_data_type *mdata, mask = 0x3 << (pipe->xin_id * 2); reg_val &= ~(mask); - vbif_qos = is_realtime ? - mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i]; + vbif_qos = vbif_qos_ptr[i]; reg_val |= vbif_qos << (pipe->xin_id * 2); MDSS_VBIF_WRITE(mdata, MDSS_VBIF_QOS_REMAP_BASE + i*4, reg_val, is_nrt_vbif); diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h index 3fc5b2226b3e..d73416e311b5 100644 --- a/drivers/video/fbdev/msm/mdss_panel.h +++ b/drivers/video/fbdev/msm/mdss_panel.h @@ -265,6 +265,10 @@ struct mdss_intf_recovery { * Argument provided is bits per pixel (8/10/12) * @MDSS_EVENT_UPDATE_PANEL_PPM: update pixel clock by input PPM. * Argument provided is parts per million. + * @MDSS_EVENT_AVR_MODE: Setup DSI Video mode to support AVR based on the + * avr mode passed as argument + * 0 - disable AVR support + * 1 - enable AVR support */ enum mdss_intf_events { MDSS_EVENT_RESET = 1, @@ -299,6 +303,7 @@ enum mdss_intf_events { MDSS_EVENT_DISABLE_PANEL, MDSS_EVENT_UPDATE_PANEL_PPM, MDSS_EVENT_DSI_TIMING_DB_CTRL, + MDSS_EVENT_AVR_MODE, MDSS_EVENT_MAX, }; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 624a57a9c4aa..c6a499b7547e 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -275,11 +275,11 @@ loop: goto loop; end_loop: - write_unlock(&journal->j_state_lock); del_timer_sync(&journal->j_commit_timer); journal->j_task = NULL; wake_up(&journal->j_wait_done_commit); jbd_debug(1, "Journal thread exiting.\n"); + write_unlock(&journal->j_state_lock); return 0; } diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h index fad58671c49e..62acf17a894b 100644 --- a/include/linux/iio/consumer.h +++ b/include/linux/iio/consumer.h @@ -161,6 +161,16 @@ int iio_read_channel_processed(struct iio_channel *chan, int *val); int iio_write_channel_raw(struct iio_channel *chan, int val); /** + * iio_write_channel_processed() - write to a given channel + * @chan: The channel being queried. + * @val: Value being written. + * + * Note processed writes to iio channels are converted to raw + * values before being written. + */ +int iio_write_channel_processed(struct iio_channel *chan, int val); + +/** * iio_get_channel_type() - get the type of a channel * @channel: The channel being queried. * @type: The type of the channel. diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h index 44a04b5c2fcd..4378080da0d9 100644 --- a/include/linux/msm_ext_display.h +++ b/include/linux/msm_ext_display.h @@ -91,7 +91,7 @@ enum msm_ext_disp_power_state { /** * struct msm_ext_disp_intf_ops - operations exposed to display interface * @hpd: updates external display interface state - * @notify: updates audio framework with interface state + * @notify: acknowledgment to power on or off */ struct msm_ext_disp_intf_ops { int (*hpd)(struct platform_device *pdev, @@ -100,8 +100,7 @@ struct msm_ext_disp_intf_ops { u32 flags); int (*notify)(struct platform_device *pdev, enum msm_ext_disp_cable_state state); - int (*ack)(struct platform_device *pdev, - u32 ack); + int (*ack)(struct platform_device *pdev, u32 ack); }; /** diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index fb2607dd365b..6037fbf00a23 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1040,6 +1040,19 @@ int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, */ int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size); +/** + * gsi_get_inst_ram_offset_and_size - Peripheral should call this function + * to get instruction RAM base address offset and size. Peripheral typically + * uses this info to load GSI FW into the IRAM. + * + * @base_offset:[OUT] - IRAM base offset address + * @size: [OUT] - IRAM size + + * @Return none + */ +void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, + unsigned long *size); + /* * Here is a typical sequence of calls * @@ -1227,9 +1240,15 @@ static inline int gsi_configure_regs(phys_addr_t gsi_base_addr, u32 gsi_size, { return -GSI_STATUS_UNSUPPORTED_OP; } + static inline int gsi_enable_fw(phys_addr_t gsi_base_addr, u32 gsi_size) { return -GSI_STATUS_UNSUPPORTED_OP; } + +static inline void gsi_get_inst_ram_offset_and_size(unsigned long *base_offset, + unsigned long *size) +{ +} #endif #endif diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 8f95c91c059a..64f5c4ca09d5 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -237,6 +237,7 @@ enum power_supply_property { POWER_SUPPLY_PROP_FCC_DELTA, POWER_SUPPLY_PROP_ICL_REDUCTION, POWER_SUPPLY_PROP_PARALLEL_MODE, + POWER_SUPPLY_PROP_CONNECTOR_THERM_ZONE, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ diff --git a/include/linux/qdsp6v2/apr_tal.h b/include/linux/qdsp6v2/apr_tal.h index c2c49dd748de..bf324064960b 100644 --- a/include/linux/qdsp6v2/apr_tal.h +++ b/include/linux/qdsp6v2/apr_tal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2011, 2016-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -32,7 +32,6 @@ #if defined(CONFIG_MSM_QDSP6_APRV2_GLINK) || \ defined(CONFIG_MSM_QDSP6_APRV3_GLINK) #define APR_MAX_BUF 512 -#define APR_NUM_OF_TX_BUF 30 #else #define APR_MAX_BUF 8092 #endif diff --git a/include/linux/regulator/qpnp-regulator.h b/include/linux/regulator/qpnp-regulator.h index c7afeb50f244..36288c068ac3 100644 --- a/include/linux/regulator/qpnp-regulator.h +++ b/include/linux/regulator/qpnp-regulator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -158,8 +158,8 @@ enum qpnp_boost_current_limit { struct qpnp_regulator_platform_data { struct regulator_init_data init_data; int pull_down_enable; - unsigned pin_ctrl_enable; - unsigned pin_ctrl_hpm; + unsigned int pin_ctrl_enable; + unsigned int pin_ctrl_hpm; int system_load; int enable_time; int ocp_enable; diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 418eb97110a3..ef8a092251aa 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -45,6 +45,14 @@ extern unsigned int sysctl_sched_initial_task_util; extern unsigned int sysctl_sched_cstate_aware; #ifdef CONFIG_SCHED_HMP + +enum freq_reporting_policy { + FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK, + FREQ_REPORT_CPU_LOAD, + FREQ_REPORT_TOP_TASK, + FREQ_REPORT_INVALID_POLICY +}; + extern int sysctl_sched_freq_inc_notify; extern int sysctl_sched_freq_dec_notify; extern unsigned int sysctl_sched_freq_reporting_policy; diff --git a/include/linux/usb/xhci_pdriver.h b/include/linux/usb/xhci_pdriver.h index 376654b5b0f7..a44b53c33e75 100644 --- a/include/linux/usb/xhci_pdriver.h +++ b/include/linux/usb/xhci_pdriver.h @@ -19,9 +19,13 @@ * @usb3_lpm_capable: determines if this xhci platform supports USB3 * LPM capability * + * @imod_interval: minimum inter-interrupt interval. Specified in + * 250nsec increments. + * */ struct usb_xhci_pdata { unsigned usb3_lpm_capable:1; + unsigned imod_interval; }; #endif /* __USB_CORE_XHCI_PDRIVER_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index e5930177c96a..1ce3ea1fd917 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5474,6 +5474,21 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, void *data), void *data); +/* + * cfg80211_stop_iface - trigger interface disconnection + * + * @wiphy: the wiphy + * @wdev: wireless device + * @gfp: context flags + * + * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA + * disconnected. + * + * Note: This doesn't need any locks and is asynchronous. + */ +void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, + gfp_t gfp); + /** * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy * @wiphy: the wiphy to shut down diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index a047a33334d2..1f8bba7e9ab7 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -42,6 +42,8 @@ struct param_outband { #define ADM_MATRIX_ID_AUDIO_TX 1 #define ADM_MATRIX_ID_COMPRESSED_AUDIO_RX 2 + +#define ADM_MATRIX_ID_LISTEN_TX 4 /* Enumeration for an audio Tx matrix ID.*/ #define ADM_MATRIX_ID_AUDIOX 1 @@ -9044,6 +9046,7 @@ struct asm_aptx_dec_fmt_blk_v2 { #define LSM_SESSION_EVENT_DETECTION_STATUS_V2 (0x00012B01) #define LSM_DATA_EVENT_READ_DONE (0x00012B02) #define LSM_DATA_EVENT_STATUS (0x00012B03) +#define LSM_SESSION_EVENT_DETECTION_STATUS_V3 (0x00012B04) #define LSM_MODULE_ID_VOICE_WAKEUP (0x00012C00) #define LSM_PARAM_ID_ENDPOINT_DETECT_THRESHOLD (0x00012C01) @@ -9056,6 +9059,12 @@ struct asm_aptx_dec_fmt_blk_v2 { #define LSM_PARAM_ID_LAB_ENABLE (0x00012C09) #define LSM_PARAM_ID_LAB_CONFIG (0x00012C0A) #define LSM_MODULE_ID_FRAMEWORK (0x00012C0E) +#define LSM_PARAM_ID_SWMAD_CFG (0x00012C18) +#define LSM_PARAM_ID_SWMAD_MODEL (0x00012C19) +#define LSM_PARAM_ID_SWMAD_ENABLE (0x00012C1A) +#define LSM_PARAM_ID_POLLING_ENABLE (0x00012C1B) +#define LSM_PARAM_ID_MEDIA_FMT (0x00012C1E) +#define LSM_PARAM_ID_FWK_MODE_CONFIG (0x00012C27) /* HW MAD specific */ #define AFE_MODULE_HW_MAD (0x00010230) @@ -10172,6 +10181,7 @@ enum { COMPRESSED_PASSTHROUGH, COMPRESSED_PASSTHROUGH_CONVERT, COMPRESSED_PASSTHROUGH_DSD, + LISTEN, }; #define AUDPROC_MODULE_ID_COMPRESSED_MUTE 0x00010770 diff --git a/include/sound/cpe_core.h b/include/sound/cpe_core.h index 323a63fd6238..846cf819b9e5 100644 --- a/include/sound/cpe_core.h +++ b/include/sound/cpe_core.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -162,7 +162,7 @@ struct wcd_cpe_lsm_ops { int (*lsm_set_one_param)(void *core_handle, struct cpe_lsm_session *session, struct lsm_params_info *p_info, - void *data, enum LSM_PARAM_TYPE param_type); + void *data, uint32_t param_type); void (*lsm_get_snd_model_offset) (void *core_handle, struct cpe_lsm_session *, size_t *offset); diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index 8c7da3b9838d..25376315dd20 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -96,7 +96,7 @@ int adm_unmap_rtac_block(uint32_t *mem_map_handle); int adm_close(int port, int topology, int perf_mode); int adm_matrix_map(int path, struct route_payload payload_map, - int perf_mode); + int perf_mode, uint32_t passthr_mode); int adm_connect_afe_port(int mode, int session_id, int port_id); diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h index fb848bc70873..4805246766d6 100644 --- a/include/sound/q6lsm.h +++ b/include/sound/q6lsm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -21,6 +21,10 @@ #define MAX_NUM_CONFIDENCE 20 +#define ADM_LSM_PORT_ID 0xADCB + +#define LSM_MAX_NUM_CHANNELS 8 + typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv); @@ -49,11 +53,12 @@ struct lsm_lab_buffer { uint32_t mem_map_handle; }; -struct lsm_lab_hw_params { +struct lsm_hw_params { u16 sample_rate; u16 sample_size; u32 buf_sz; u32 period_count; + u16 num_chs; }; struct lsm_client { @@ -79,8 +84,12 @@ struct lsm_client { bool lab_enable; bool lab_started; struct lsm_lab_buffer *lab_buffer; - struct lsm_lab_hw_params hw_params; + struct lsm_hw_params hw_params; bool use_topology; + int session_state; + bool poll_enable; + int perf_mode; + uint32_t event_mode; }; struct lsm_stream_cmd_open_tx { @@ -134,6 +143,27 @@ struct lsm_param_connect_to_port { uint16_t reserved; } __packed; +struct lsm_param_poll_enable { + struct lsm_param_payload_common common; + uint32_t minor_version; + /* indicates to voice wakeup that HW MAD/SW polling is enabled or not */ + uint32_t polling_enable; +} __packed; + +struct lsm_param_fwk_mode_cfg { + struct lsm_param_payload_common common; + uint32_t minor_version; + uint32_t mode; +} __packed; + +struct lsm_param_media_fmt { + struct lsm_param_payload_common common; + uint32_t minor_version; + uint32_t sample_rate; + uint16_t num_channels; + uint16_t bit_width; + uint8_t channel_mapping[LSM_MAX_NUM_CHANNELS]; +} __packed; /* * This param cannot be sent in this format. @@ -163,11 +193,22 @@ struct lsm_cmd_set_params_conf { struct lsm_param_min_confidence_levels conf_payload; } __packed; -struct lsm_cmd_set_opmode_connectport { +struct lsm_cmd_set_params_opmode { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_op_mode op_mode; +} __packed; + +struct lsm_cmd_set_connectport { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_connect_to_port connect_to_port; +} __packed; + +struct lsm_cmd_poll_enable { struct apr_hdr msg_hdr; struct lsm_set_params_hdr params_hdr; - struct lsm_param_connect_to_port connect_to_port; - struct lsm_param_op_mode op_mode; + struct lsm_param_poll_enable poll_enable; } __packed; struct lsm_param_epd_thres { @@ -250,6 +291,19 @@ struct lsm_cmd_read_done { uint32_t flags; } __packed; +struct lsm_cmd_set_fwk_mode_cfg { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_fwk_mode_cfg fwk_mode_cfg; +} __packed; + +struct lsm_cmd_set_media_fmt { + struct apr_hdr msg_hdr; + struct lsm_set_params_hdr params_hdr; + struct lsm_param_media_fmt media_fmt; +} __packed; + + struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv); void q6lsm_client_free(struct lsm_client *client); int q6lsm_open(struct lsm_client *client, uint16_t app_id); @@ -274,8 +328,11 @@ int q6lsm_read(struct lsm_client *client, struct lsm_cmd_read *read); int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc); int q6lsm_set_one_param(struct lsm_client *client, struct lsm_params_info *p_info, void *data, - enum LSM_PARAM_TYPE param_type); + uint32_t param_type); void q6lsm_sm_set_param_data(struct lsm_client *client, struct lsm_params_info *p_info, size_t *offset); +int q6lsm_set_port_connected(struct lsm_client *client); +int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode); +int q6lsm_set_media_fmt_params(struct lsm_client *client); #endif /* __Q6LSM_H__ */ diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 8fdf57504ab6..c8653a9f0e9e 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -1058,6 +1058,9 @@ enum vl42_mpeg_vidc_video_h264_svc_nal { (V4L2_CID_MPEG_MSM_VIDC_BASE + 68) enum v4l2_mpeg_vidc_video_perf_mode { +#define V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT \ + V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT + V4L2_MPEG_VIDC_VIDEO_PERF_UNINIT = 0, V4L2_MPEG_VIDC_VIDEO_PERF_MAX_QUALITY = 1, V4L2_MPEG_VIDC_VIDEO_PERF_POWER_SAVE = 2 }; diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h index b259bdef8a93..e9370cb660b2 100644 --- a/include/uapi/media/msm_vidc.h +++ b/include/uapi/media/msm_vidc.h @@ -245,7 +245,7 @@ enum msm_vidc_extradata_type { MSM_VIDC_EXTRADATA_DIGITAL_ZOOM = 0x07000010, #define MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO \ MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO - MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x070000011, + MSM_VIDC_EXTRADATA_VPX_COLORSPACE_INFO = 0x00000014, MSM_VIDC_EXTRADATA_MULTISLICE_INFO = 0x7F100000, MSM_VIDC_EXTRADATA_NUM_CONCEALED_MB = 0x7F100001, MSM_VIDC_EXTRADATA_INDEX = 0x7F100002, diff --git a/include/uapi/sound/lsm_params.h b/include/uapi/sound/lsm_params.h index eafdc117413a..9ca5930475ba 100644 --- a/include/uapi/sound/lsm_params.h +++ b/include/uapi/sound/lsm_params.h @@ -1,6 +1,9 @@ #ifndef _UAPI_LSM_PARAMS_H__ #define _UAPI_LSM_PARAMS_H__ +#define LSM_POLLING_ENABLE_SUPPORT +#define LSM_EVENT_TIMESTAMP_MODE_SUPPORT + #include <linux/types.h> #include <sound/asound.h> @@ -18,6 +21,19 @@ #define LSM_OUT_TRANSFER_MODE_RT (0) #define LSM_OUT_TRANSFER_MODE_FTRT (1) +#define LSM_ENDPOINT_DETECT_THRESHOLD (0) +#define LSM_OPERATION_MODE (1) +#define LSM_GAIN (2) +#define LSM_MIN_CONFIDENCE_LEVELS (3) +#define LSM_REG_SND_MODEL (4) +#define LSM_DEREG_SND_MODEL (5) +#define LSM_CUSTOM_PARAMS (6) +#define LSM_POLLING_ENABLE (7) +#define LSM_PARAMS_MAX (LSM_POLLING_ENABLE + 1) + +#define LSM_EVENT_NON_TIME_STAMP_MODE (0) +#define LSM_EVENT_TIME_STAMP_MODE (1) + enum lsm_app_id { LSM_VOICE_WAKEUP_APP_ID = 1, LSM_VOICE_WAKEUP_APP_ID_V2 = 2, @@ -35,18 +51,6 @@ enum lsm_vw_status { LSM_VOICE_WAKEUP_STATUS_REJECTED }; -enum LSM_PARAM_TYPE { - LSM_ENDPOINT_DETECT_THRESHOLD = 0, - LSM_OPERATION_MODE, - LSM_GAIN, - LSM_MIN_CONFIDENCE_LEVELS, - LSM_REG_SND_MODEL, - LSM_DEREG_SND_MODEL, - LSM_CUSTOM_PARAMS, - /* driver ioctl will parse only so many params */ - LSM_PARAMS_MAX, -}; - /* * Data for LSM_ENDPOINT_DETECT_THRESHOLD param_type * @epd_begin: Begin threshold @@ -75,6 +79,14 @@ struct snd_lsm_gain { __u16 gain; }; +/* + * Data for LSM_POLLING_ENABLE param_type + * @poll_en: Polling enable or disable + */ +struct snd_lsm_poll_enable { + bool poll_en; +}; + struct snd_lsm_sound_model_v2 { __u8 __user *data; @@ -95,11 +107,20 @@ struct snd_lsm_event_status { __u8 payload[0]; }; +struct snd_lsm_event_status_v3 { + __u32 timestamp_lsw; + __u32 timestamp_msw; + __u16 status; + __u16 payload_size; + __u8 payload[0]; +}; + struct snd_lsm_detection_params { __u8 *conf_level; enum lsm_detection_mode detect_mode; __u8 num_confidence_levels; bool detect_failure; + bool poll_enable; }; /* @@ -122,7 +143,7 @@ struct lsm_params_info { __u32 param_id; __u32 param_size; __u8 __user *param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; /* @@ -171,5 +192,9 @@ struct snd_lsm_output_format_cfg { struct snd_lsm_module_params) #define SNDRV_LSM_OUT_FORMAT_CFG _IOW('U', 0x0C, \ struct snd_lsm_output_format_cfg) +#define SNDRV_LSM_SET_PORT _IO('U', 0x0D) +#define SNDRV_LSM_SET_FWK_MODE_CONFIG _IOW('U', 0x0E, uint32_t) +#define SNDRV_LSM_EVENT_STATUS_V3 _IOW('U', 0x0F, \ + struct snd_lsm_event_status_v3) #endif diff --git a/kernel/sched/boost.c b/kernel/sched/boost.c index fcfda385b74a..5bdd51b1e55e 100644 --- a/kernel/sched/boost.c +++ b/kernel/sched/boost.c @@ -156,9 +156,6 @@ void sched_boost_parse_dt(void) struct device_node *sn; const char *boost_policy; - if (!sched_enable_hmp) - return; - sn = of_find_node_by_path("/sched-hmp"); if (!sn) return; @@ -175,9 +172,6 @@ int sched_set_boost(int type) { int ret = 0; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&boost_mutex); if (verify_boost_params(sysctl_sched_boost, type)) @@ -197,9 +191,6 @@ int sched_boost_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; unsigned int old_val; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&boost_mutex); old_val = *data; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 672ed90fc879..3fcadbae663d 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3025,8 +3025,9 @@ void sched_exec(void) unsigned long flags; int dest_cpu, curr_cpu; - if (sched_enable_hmp) - return; +#ifdef CONFIG_SCHED_HMP + return; +#endif raw_spin_lock_irqsave(&p->pi_lock, flags); curr_cpu = task_cpu(p); @@ -8215,8 +8216,9 @@ void __init sched_init(void) int i, j; unsigned long alloc_size = 0, ptr; - if (sched_enable_hmp) - pr_info("HMP scheduling enabled.\n"); +#ifdef CONFIG_SCHED_HMP + pr_info("HMP scheduling enabled.\n"); +#endif BUG_ON(num_possible_cpus() > BITS_PER_LONG); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ac4c3f1d144a..6f68b0e19c4a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3332,9 +3332,9 @@ void _inc_hmp_sched_stats_fair(struct rq *rq, * inc/dec_nr_big_task and inc/dec_cumulative_runnable_avg called * from inc_cfs_rq_hmp_stats() have similar checks), we gain a bit on * efficiency by short-circuiting for_each_sched_entity() loop when - * !sched_enable_hmp || sched_disable_window_stats + * sched_disable_window_stats */ - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; for_each_sched_entity(se) { @@ -3357,7 +3357,7 @@ _dec_hmp_sched_stats_fair(struct rq *rq, struct task_struct *p, int change_cra) struct sched_entity *se = &p->se; /* See comment on efficiency in _inc_hmp_sched_stats_fair */ - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; for_each_sched_entity(se) { @@ -3482,8 +3482,7 @@ static inline int migration_needed(struct task_struct *p, int cpu) int nice; struct related_thread_group *grp; - if (!sched_enable_hmp || p->state != TASK_RUNNING || - p->nr_cpus_allowed == 1) + if (p->state != TASK_RUNNING || p->nr_cpus_allowed == 1) return 0; /* No need to migrate task that is about to be throttled */ @@ -7024,8 +7023,9 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f int want_affine = 0; int sync = wake_flags & WF_SYNC; - if (sched_enable_hmp) - return select_best_cpu(p, prev_cpu, 0, sync); +#ifdef CONFIG_SCHED_HMP + return select_best_cpu(p, prev_cpu, 0, sync); +#endif if (sd_flag & SD_BALANCE_WAKE) want_affine = (!wake_wide(p) && task_fits_max(p, cpu) && @@ -9313,8 +9313,9 @@ static struct rq *find_busiest_queue(struct lb_env *env, unsigned long busiest_load = 0, busiest_capacity = 1; int i; - if (sched_enable_hmp) - return find_busiest_queue_hmp(env, group); +#ifdef CONFIG_SCHED_HMP + return find_busiest_queue_hmp(env, group); +#endif for_each_cpu_and(i, sched_group_cpus(group), env->cpus) { unsigned long capacity, wl; @@ -10120,8 +10121,9 @@ static inline int find_new_ilb(int type) { int ilb; - if (sched_enable_hmp) - return find_new_hmp_ilb(type); +#ifdef CONFIG_SCHED_HMP + return find_new_hmp_ilb(type); +#endif ilb = cpumask_first(nohz.idle_cpus_mask); @@ -10496,8 +10498,9 @@ static inline int _nohz_kick_needed(struct rq *rq, int cpu, int *type) if (likely(!atomic_read(&nohz.nr_cpus))) return 0; - if (sched_enable_hmp) - return _nohz_kick_needed_hmp(rq, cpu, type); +#ifdef CONFIG_SCHED_HMP + return _nohz_kick_needed_hmp(rq, cpu, type); +#endif if (time_before(now, nohz.next_balance)) return 0; diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index 0a74c8d23552..6379de764236 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -615,19 +615,6 @@ int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb) return 0; } -int __init set_sched_enable_hmp(char *str) -{ - int enable_hmp = 0; - - get_option(&str, &enable_hmp); - - sched_enable_hmp = !!enable_hmp; - - return 0; -} - -early_param("sched_enable_hmp", set_sched_enable_hmp); - /* Clear any HMP scheduler related requests pending from or on cpu */ void clear_hmp_request(int cpu) { @@ -869,9 +856,6 @@ unsigned int max_task_load(void) return sched_ravg_window; } -/* Use this knob to turn on or off HMP-aware task placement logic */ -unsigned int __read_mostly sched_enable_hmp; - /* A cpu can no longer accommodate more tasks if: * * rq->nr_running > sysctl_sched_spill_nr_run || @@ -1244,7 +1228,7 @@ unlock: void inc_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; if (is_big_task(p)) @@ -1253,7 +1237,7 @@ void inc_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) void dec_nr_big_task(struct hmp_sched_stats *stats, struct task_struct *p) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; if (is_big_task(p)) @@ -1322,7 +1306,7 @@ void fixup_nr_big_tasks(struct hmp_sched_stats *stats, u64 new_task_load; u64 old_task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; old_task_load = scale_load_to_cpu(task_load(p), task_cpu(p)); @@ -1432,9 +1416,6 @@ int sched_window_update_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; unsigned int old_val; - if (!sched_enable_hmp) - return -EINVAL; - mutex_lock(&policy_mutex); old_val = *data; @@ -1470,9 +1451,6 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write, unsigned int *data = (unsigned int *)table->data; int update_task_count = 0; - if (!sched_enable_hmp) - return 0; - /* * The policy mutex is acquired with cpu_hotplug.lock * held from cpu_up()->cpufreq_governor_interactive()-> @@ -1749,9 +1727,6 @@ static int send_notification(struct rq *rq, int check_pred, int check_groups) int rc = 0; u64 group_load = 0, new_load = 0; - if (!sched_enable_hmp) - return 0; - if (check_pred) { u64 prev = rq->old_busy_time; u64 predicted = rq->hmp_stats.pred_demands_sum; @@ -2812,7 +2787,7 @@ static u64 update_task_demand(struct task_struct *p, struct rq *rq, } static inline void -update_task_burst(struct task_struct *p, struct rq *rq, int event, int runtime) +update_task_burst(struct task_struct *p, struct rq *rq, int event, u64 runtime) { /* * update_task_demand() has checks for idle task and @@ -2960,7 +2935,7 @@ void set_window_start(struct rq *rq) { static int sync_cpu_available; - if (rq->window_start || !sched_enable_hmp) + if (rq->window_start) return; if (!sync_cpu_available) { @@ -3133,7 +3108,7 @@ static inline u64 freq_policy_load(struct rq *rq, u64 load) case FREQ_REPORT_CPU_LOAD: break; default: - WARN_ON_ONCE(1); + break; } return load; @@ -3539,7 +3514,7 @@ void fixup_busy_time(struct task_struct *p, int new_cpu) bool new_task; struct related_thread_group *grp; - if (!sched_enable_hmp || (!p->on_rq && p->state != TASK_WAKING)) + if (!p->on_rq && p->state != TASK_WAKING) return; if (exiting_task(p)) { @@ -4246,9 +4221,6 @@ static int register_sched_callback(void) { int ret; - if (!sched_enable_hmp) - return 0; - ret = cpufreq_register_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 3fe00d6fa335..b72352bbd752 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1406,6 +1406,7 @@ static void yield_task_rt(struct rq *rq) #ifdef CONFIG_SMP static int find_lowest_rq(struct task_struct *task); +#ifdef CONFIG_SCHED_HMP static int select_task_rq_rt_hmp(struct task_struct *p, int cpu, int sd_flag, int flags) { @@ -1419,6 +1420,7 @@ select_task_rq_rt_hmp(struct task_struct *p, int cpu, int sd_flag, int flags) return cpu; } +#endif static int select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags) @@ -1426,8 +1428,9 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags) struct task_struct *curr; struct rq *rq; - if (sched_enable_hmp) - return select_task_rq_rt_hmp(p, cpu, sd_flag, flags); +#ifdef CONFIG_SCHED_HMP + return select_task_rq_rt_hmp(p, cpu, sd_flag, flags); +#endif /* For anything but wake ups, just return the task_cpu */ if (sd_flag != SD_BALANCE_WAKE && sd_flag != SD_BALANCE_FORK) @@ -1796,14 +1799,6 @@ static int find_lowest_rq_hmp(struct task_struct *task) return best_cpu; } - -#else /* CONFIG_SCHED_HMP */ - -static int find_lowest_rq_hmp(struct task_struct *task) -{ - return -1; -} - #endif /* CONFIG_SCHED_HMP */ static int find_lowest_rq(struct task_struct *task) @@ -1813,8 +1808,9 @@ static int find_lowest_rq(struct task_struct *task) int this_cpu = smp_processor_id(); int cpu = task_cpu(task); - if (sched_enable_hmp) - return find_lowest_rq_hmp(task); +#ifdef CONFIG_SCHED_HMP + return find_lowest_rq_hmp(task); +#endif /* Make sure the mask is initialized first */ if (unlikely(!lowest_mask)) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 3e2ef7b0df3e..360e298398fb 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1071,10 +1071,6 @@ enum sched_boost_policy { #define WINDOW_STATS_AVG 3 #define WINDOW_STATS_INVALID_POLICY 4 -#define FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK 0 -#define FREQ_REPORT_CPU_LOAD 1 -#define FREQ_REPORT_TOP_TASK 2 - #define SCHED_UPMIGRATE_MIN_NICE 15 #define EXITING_TASK_MARKER 0xdeaddead @@ -1085,7 +1081,6 @@ enum sched_boost_policy { extern struct mutex policy_mutex; extern unsigned int sched_ravg_window; extern unsigned int sched_disable_window_stats; -extern unsigned int sched_enable_hmp; extern unsigned int max_possible_freq; extern unsigned int min_max_freq; extern unsigned int pct_task_load(struct task_struct *p); @@ -1129,7 +1124,6 @@ extern void update_cluster_topology(void); extern void note_task_waking(struct task_struct *p, u64 wallclock); extern void set_task_last_switch_out(struct task_struct *p, u64 wallclock); extern void init_clusters(void); -extern int __init set_sched_enable_hmp(char *str); extern void reset_cpu_hmp_stats(int cpu, int reset_cra); extern unsigned int max_task_load(void); extern void sched_account_irqtime(int cpu, struct task_struct *curr, @@ -1259,7 +1253,7 @@ inc_cumulative_runnable_avg(struct hmp_sched_stats *stats, { u32 task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; task_load = sched_disable_window_stats ? 0 : p->ravg.demand; @@ -1274,7 +1268,7 @@ dec_cumulative_runnable_avg(struct hmp_sched_stats *stats, { u32 task_load; - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; task_load = sched_disable_window_stats ? 0 : p->ravg.demand; @@ -1292,7 +1286,7 @@ fixup_cumulative_runnable_avg(struct hmp_sched_stats *stats, struct task_struct *p, s64 task_load_delta, s64 pred_demand_delta) { - if (!sched_enable_hmp || sched_disable_window_stats) + if (sched_disable_window_stats) return; stats->cumulative_runnable_avg += task_load_delta; @@ -1661,7 +1655,6 @@ static inline int update_preferred_cluster(struct related_thread_group *grp, static inline void add_new_task_to_grp(struct task_struct *new) {} -#define sched_enable_hmp 0 #define PRED_DEMAND_DELTA (0) static inline void diff --git a/kernel/sysctl.c b/kernel/sysctl.c index a2a87c3ad44e..7112dc54d88e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -133,6 +133,7 @@ static int ten_thousand = 10000; #endif #ifdef CONFIG_SCHED_HMP static int one_thousand = 1000; +static int max_freq_reporting_policy = FREQ_REPORT_INVALID_POLICY - 1; #endif /* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */ @@ -297,6 +298,7 @@ static struct ctl_table kern_table[] = { .mode = 0644, .proc_handler = proc_dointvec_minmax, .extra1 = &zero, + .extra2 = &max_freq_reporting_policy, }, { .procname = "sched_freq_inc_notify", @@ -591,7 +593,8 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_time_avg, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &one, }, { .procname = "sched_shares_window_ns", diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 46e60923221f..6f7985e6f129 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -208,6 +208,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, u8 *data; bool pfmemalloc; + if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE)) + gfp_mask |= GFP_DMA; + cache = (flags & SKB_ALLOC_FCLONE) ? skbuff_fclone_cache : skbuff_head_cache; diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 800f1aff472f..00a43a70e1fc 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c @@ -132,7 +132,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_SUSPEND, false); - local->wowlan = false; + return err; } else { goto suspend; } diff --git a/net/wireless/ap.c b/net/wireless/ap.c index f09f5683cb30..91d02ac0f42f 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c @@ -6,8 +6,8 @@ #include "rdev-ops.h" -static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, - struct net_device *dev, bool notify) +int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, + struct net_device *dev, bool notify) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; diff --git a/net/wireless/core.c b/net/wireless/core.c index 14868e42f3ca..01d0c4eb06fc 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -927,6 +927,92 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, rdev->num_running_monitor_ifaces += num; } +void __cfg80211_leave(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev) +{ + struct net_device *dev = wdev->netdev; + struct cfg80211_sched_scan_request *sched_scan_req; + + ASSERT_RTNL(); + ASSERT_WDEV_LOCK(wdev); + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + __cfg80211_leave_ibss(rdev, dev, true); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + sched_scan_req = rtnl_dereference(rdev->sched_scan_req); + if (sched_scan_req && dev == sched_scan_req->dev) + __cfg80211_stop_sched_scan(rdev, false); +#ifdef CONFIG_CFG80211_WEXT + kfree(wdev->wext.ie); + wdev->wext.ie = NULL; + wdev->wext.ie_len = 0; + wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; +#endif + cfg80211_disconnect(rdev, dev, + WLAN_REASON_DEAUTH_LEAVING, true); + cfg80211_mlme_down(rdev, dev); + break; + case NL80211_IFTYPE_MESH_POINT: + __cfg80211_leave_mesh(rdev, dev); + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: + __cfg80211_stop_ap(rdev, dev, true); + break; + case NL80211_IFTYPE_OCB: + __cfg80211_leave_ocb(rdev, dev); + break; + case NL80211_IFTYPE_WDS: + /* must be handled by mac80211/driver, has no APIs */ + break; + case NL80211_IFTYPE_P2P_DEVICE: + /* cannot happen, has no netdev */ + break; + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_MONITOR: + /* nothing to do */ + break; + case NL80211_IFTYPE_UNSPECIFIED: + case NUM_NL80211_IFTYPES: + /* invalid */ + break; + } + wdev->beacon_interval = 0; +} + +void cfg80211_leave(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev) +{ + wdev_lock(wdev); + __cfg80211_leave(rdev, wdev); + wdev_unlock(wdev); +} + +void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev, + gfp_t gfp) +{ + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct cfg80211_event *ev; + unsigned long flags; + + trace_cfg80211_stop_iface(wiphy, wdev); + + ev = kzalloc(sizeof(*ev), gfp); + if (!ev) + return; + + ev->type = EVENT_STOPPED; + + spin_lock_irqsave(&wdev->event_lock, flags); + list_add_tail(&ev->list, &wdev->event_list); + spin_unlock_irqrestore(&wdev->event_lock, flags); + queue_work(cfg80211_wq, &rdev->event_work); +} +EXPORT_SYMBOL(cfg80211_stop_iface); + static int cfg80211_netdev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr) { @@ -988,40 +1074,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, dev->priv_flags |= IFF_DONT_BRIDGE; break; case NETDEV_GOING_DOWN: - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: - cfg80211_leave_ibss(rdev, dev, true); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_STATION: - ASSERT_RTNL(); - sched_scan_req = rtnl_dereference(rdev->sched_scan_req); - if (sched_scan_req && dev == sched_scan_req->dev) - __cfg80211_stop_sched_scan(rdev, false); - - wdev_lock(wdev); -#ifdef CONFIG_CFG80211_WEXT - kfree(wdev->wext.ie); - wdev->wext.ie = NULL; - wdev->wext.ie_len = 0; - wdev->wext.connect.auth_type = - NL80211_AUTHTYPE_AUTOMATIC; -#endif - cfg80211_disconnect(rdev, dev, - WLAN_REASON_DEAUTH_LEAVING, true); - cfg80211_mlme_down(rdev, dev); - wdev_unlock(wdev); - break; - case NL80211_IFTYPE_MESH_POINT: - cfg80211_leave_mesh(rdev, dev); - break; - case NL80211_IFTYPE_AP: - cfg80211_stop_ap(rdev, dev, false); - break; - default: - break; - } - wdev->beacon_interval = 0; + cfg80211_leave(rdev, wdev); break; case NETDEV_DOWN: cfg80211_update_iface_num(rdev, wdev->iftype, -1); diff --git a/net/wireless/core.h b/net/wireless/core.h index a06a1056f726..a972e386ad7f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -199,6 +199,7 @@ enum cfg80211_event_type { EVENT_ROAMED, EVENT_DISCONNECTED, EVENT_IBSS_JOINED, + EVENT_STOPPED, }; struct cfg80211_event { @@ -297,6 +298,8 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev, struct mesh_setup *setup, const struct mesh_config *conf); +int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, + struct net_device *dev); int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, struct net_device *dev); int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, @@ -316,6 +319,8 @@ int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev, struct net_device *dev); /* AP */ +int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, + struct net_device *dev, bool notify); int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, struct net_device *dev, bool notify); @@ -470,6 +475,11 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype, int num); +void __cfg80211_leave(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); +void cfg80211_leave(struct cfg80211_registered_device *rdev, + struct wireless_dev *wdev); + void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev); diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 929795af643f..092300b30c37 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -238,8 +238,8 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, return 0; } -static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, - struct net_device *dev) +int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, + struct net_device *dev) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index b3675ce67a8b..6bde2241bffa 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -6,11 +6,12 @@ #include "core.h" #include "trace.h" -static inline int rdev_suspend(struct cfg80211_registered_device *rdev) +static inline int rdev_suspend(struct cfg80211_registered_device *rdev, + struct cfg80211_wowlan *wowlan) { int ret; - trace_rdev_suspend(&rdev->wiphy, rdev->wiphy.wowlan_config); - ret = rdev->ops->suspend(&rdev->wiphy, rdev->wiphy.wowlan_config); + trace_rdev_suspend(&rdev->wiphy, wowlan); + ret = rdev->ops->suspend(&rdev->wiphy, wowlan); trace_rdev_return_int(&rdev->wiphy, ret); return ret; } diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 0178de1fc9aa..460c4b0e343c 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -94,12 +94,11 @@ static int wiphy_suspend(struct device *dev) rdev->suspend_at = get_seconds(); - if (rdev->ops->suspend) { - rtnl_lock(); - if (rdev->wiphy.registered) - ret = rdev_suspend(rdev); - rtnl_unlock(); - } + rtnl_lock(); + if (rdev->wiphy.registered) + if (rdev->ops->suspend) + ret = rdev_suspend(rdev, NULL); + rtnl_unlock(); return ret; } diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 500d72ac719a..b7bf5ba63555 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2827,6 +2827,22 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_abort_scan, TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), TP_ARGS(wiphy, wdev) ); + +TRACE_EVENT(cfg80211_stop_iface, + TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), + TP_ARGS(wiphy, wdev), + TP_STRUCT__entry( + WIPHY_ENTRY + WDEV_ENTRY + ), + TP_fast_assign( + WIPHY_ASSIGN; + WDEV_ASSIGN; + ), + TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, + WIPHY_PR_ARG, WDEV_PR_ARG) +); + #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH diff --git a/net/wireless/util.c b/net/wireless/util.c index ef394e8a42bc..dfd0766abd6f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -895,6 +895,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, ev->ij.channel); break; + case EVENT_STOPPED: + __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); + break; } wdev_unlock(wdev); @@ -1080,7 +1083,7 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 58500000, 65000000, 78000000, - 0, + 86500000, }, { 13500000, 27000000, diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 328b4a43f09a..b73133885384 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -375,7 +375,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, * the elapsed time to detect xruns. */ jdelta = curr_jiffies - runtime->hw_ptr_jiffies; - if (jdelta < runtime->hw_ptr_buffer_jiffies / 2) + if ((jdelta < runtime->hw_ptr_buffer_jiffies / 2) || + (runtime->hw_ptr_buffer_jiffies <= 0)) goto no_delta_check; hdelta = jdelta - delta * HZ / runtime->rate; xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1; diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c index 5c210dc2176e..df0bdf666ba1 100644 --- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c +++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c @@ -50,6 +50,9 @@ static unsigned long rx_digital_gain_reg[] = { static unsigned long tx_digital_gain_reg[] = { MSM89XX_CDC_CORE_TX1_VOL_CTL_GAIN, MSM89XX_CDC_CORE_TX2_VOL_CTL_GAIN, + MSM89XX_CDC_CORE_TX3_VOL_CTL_GAIN, + MSM89XX_CDC_CORE_TX4_VOL_CTL_GAIN, + MSM89XX_CDC_CORE_TX5_VOL_CTL_GAIN, }; static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0); @@ -729,6 +732,7 @@ static int msm_dig_cdc_hw_params(struct snd_pcm_substream *substream, MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x20); break; case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_3LE: snd_soc_update_bits(dai->codec, MSM89XX_CDC_CORE_CLK_RX_I2S_CTL, 0x20, 0x00); break; @@ -799,13 +803,8 @@ static int msm_dig_cdc_codec_enable_dmic(struct snd_soc_dapm_widget *w, dmic_clk_en, dmic_clk_en); } snd_soc_update_bits(codec, - MSM89XX_CDC_CORE_TX1_DMIC_CTL, 0x07, 0x02); - snd_soc_update_bits(codec, - MSM89XX_CDC_CORE_TX2_DMIC_CTL, 0x07, 0x02); - snd_soc_update_bits(codec, - MSM89XX_CDC_CORE_TX3_DMIC_CTL, 0x07, 0x02); - snd_soc_update_bits(codec, - MSM89XX_CDC_CORE_TX4_DMIC_CTL, 0x07, 0x02); + MSM89XX_CDC_CORE_TX1_DMIC_CTL + (dmic - 1) * 0x20, + 0x07, 0x02); break; case SND_SOC_DAPM_POST_PMD: (*dmic_clk_cnt)--; @@ -884,6 +883,10 @@ static int msm_dig_cdc_codec_enable_dec(struct snd_soc_dapm_widget *w, 32 * (decimator - 1); tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX1_MUX_CTL + 32 * (decimator - 1); + if (decimator == 5) { + tx_vol_ctl_reg = MSM89XX_CDC_CORE_TX5_VOL_CTL_CFG; + tx_mux_ctl_reg = MSM89XX_CDC_CORE_TX5_MUX_CTL; + } switch (event) { case SND_SOC_DAPM_PRE_PMU: @@ -1225,11 +1228,18 @@ static const struct snd_soc_dapm_route audio_dig_map[] = { {"I2S TX1", NULL, "DEC1 MUX"}, {"I2S TX2", NULL, "DEC2 MUX"}, - {"I2S TX3", NULL, "DEC3 MUX"}, - {"I2S TX4", NULL, "DEC4 MUX"}, + {"I2S TX3", NULL, "I2S TX2 INP1"}, + {"I2S TX4", NULL, "I2S TX2 INP2"}, {"I2S TX5", NULL, "DEC3 MUX"}, - {"I2S TX6", NULL, "DEC4 MUX"}, - {"I2S TX6", NULL, "DEC5 MUX"}, + {"I2S TX6", NULL, "I2S TX3 INP2"}, + + {"I2S TX2 INP1", "RX_MIX1", "RX1 MIX2"}, + {"I2S TX2 INP1", "DEC3", "DEC3 MUX"}, + {"I2S TX2 INP2", "RX_MIX2", "RX2 MIX2"}, + {"I2S TX2 INP2", "RX_MIX3", "RX3 MIX1"}, + {"I2S TX2 INP2", "DEC4", "DEC4 MUX"}, + {"I2S TX3 INP2", "DEC4", "DEC4 MUX"}, + {"I2S TX3 INP2", "DEC5", "DEC5 MUX"}, {"PDM_OUT_RX1", NULL, "RX1 CHAIN"}, {"PDM_OUT_RX2", NULL, "RX2 CHAIN"}, @@ -1350,6 +1360,19 @@ static const struct snd_soc_dapm_route audio_dig_map[] = { {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"}, }; + +static const char * const i2s_tx2_inp1_text[] = { + "ZERO", "RX_MIX1", "DEC3" +}; + +static const char * const i2s_tx2_inp2_text[] = { + "ZERO", "RX_MIX2", "RX_MIX3", "DEC4" +}; + +static const char * const i2s_tx3_inp2_text[] = { + "DEC4", "DEC5" +}; + static const char * const rx_mix1_text[] = { "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3" }; @@ -1365,6 +1388,20 @@ static const char * const dec_mux_text[] = { static const char * const iir_inp1_text[] = { "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3", "DEC3", "DEC4" }; + +/* I2S TX MUXes */ +static const struct soc_enum i2s_tx2_inp1_chain_enum = + SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL, + 2, 3, i2s_tx2_inp1_text); + +static const struct soc_enum i2s_tx2_inp2_chain_enum = + SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL, + 0, 4, i2s_tx2_inp2_text); + +static const struct soc_enum i2s_tx3_inp2_chain_enum = + SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_TX_I2S_SD1_CTL, + 4, 2, i2s_tx3_inp2_text); + /* RX1 MIX1 */ static const struct soc_enum rx_mix1_inp1_chain_enum = SOC_ENUM_SINGLE(MSM89XX_CDC_CORE_CONN_RX1_B1_CTL, @@ -1482,6 +1519,15 @@ static const struct snd_kcontrol_new dec4_mux = static const struct snd_kcontrol_new decsva_mux = MSM89XX_DEC_ENUM("DEC5 MUX Mux", decsva_mux_enum); +static const struct snd_kcontrol_new i2s_tx2_inp1_mux = + SOC_DAPM_ENUM("I2S TX2 INP1 Mux", i2s_tx2_inp1_chain_enum); + +static const struct snd_kcontrol_new i2s_tx2_inp2_mux = + SOC_DAPM_ENUM("I2S TX2 INP2 Mux", i2s_tx2_inp2_chain_enum); + +static const struct snd_kcontrol_new i2s_tx3_inp2_mux = + SOC_DAPM_ENUM("I2S TX3 INP2 Mux", i2s_tx3_inp2_chain_enum); + static const struct snd_kcontrol_new iir1_inp1_mux = SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum); @@ -1623,6 +1669,14 @@ static const struct snd_soc_dapm_widget msm_dig_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", MSM89XX_CDC_CORE_CLK_TX_I2S_CTL, 4, 0, NULL, 0), + + SND_SOC_DAPM_MUX("I2S TX2 INP1", SND_SOC_NOPM, 0, 0, + &i2s_tx2_inp1_mux), + SND_SOC_DAPM_MUX("I2S TX2 INP2", SND_SOC_NOPM, 0, 0, + &i2s_tx2_inp2_mux), + SND_SOC_DAPM_MUX("I2S TX3 INP2", SND_SOC_NOPM, 0, 0, + &i2s_tx3_inp2_mux), + /* Digital Mic Inputs */ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0, msm_dig_cdc_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU | diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c index f51301d1ab08..71a2052f1089 100644 --- a/sound/soc/codecs/wcd-dsp-mgr.c +++ b/sound/soc/codecs/wcd-dsp-mgr.c @@ -1,5 +1,4 @@ -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -881,12 +880,50 @@ done: static int wdsp_suspend(struct device *wdsp_dev) { - return 0; + struct wdsp_mgr_priv *wdsp; + int rc = 0, i; + + if (!wdsp_dev) { + pr_err("%s: Invalid handle to device\n", __func__); + return -EINVAL; + } + + wdsp = dev_get_drvdata(wdsp_dev); + + for (i = WDSP_CMPNT_TYPE_MAX - 1; i >= 0; i--) { + rc = wdsp_unicast_event(wdsp, i, WDSP_EVENT_SUSPEND, NULL); + if (rc < 0) { + WDSP_ERR(wdsp, "component %s failed to suspend\n", + WDSP_GET_CMPNT_TYPE_STR(i)); + break; + } + } + + return rc; } static int wdsp_resume(struct device *wdsp_dev) { - return 0; + struct wdsp_mgr_priv *wdsp; + int rc = 0, i; + + if (!wdsp_dev) { + pr_err("%s: Invalid handle to device\n", __func__); + return -EINVAL; + } + + wdsp = dev_get_drvdata(wdsp_dev); + + for (i = 0; i < WDSP_CMPNT_TYPE_MAX; i++) { + rc = wdsp_unicast_event(wdsp, i, WDSP_EVENT_RESUME, NULL); + if (rc < 0) { + WDSP_ERR(wdsp, "component %s failed to resume\n", + WDSP_GET_CMPNT_TYPE_STR(i)); + break; + } + } + + return rc; } static struct wdsp_mgr_ops wdsp_ops = { diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index cb201899b4b8..8454ebfc6216 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1610,12 +1610,8 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0); wcd_mbhc_report_plug(mbhc, 0, SND_JACK_LINEOUT); } else if (mbhc->current_plug == MBHC_PLUG_TYPE_ANC_HEADPHONE) { - mbhc->mbhc_cb->irq_control(codec, - mbhc->intr_ids->mbhc_hs_rem_intr, - false); - mbhc->mbhc_cb->irq_control(codec, - mbhc->intr_ids->mbhc_hs_ins_intr, - false); + wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM, false); + wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 0); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0); diff --git a/sound/soc/codecs/wcd-spi.c b/sound/soc/codecs/wcd-spi.c index 614410c26a91..b03a8a9caed7 100644 --- a/sound/soc/codecs/wcd-spi.c +++ b/sound/soc/codecs/wcd-spi.c @@ -1,5 +1,4 @@ -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -60,7 +59,8 @@ /* Command delays */ #define WCD_SPI_CLKREQ_DELAY_USECS (500) -#define WCD_SPI_CLK_OFF_TIMER_MS (3000) +#define WCD_SPI_CLK_OFF_TIMER_MS (500) +#define WCD_SPI_RESUME_TIMEOUT_MS 100 /* Command masks */ #define WCD_CMD_ADDR_MASK \ @@ -90,6 +90,7 @@ /* Status mask bits */ #define WCD_SPI_CLK_STATE_ENABLED BIT(0) +#define WCD_SPI_IS_SUSPENDED BIT(1) /* Locking related */ #define WCD_SPI_MUTEX_LOCK(spi, lock) \ @@ -144,6 +145,9 @@ struct wcd_spi_priv { /* Debugfs related information */ struct wcd_spi_debug_data debug_data; + + /* Completion object to indicate system resume completion */ + struct completion resume_comp; }; enum xfer_request { @@ -170,6 +174,55 @@ static void wcd_spi_reinit_xfer(struct spi_transfer *xfer) xfer->len = 0; } +static bool wcd_spi_is_suspended(struct wcd_spi_priv *wcd_spi) +{ + return test_bit(WCD_SPI_IS_SUSPENDED, &wcd_spi->status_mask); +} + +static bool wcd_spi_can_suspend(struct wcd_spi_priv *wcd_spi) +{ + struct spi_device *spi = wcd_spi->spi; + + if (wcd_spi->clk_users > 0 || + test_bit(WCD_SPI_CLK_STATE_ENABLED, &wcd_spi->status_mask)) { + dev_err(&spi->dev, "%s: cannot suspend, clk_users = %d\n", + __func__, wcd_spi->clk_users); + return false; + } + + return true; +} + +static int wcd_spi_wait_for_resume(struct wcd_spi_priv *wcd_spi) +{ + struct spi_device *spi = wcd_spi->spi; + int rc = 0; + + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + /* If the system is already in resumed state, return right away */ + if (!wcd_spi_is_suspended(wcd_spi)) + goto done; + + /* If suspended then wait for resume to happen */ + reinit_completion(&wcd_spi->resume_comp); + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + rc = wait_for_completion_timeout(&wcd_spi->resume_comp, + msecs_to_jiffies(WCD_SPI_RESUME_TIMEOUT_MS)); + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + if (rc == 0) { + dev_err(&spi->dev, "%s: failed to resume in %u msec\n", + __func__, WCD_SPI_RESUME_TIMEOUT_MS); + rc = -EIO; + goto done; + } + + dev_dbg(&spi->dev, "%s: resume successful\n", __func__); + rc = 0; +done: + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + return rc; +} + static int wcd_spi_read_single(struct spi_device *spi, u32 remote_addr, u32 *val) { @@ -579,6 +632,18 @@ static int wcd_spi_clk_ctrl(struct spi_device *spi, } if (request == WCD_SPI_CLK_ENABLE) { + /* + * If the SPI bus is suspended, then return error + * as the transaction cannot be completed. + */ + if (wcd_spi_is_suspended(wcd_spi)) { + dev_err(&spi->dev, + "%s: SPI suspended, cannot enable clk\n", + __func__); + ret = -EIO; + goto done; + } + /* Cancel the disable clk work */ WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); cancel_delayed_work_sync(&wcd_spi->clk_dwork); @@ -899,6 +964,17 @@ static int wdsp_spi_event_handler(struct device *dev, void *priv_data, ret = wdsp_spi_read_section(spi, data); break; + case WDSP_EVENT_SUSPEND: + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + if (!wcd_spi_can_suspend(wcd_spi)) + ret = -EBUSY; + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + break; + + case WDSP_EVENT_RESUME: + ret = wcd_spi_wait_for_resume(wcd_spi); + break; + default: dev_dbg(&spi->dev, "%s: Unhandled event %d\n", __func__, event); @@ -1303,6 +1379,7 @@ static int wcd_spi_probe(struct spi_device *spi) mutex_init(&wcd_spi->clk_mutex); mutex_init(&wcd_spi->xfer_mutex); INIT_DELAYED_WORK(&wcd_spi->clk_dwork, wcd_spi_clk_work); + init_completion(&wcd_spi->resume_comp); wcd_spi->spi = spi; spi_set_drvdata(spi, wcd_spi); @@ -1340,6 +1417,61 @@ static int wcd_spi_remove(struct spi_device *spi) return 0; } +#ifdef CONFIG_PM +static int wcd_spi_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); + int rc = 0; + + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + if (!wcd_spi_can_suspend(wcd_spi)) { + rc = -EBUSY; + goto done; + } + + /* + * If we are here, it is okay to let the suspend go + * through for this driver. But, still need to notify + * the master to make sure all other components can suspend + * as well. + */ + if (wcd_spi->m_dev && wcd_spi->m_ops && + wcd_spi->m_ops->suspend) { + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + rc = wcd_spi->m_ops->suspend(wcd_spi->m_dev); + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + } + + if (rc == 0) + set_bit(WCD_SPI_IS_SUSPENDED, &wcd_spi->status_mask); + else + dev_dbg(&spi->dev, "%s: cannot suspend, err = %d\n", + __func__, rc); +done: + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + return rc; +} + +static int wcd_spi_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); + + WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); + clear_bit(WCD_SPI_IS_SUSPENDED, &wcd_spi->status_mask); + complete(&wcd_spi->resume_comp); + WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); + + return 0; +} + +static const struct dev_pm_ops wcd_spi_pm_ops = { + .suspend = wcd_spi_suspend, + .resume = wcd_spi_resume, +}; +#endif + static const struct of_device_id wcd_spi_of_match[] = { { .compatible = "qcom,wcd-spi-v2", }, { } @@ -1350,6 +1482,9 @@ static struct spi_driver wcd_spi_driver = { .driver = { .name = "wcd-spi-v2", .of_match_table = wcd_spi_of_match, +#ifdef CONFIG_PM + .pm = &wcd_spi_pm_ops, +#endif }, .probe = wcd_spi_probe, .remove = wcd_spi_remove, diff --git a/sound/soc/codecs/wcd934x/wcd934x-routing.h b/sound/soc/codecs/wcd934x/wcd934x-routing.h index 8ca4c07a3327..cd165af43eab 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-routing.h +++ b/sound/soc/codecs/wcd934x/wcd934x-routing.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -914,9 +914,23 @@ const struct snd_soc_dapm_route tavil_audio_map[] = { {"ANC OUT EAR Enable", "Switch", "ADC MUX11"}, {"RX INT0 MIX2", NULL, "ANC OUT EAR Enable"}, + {"ANC OUT HPHL Enable", "Switch", "ADC MUX10"}, + {"ANC OUT HPHL Enable", "Switch", "ADC MUX11"}, + {"RX INT1 MIX2", NULL, "ANC OUT HPHL Enable"}, + + {"ANC OUT HPHR Enable", "Switch", "ADC MUX12"}, + {"ANC OUT HPHR Enable", "Switch", "ADC MUX13"}, + {"RX INT2 MIX2", NULL, "ANC OUT HPHR Enable"}, + {"ANC EAR PA", NULL, "RX INT0 DAC"}, {"ANC EAR", NULL, "ANC EAR PA"}, + {"ANC HPHL PA", NULL, "RX INT1 DAC"}, + {"ANC HPHL", NULL, "ANC HPHL PA"}, + + {"ANC HPHR PA", NULL, "RX INT2 DAC"}, + {"ANC HPHR", NULL, "ANC HPHR PA"}, + {"ANC OUT EAR SPKR Enable", "Switch", "ADC MUX10"}, {"ANC OUT EAR SPKR Enable", "Switch", "ADC MUX11"}, {"RX INT7 MIX2", NULL, "ANC OUT EAR SPKR Enable"}, diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index c5d2b1ce8151..5b300a668489 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -176,6 +176,10 @@ enum { AUDIO_NOMINAL, HPH_PA_DELAY, CLSH_Z_CONFIG, + ANC_MIC_AMIC1, + ANC_MIC_AMIC2, + ANC_MIC_AMIC3, + ANC_MIC_AMIC4, }; enum { @@ -510,6 +514,7 @@ module_param(tx_unmute_delay, int, S_IRUGO | S_IWUSR | S_IWGRP); MODULE_PARM_DESC(tx_unmute_delay, "delay to unmute the tx path"); +static void tavil_codec_set_tx_hold(struct snd_soc_codec *, u16, bool); /* Hold instance to soundwire platform device */ struct tavil_swr_ctrl_data { @@ -998,14 +1003,30 @@ static int tavil_put_anc_func(struct snd_kcontrol *kcontrol, snd_soc_dapm_enable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_enable_pin(dapm, "ANC EAR"); snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_enable_pin(dapm, "ANC HPHR"); snd_soc_dapm_disable_pin(dapm, "EAR PA"); snd_soc_dapm_disable_pin(dapm, "EAR"); + snd_soc_dapm_disable_pin(dapm, "HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "HPHL"); + snd_soc_dapm_disable_pin(dapm, "HPHR"); } else { snd_soc_dapm_disable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_disable_pin(dapm, "ANC EAR"); snd_soc_dapm_disable_pin(dapm, "ANC SPK1 PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR"); snd_soc_dapm_enable_pin(dapm, "EAR PA"); snd_soc_dapm_enable_pin(dapm, "EAR"); + snd_soc_dapm_enable_pin(dapm, "HPHL"); + snd_soc_dapm_enable_pin(dapm, "HPHR"); + snd_soc_dapm_enable_pin(dapm, "HPHL PA"); + snd_soc_dapm_enable_pin(dapm, "HPHR PA"); } mutex_unlock(&tavil->codec_mutex); @@ -1122,16 +1143,56 @@ static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w, } /* Rate converter clk enable and set bypass mode */ - snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL, - 0x05, 0x05); + if (!strcmp(w->name, "RX INT0 DAC") || + !strcmp(w->name, "RX INT1 DAC") || + !strcmp(w->name, "ANC SPK1 PA")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_RC_COMMON_CTL, + 0x05, 0x05); + if (!strcmp(w->name, "RX INT1 DAC")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_FIFO_COMMON_CTL, + 0x66, 0x66); + } + } else if (!strcmp(w->name, "RX INT2 DAC")) { + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_RC_COMMON_CTL, + 0x05, 0x05); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_FIFO_COMMON_CTL, + 0x66, 0x66); + } + if (!strcmp(w->name, "RX INT1 DAC")) + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08); + else if (!strcmp(w->name, "RX INT2 DAC")) + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08); + if (!hwdep_cal) release_firmware(fw); break; + + case SND_SOC_DAPM_POST_PMU: + if (!strcmp(w->name, "ANC HPHL PA") || + !strcmp(w->name, "ANC HPHR PA")) { + /* Remove ANC Rx from reset */ + snd_soc_update_bits(codec, + WCD934X_CDC_ANC0_CLK_RESET_CTL, + 0x08, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x08, 0x00); + } + + break; + case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WCD934X_CDC_ANC0_RC_COMMON_CTL, 0x05, 0x00); if (!strcmp(w->name, "ANC EAR PA") || - !strcmp(w->name, "ANC SPK1 PA")) { + !strcmp(w->name, "ANC SPK1 PA") || + !strcmp(w->name, "ANC HPHL PA")) { snd_soc_update_bits(codec, WCD934X_CDC_ANC0_MODE_1_CTL, 0x30, 0x00); msleep(50); @@ -1146,6 +1207,21 @@ static int tavil_codec_enable_anc(struct snd_soc_dapm_widget *w, snd_soc_update_bits(codec, WCD934X_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x00); + } else if (!strcmp(w->name, "ANC HPHR PA")) { + snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL, + 0x30, 0x00); + msleep(50); + snd_soc_update_bits(codec, WCD934X_CDC_ANC1_MODE_1_CTL, + 0x01, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x38, 0x38); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x07, 0x00); + snd_soc_update_bits(codec, + WCD934X_CDC_ANC1_CLK_RESET_CTL, + 0x38, 0x00); } break; } @@ -1893,6 +1969,18 @@ static void tavil_codec_override(struct snd_soc_codec *codec, int mode, } } +static void tavil_codec_clear_anc_tx_hold(struct tavil_priv *tavil) +{ + if (test_and_clear_bit(ANC_MIC_AMIC1, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC1, false); + if (test_and_clear_bit(ANC_MIC_AMIC2, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC2, false); + if (test_and_clear_bit(ANC_MIC_AMIC3, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC3, false); + if (test_and_clear_bit(ANC_MIC_AMIC4, &tavil->status_mask)) + tavil_codec_set_tx_hold(tavil->codec, WCD934X_ANA_AMIC4, false); +} + static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -1900,6 +1988,7 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -1908,6 +1997,11 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, (0x03 << 1)); + + if ((!(strcmp(w->name, "ANC HPHR PA"))) && + (test_bit(HPH_PA_DELAY, &tavil->status_mask))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0xC0, 0xC0); + set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) { @@ -1917,6 +2011,16 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: + if ((!(strcmp(w->name, "ANC HPHR PA")))) { + if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0) + != 0xC0) + /* + * If PA_EN is not set (potentially in ANC case) + * then do nothing for POST_PMU and let left + * channel handle everything. + */ + break; + } /* * 7ms sleep is required after PA is enabled as per * HW requirement. If compander is disabled, then @@ -1929,6 +2033,12 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &tavil->status_mask); } + if (tavil->anc_func) { + /* Clear Tx FE HOLD if both PAs are enabled */ + if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) & + 0xC0) == 0xC0) + tavil_codec_clear_anc_tx_hold(tavil); + } snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, 0x01, 0x01); @@ -1951,6 +2061,34 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, (snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2, 0x04, 0x00); + if (!(strcmp(w->name, "ANC HPHR PA"))) { + pr_debug("%s:Do everything needed for left channel\n", + __func__); + /* Do everything needed for left channel */ + snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, + 0x01, 0x01); + + /* Remove mute */ + snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL, + 0x10, 0x00); + + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_MIX_CTL, + 0x10, 0x00); + + if (dsd_conf && (snd_soc_read(codec, + WCD934X_CDC_DSD0_PATH_CTL) & + 0x01)) + snd_soc_update_bits(codec, + WCD934X_CDC_DSD0_CFG2, + 0x04, 0x00); + /* Remove ANC Rx from reset */ + ret = tavil_codec_enable_anc(w, kcontrol, event); + } tavil_codec_override(codec, tavil->hph_mode, event); break; case SND_SOC_DAPM_PRE_PMD: @@ -1967,6 +2105,8 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, 0x10, 0x10); snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_MIX_CTL, 0x10, 0x10); + if (!(strcmp(w->name, "ANC HPHR PA"))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, 0x40, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* @@ -1984,10 +2124,16 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x0); + if (!(strcmp(w->name, "ANC HPHR PA"))) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_CFG0, + 0x10, 0x00); + } break; }; - return 0; + return ret; } static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, @@ -1997,6 +2143,7 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event); @@ -2005,6 +2152,10 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, (0x03 << 1)); + if ((!(strcmp(w->name, "ANC HPHL PA"))) && + (test_bit(HPH_PA_DELAY, &tavil->status_mask))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, + 0xC0, 0xC0); set_bit(HPH_PA_DELAY, &tavil->status_mask); if (dsd_conf && (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) { @@ -2014,6 +2165,16 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, } break; case SND_SOC_DAPM_POST_PMU: + if (!(strcmp(w->name, "ANC HPHL PA"))) { + if ((snd_soc_read(codec, WCD934X_ANA_HPH) & 0xC0) + != 0xC0) + /* + * If PA_EN is not set (potentially in ANC + * case) then do nothing for POST_PMU and + * let right channel handle everything. + */ + break; + } /* * 7ms sleep is required after PA is enabled as per * HW requirement. If compander is disabled, then @@ -2026,6 +2187,13 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, usleep_range(7000, 7100); clear_bit(HPH_PA_DELAY, &tavil->status_mask); } + if (tavil->anc_func) { + /* Clear Tx FE HOLD if both PAs are enabled */ + if ((snd_soc_read(tavil->codec, WCD934X_ANA_HPH) & + 0xC0) == 0xC0) + tavil_codec_clear_anc_tx_hold(tavil); + } + snd_soc_update_bits(codec, WCD934X_HPH_L_TEST, 0x01, 0x01); /* Remove Mute on primary path */ snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL, @@ -2046,6 +2214,33 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, (snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01)) snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2, 0x04, 0x00); + if (!(strcmp(w->name, "ANC HPHL PA"))) { + pr_debug("%s:Do everything needed for right channel\n", + __func__); + + /* Do everything needed for right channel */ + snd_soc_update_bits(codec, WCD934X_HPH_R_TEST, + 0x01, 0x01); + + /* Remove mute */ + snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL, + 0x10, 0x00); + + /* Remove mix path mute if it is enabled */ + if ((snd_soc_read(codec, + WCD934X_CDC_RX2_RX_PATH_MIX_CTL)) & + 0x10) + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_MIX_CTL, + 0x10, 0x00); + if (dsd_conf && (snd_soc_read(codec, + WCD934X_CDC_DSD1_PATH_CTL) & 0x01)) + snd_soc_update_bits(codec, + WCD934X_CDC_DSD1_CFG2, + 0x04, 0x00); + /* Remove ANC Rx from reset */ + ret = tavil_codec_enable_anc(w, kcontrol, event); + } tavil_codec_override(codec, tavil->hph_mode, event); break; case SND_SOC_DAPM_PRE_PMD: @@ -2063,6 +2258,9 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, 0x10, 0x10); snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL, 0x10, 0x10); + if (!(strcmp(w->name, "ANC HPHL PA"))) + snd_soc_update_bits(codec, WCD934X_ANA_HPH, + 0x80, 0x00); break; case SND_SOC_DAPM_POST_PMD: /* @@ -2080,10 +2278,15 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w, if (TAVIL_IS_1_0(tavil->wcd9xxx)) snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL, 0x06, 0x0); + if (!(strcmp(w->name, "ANC HPHL PA"))) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_CFG0, 0x10, 0x00); + } break; }; - return 0; + return ret; } static int tavil_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w, @@ -2190,12 +2393,18 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, int hph_mode = tavil->hph_mode; u8 dem_inp; struct tavil_dsd_config *dsd_conf = tavil->dsd_config; + int ret = 0; dev_dbg(codec->dev, "%s wname: %s event: %d hph_mode: %d\n", __func__, w->name, event, hph_mode); switch (event) { case SND_SOC_DAPM_PRE_PMU: + if (tavil->anc_func) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + /* 40 msec delay is needed to avoid click and pop */ + msleep(40); + } /* Read DEM INP Select */ dem_inp = snd_soc_read(codec, WCD934X_CDC_RX2_RX_PATH_SEC0) & 0x03; @@ -2226,6 +2435,10 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, WCD_CLSH_EVENT_PRE_DAC, WCD_CLSH_STATE_HPHR, hph_mode); + if (tavil->anc_func) + snd_soc_update_bits(codec, + WCD934X_CDC_RX2_RX_PATH_CFG0, + 0x10, 0x10); break; case SND_SOC_DAPM_POST_PMD: /* 1000us required as per HW requirement */ @@ -2269,6 +2482,11 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: + if (tavil->anc_func) { + ret = tavil_codec_enable_anc(w, kcontrol, event); + /* 40 msec delay is needed to avoid click and pop */ + msleep(40); + } /* Read DEM INP Select */ dem_inp = snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_SEC0) & 0x03; @@ -2300,6 +2518,11 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, WCD_CLSH_STATE_HPHL, hph_mode); + if (tavil->anc_func) + snd_soc_update_bits(codec, + WCD934X_CDC_RX1_RX_PATH_CFG0, + 0x10, 0x10); + ret = tavil_mbhc_get_impedance(tavil->mbhc, &impedl, &impedr); if (!ret) { @@ -3184,6 +3407,15 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec, } EXPORT_SYMBOL(tavil_codec_enable_interp_clk); +static int tavil_anc_out_switch_cb(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + + tavil_codec_enable_interp_clk(codec, event, w->shift); + + return 0; +} static int tavil_codec_set_idle_detect_thr(struct snd_soc_codec *codec, int interp, int path_type) { @@ -3638,8 +3870,8 @@ static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, { int adc_mux_n = w->shift; struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); int amic_n; - u16 amic_reg; dev_dbg(codec->dev, "%s: event: %d\n", __func__, event); @@ -3647,8 +3879,13 @@ static int tavil_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMU: amic_n = tavil_codec_find_amic_input(codec, adc_mux_n); if (amic_n) { - amic_reg = WCD934X_ANA_AMIC1 + amic_n - 1; - tavil_codec_set_tx_hold(codec, amic_reg, false); + /* + * Prevent ANC Rx pop by leaving Tx FE in HOLD + * state until PA is up. Track AMIC being used + * so we can release the HOLD later. + */ + set_bit(ANC_MIC_AMIC1 + amic_n - 1, + &tavil->status_mask); } break; default: @@ -6471,6 +6708,12 @@ static const struct snd_kcontrol_new anc_ear_spkr_switch = static const struct snd_kcontrol_new anc_spkr_pa_switch = SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); +static const struct snd_kcontrol_new anc_hphl_pa_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); + +static const struct snd_kcontrol_new anc_hphr_pa_switch = + SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); + static const struct snd_kcontrol_new mad_cpe1_switch = SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0); @@ -7110,6 +7353,14 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_PGA_E("ANC SPK1 PA", SND_SOC_NOPM, 0, 0, NULL, 0, tavil_codec_enable_spkr_anc, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0, + tavil_codec_enable_hphl_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0, + tavil_codec_enable_hphr_pa, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUTPUT("EAR"), SND_SOC_DAPM_OUTPUT("HPHL"), @@ -7119,6 +7370,8 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("SPK1 OUT"), SND_SOC_DAPM_OUTPUT("SPK2 OUT"), SND_SOC_DAPM_OUTPUT("ANC EAR"), + SND_SOC_DAPM_OUTPUT("ANC HPHL"), + SND_SOC_DAPM_OUTPUT("ANC HPHR"), SND_SOC_DAPM_SWITCH("ANC OUT EAR Enable", SND_SOC_NOPM, 0, 0, &anc_ear_switch), @@ -7127,6 +7380,13 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = { SND_SOC_DAPM_SWITCH("ANC SPKR PA Enable", SND_SOC_NOPM, 0, 0, &anc_spkr_pa_switch), + SND_SOC_DAPM_SWITCH_E("ANC OUT HPHL Enable", SND_SOC_NOPM, INTERP_HPHL, + 0, &anc_hphl_pa_switch, tavil_anc_out_switch_cb, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SWITCH_E("ANC OUT HPHR Enable", SND_SOC_NOPM, INTERP_HPHR, + 0, &anc_hphr_pa_switch, tavil_anc_out_switch_cb, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0, tavil_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -9030,6 +9290,10 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) mutex_lock(&tavil->codec_mutex); snd_soc_dapm_disable_pin(dapm, "ANC EAR PA"); snd_soc_dapm_disable_pin(dapm, "ANC EAR"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR PA"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHL"); + snd_soc_dapm_disable_pin(dapm, "ANC HPHR"); snd_soc_dapm_enable_pin(dapm, "ANC SPK1 PA"); mutex_unlock(&tavil->codec_mutex); diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c index 2088698392de..2082c356203d 100644 --- a/sound/soc/codecs/wcd_cpe_core.c +++ b/sound/soc/codecs/wcd_cpe_core.c @@ -3029,7 +3029,7 @@ err_ret: static int wcd_cpe_set_one_param(void *core_handle, struct cpe_lsm_session *session, struct lsm_params_info *p_info, - void *data, enum LSM_PARAM_TYPE param_type) + void *data, uint32_t param_type) { struct wcd_cpe_core *core = core_handle; int rc = 0; @@ -3044,25 +3044,9 @@ static int wcd_cpe_set_one_param(void *core_handle, rc = wcd_cpe_send_param_epd_thres(core, session, data, &ids); break; - case LSM_OPERATION_MODE: { - struct cpe_lsm_ids connectport_ids; - - rc = wcd_cpe_send_param_opmode(core, session, - data, &ids); - if (rc) - break; - - connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = wcd_cpe_send_param_connectport(core, session, NULL, - &connectport_ids, CPE_AFE_PORT_1_TX); - if (rc) - dev_err(core->dev, - "%s: send_param_connectport failed, err %d\n", - __func__, rc); + case LSM_OPERATION_MODE: + rc = wcd_cpe_send_param_opmode(core, session, data, &ids); break; - } case LSM_GAIN: rc = wcd_cpe_send_param_gain(core, session, data, &ids); break; @@ -3081,13 +3065,13 @@ static int wcd_cpe_set_one_param(void *core_handle, break; default: pr_err("%s: wrong param_type 0x%x\n", - __func__, p_info->param_type); + __func__, param_type); } if (rc) dev_err(core->dev, "%s: send_param(%d) failed, err %d\n", - __func__, p_info->param_type, rc); + __func__, param_type, rc); return rc; } diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c index ffc6119e543d..b2008d6da2a1 100644 --- a/sound/soc/msm/msm-cpe-lsm.c +++ b/sound/soc/msm/msm-cpe-lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1049,7 +1049,6 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, struct cpe_lsm_lab *lab_d = &lsm_d->lab; struct snd_dma_buffer *dma_buf = &substream->dma_buffer; struct msm_slim_dma_data *dma_data = NULL; - struct snd_lsm_event_status *user; struct snd_lsm_detection_params det_params; int rc = 0; @@ -1318,11 +1317,20 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_EVENT_STATUS: + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status *user; + struct snd_lsm_event_status_v3 *user_v3; + dev_dbg(rtd->dev, "%s: %s\n", - __func__, "SNDRV_LSM_EVENT_STATUS"); - - user = arg; + __func__, "SNDRV_LSM_EVENT_STATUS(_V3)"); + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid argument to ioctl %s\n", + __func__, + "SNDRV_LSM_EVENT_STATUS(_V3)"); + return -EINVAL; + } /* * Release the api lock before wait to allow @@ -1343,31 +1351,62 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, if (atomic_read(&lsm_d->event_avail) == 1) { rc = 0; atomic_set(&lsm_d->event_avail, 0); - if (lsm_d->ev_det_pld_size > - user->payload_size) { - dev_err(rtd->dev, - "%s: avail pld_bytes = %u, needed = %u\n", - __func__, - user->payload_size, - lsm_d->ev_det_pld_size); - return -EINVAL; - } - - user->status = lsm_d->ev_det_status; - user->payload_size = lsm_d->ev_det_pld_size; - - memcpy(user->payload, - lsm_d->ev_det_payload, - lsm_d->ev_det_pld_size); + if (cmd == SNDRV_LSM_EVENT_STATUS) { + user = arg; + if (lsm_d->ev_det_pld_size > + user->payload_size) { + dev_err(rtd->dev, + "%s: avail pld_bytes = %u, needed = %u\n", + __func__, + user->payload_size, + lsm_d->ev_det_pld_size); + return -EINVAL; + } + + user->status = lsm_d->ev_det_status; + user->payload_size = + lsm_d->ev_det_pld_size; + memcpy(user->payload, + lsm_d->ev_det_payload, + lsm_d->ev_det_pld_size); + } else { + user_v3 = arg; + if (lsm_d->ev_det_pld_size > + user_v3->payload_size) { + dev_err(rtd->dev, + "%s: avail pld_bytes = %u, needed = %u\n", + __func__, + user_v3->payload_size, + lsm_d->ev_det_pld_size); + return -EINVAL; + } + /* event status timestamp not supported + * on CPE mode. Set msw and lsw to 0. + */ + user_v3->timestamp_lsw = 0; + user_v3->timestamp_msw = 0; + user_v3->status = lsm_d->ev_det_status; + user_v3->payload_size = + lsm_d->ev_det_pld_size; + memcpy(user_v3->payload, + lsm_d->ev_det_payload, + lsm_d->ev_det_pld_size); + } } else if (atomic_read(&lsm_d->event_stop) == 1) { dev_dbg(rtd->dev, "%s: wait_aborted\n", __func__); - user->payload_size = 0; + if (cmd == SNDRV_LSM_EVENT_STATUS) { + user = arg; + user->payload_size = 0; + } else { + user_v3 = arg; + user_v3->payload_size = 0; + } rc = 0; } } - + } break; case SNDRV_LSM_ABORT_EVENT: @@ -1499,6 +1538,20 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, } break; + case SNDRV_LSM_SET_PORT: { + u32 port_id = cpe->input_port_id; + + dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_SET_PORT"); + rc = lsm_ops->lsm_set_port(cpe->core_handle, session, &port_id); + if (rc) { + dev_err(rtd->dev, + "%s: lsm_set_port failed, err = %d\n", + __func__, rc); + return rc; + } + } + break; + default: dev_dbg(rtd->dev, "%s: Default snd_lib_ioctl cmd 0x%x\n", @@ -1510,7 +1563,7 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream, } static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream, - struct snd_lsm_event_status *event_status) + u16 event_det_status) { struct snd_soc_pcm_runtime *rtd; struct cpe_lsm_data *lsm_d = NULL; @@ -1563,7 +1616,7 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream, reinit_completion(&lab_d->thread_complete); if (session->lab_enable && - event_status->status == + event_det_status == LSM_VOICE_WAKEUP_STATUS_DETECTED) { out_port = &session->afe_out_port_cfg; out_port->port_id = session->afe_out_port_id; @@ -2167,7 +2220,60 @@ static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream, goto done; } - msm_cpe_lsm_lab_start(substream, event_status); + msm_cpe_lsm_lab_start(substream, event_status->status); + msm_cpe_process_event_status_done(lsm_d); + kfree(event_status); + } + break; + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 u_event_status; + struct snd_lsm_event_status_v3 *event_status = NULL; + int u_pld_size = 0; + + if (copy_from_user(&u_event_status, (void *)arg, + sizeof(struct snd_lsm_event_status_v3))) { + dev_err(rtd->dev, + "%s: event status copy from user failed, size %zd\n", + __func__, + sizeof(struct snd_lsm_event_status_v3)); + err = -EFAULT; + goto done; + } + + if (u_event_status.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + dev_err(rtd->dev, + "%s: payload_size %d is invalid, max allowed = %d\n", + __func__, u_event_status.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + err = -EINVAL; + goto done; + } + + u_pld_size = sizeof(struct snd_lsm_event_status_v3) + + u_event_status.payload_size; + + event_status = kzalloc(u_pld_size, GFP_KERNEL); + if (!event_status) { + err = -ENOMEM; + goto done; + } else { + event_status->payload_size = + u_event_status.payload_size; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + } + + if (!err && copy_to_user(arg, event_status, u_pld_size)) { + dev_err(rtd->dev, + "%s: copy to user failed\n", + __func__); + kfree(event_status); + err = -EFAULT; + goto done; + } + + msm_cpe_lsm_lab_start(substream, event_status->status); msm_cpe_process_event_status_done(lsm_d); kfree(event_status); } @@ -2297,7 +2403,7 @@ struct lsm_params_info_32 { u32 param_id; u32 param_size; compat_uptr_t param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; struct snd_lsm_module_params_32 { @@ -2480,7 +2586,97 @@ static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream, goto done; } - msm_cpe_lsm_lab_start(substream, event_status); + msm_cpe_lsm_lab_start(substream, event_status->status); + msm_cpe_process_event_status_done(lsm_d); + kfree(event_status); + kfree(udata_32); + } + break; + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 *event_status = NULL; + struct snd_lsm_event_status_v3 u_event_status32; + struct snd_lsm_event_status_v3 *udata_32 = NULL; + int u_pld_size = 0; + + dev_dbg(rtd->dev, + "%s: ioctl %s\n", __func__, + "SNDRV_LSM_EVENT_STATUS_V3_32"); + + if (copy_from_user(&u_event_status32, (void *)arg, + sizeof(struct snd_lsm_event_status_v3))) { + dev_err(rtd->dev, + "%s: event status copy from user failed, size %zd\n", + __func__, + sizeof(struct snd_lsm_event_status_v3)); + err = -EFAULT; + goto done; + } + + if (u_event_status32.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + dev_err(rtd->dev, + "%s: payload_size %d is invalid, max allowed = %d\n", + __func__, u_event_status32.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + err = -EINVAL; + goto done; + } + + u_pld_size = sizeof(struct snd_lsm_event_status_v3) + + u_event_status32.payload_size; + event_status = kzalloc(u_pld_size, GFP_KERNEL); + if (!event_status) { + dev_err(rtd->dev, + "%s: No memory for event status\n", + __func__); + err = -ENOMEM; + goto done; + } else { + event_status->payload_size = + u_event_status32.payload_size; + err = msm_cpe_lsm_ioctl_shared(substream, + cmd, event_status); + if (err) + dev_err(rtd->dev, + "%s: %s failed, error = %d\n", + __func__, + "SNDRV_LSM_EVENT_STATUS_V3_32", + err); + } + + if (!err) { + udata_32 = kzalloc(u_pld_size, GFP_KERNEL); + if (!udata_32) { + dev_err(rtd->dev, + "%s: nomem for udata\n", + __func__); + err = -EFAULT; + } else { + udata_32->timestamp_lsw = + event_status->timestamp_lsw; + udata_32->timestamp_msw = + event_status->timestamp_msw; + udata_32->status = event_status->status; + udata_32->payload_size = + event_status->payload_size; + memcpy(udata_32->payload, + event_status->payload, + u_pld_size); + } + } + + if (!err && copy_to_user(arg, udata_32, + u_pld_size)) { + dev_err(rtd->dev, + "%s: copy to user failed\n", + __func__); + kfree(event_status); + kfree(udata_32); + err = -EFAULT; + goto done; + } + + msm_cpe_lsm_lab_start(substream, event_status->status); msm_cpe_process_event_status_done(lsm_d); kfree(event_status); kfree(udata_32); diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 6c1897340e74..44a6a245c7a2 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2203,12 +2203,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 1 Audio Service Capture", .aif_name = "LSM1_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM1", @@ -2218,12 +2220,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 2 Audio Service Capture", .aif_name = "LSM2_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM2", @@ -2233,12 +2237,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 3 Audio Service Capture", .aif_name = "LSM3_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM3", @@ -2248,12 +2254,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 4 Audio Service Capture", .aif_name = "LSM4_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM4", @@ -2263,12 +2271,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 5 Audio Service Capture", .aif_name = "LSM5_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM5", @@ -2278,12 +2288,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 6 Audio Service Capture", .aif_name = "LSM6_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM6", @@ -2293,12 +2305,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 7 Audio Service Capture", .aif_name = "LSM7_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM7", @@ -2308,12 +2322,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .capture = { .stream_name = "Listen 8 Audio Service Capture", .aif_name = "LSM8_UL_HL", - .rates = SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, }, .ops = &msm_fe_dai_ops, .name = "LSM8", diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 557c7946506a..391640d53d56 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -3383,12 +3383,12 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_ignore_suspend(dapm, "HPHR"); snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI"); snd_soc_dapm_ignore_suspend(dapm, "VIINPUT"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); + snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) { snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3"); snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL"); - snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR"); snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1"); snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2"); } diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c index 75af648baef3..b54cde4ef0c3 100644 --- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c +++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c @@ -607,7 +607,6 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, } INIT_LIST_HEAD(&cal_block->list); - list_add_tail(&cal_block->list, &cal_type->cal_blocks); cal_block->map_data.ion_map_handle = basic_cal->cal_data.mem_handle; if (basic_cal->cal_data.mem_handle > 0) { @@ -639,6 +638,7 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, goto err; } cal_block->buffer_number = basic_cal->cal_hdr.buffer_number; + list_add_tail(&cal_block->list, &cal_type->cal_blocks); pr_debug("%s: created block for cal type %d, buf num %d, map handle %d, map size %zd paddr 0x%pK!\n", __func__, cal_type->info.reg.cal_type, cal_block->buffer_number, @@ -648,6 +648,8 @@ static struct cal_block_data *create_cal_block(struct cal_type_data *cal_type, done: return cal_block; err: + kfree(cal_block->cal_info); + kfree(cal_block->client_info); kfree(cal_block); cal_block = NULL; return cal_block; diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c index efb6644e551f..55ca659567f5 100644 --- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c +++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -35,7 +35,7 @@ #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 4096 +#define CAPTURE_MAX_PERIOD_SIZE 61440 #define CAPTURE_MIN_PERIOD_SIZE 320 #define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256 @@ -47,12 +47,14 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = { SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rates = SNDRV_PCM_RATE_16000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE), + .rates = (SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000), .rate_min = 16000, - .rate_max = 16000, + .rate_max = 48000, .channels_min = 1, - .channels_max = 1, + .channels_max = 4, .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, @@ -64,7 +66,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = { /* Conventional and unconventional sample rate supported */ static unsigned int supported_sample_rates[] = { - 16000, + 16000, 48000, }; static struct snd_pcm_hw_constraint_list constraints_sample_rates = { @@ -76,7 +78,7 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = { struct lsm_priv { struct snd_pcm_substream *substream; struct lsm_client *lsm_client; - struct snd_lsm_event_status *event_status; + struct snd_lsm_event_status_v3 *event_status; spinlock_t event_lock; wait_queue_head_t event_wait; unsigned long event_avail; @@ -88,6 +90,11 @@ struct lsm_priv { int dma_write; }; +enum { /* lsm session states */ + IDLE = 0, + RUNNING, +}; + static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i) { int rc = 0; @@ -196,6 +203,8 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, uint16_t status = 0; uint16_t payload_size = 0; uint16_t index = 0; + uint32_t event_ts_lsw = 0; + uint32_t event_ts_msw = 0; if (!substream || !substream->private_data) { pr_err("%s: Invalid %s\n", __func__, @@ -269,24 +278,44 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token, "%s: event detect status = %d payload size = %d\n", __func__, status , payload_size); break; + + case LSM_SESSION_EVENT_DETECTION_STATUS_V3: + event_ts_lsw = ((uint32_t *)payload)[0]; + event_ts_msw = ((uint32_t *)payload)[1]; + status = (uint16_t)((uint8_t *)payload)[8]; + payload_size = (uint16_t)((uint8_t *)payload)[9]; + index = 10; + dev_dbg(rtd->dev, + "%s: ts_msw = %u, ts_lsw = %u, event detect status = %d payload size = %d\n", + __func__, event_ts_msw, event_ts_lsw, status, + payload_size); + break; + default: break; } if (opcode == LSM_SESSION_EVENT_DETECTION_STATUS || - opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2) { + opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2 || + opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V3) { spin_lock_irqsave(&prtd->event_lock, flags); prtd->event_status = krealloc(prtd->event_status, - sizeof(struct snd_lsm_event_status) + + sizeof(struct snd_lsm_event_status_v3) + payload_size, GFP_ATOMIC); if (!prtd->event_status) { dev_err(rtd->dev, "%s: no memory for event status\n", __func__); return; } - + /* + * event status timestamp will be non-zero and valid if + * opcode is LSM_SESSION_EVENT_DETECTION_STATUS_V3 + */ + prtd->event_status->timestamp_lsw = event_ts_lsw; + prtd->event_status->timestamp_msw = event_ts_msw; prtd->event_status->status = status; prtd->event_status->payload_size = payload_size; + if (likely(prtd->event_status)) { memcpy(prtd->event_status->payload, &((uint8_t *)payload)[index], @@ -641,6 +670,54 @@ err_ret: return rc; } +static int msm_lsm_set_poll_enable(struct snd_pcm_substream *substream, + struct lsm_params_info *p_info) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct lsm_priv *prtd = runtime->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_lsm_poll_enable poll_enable; + int rc = 0; + + if (p_info->param_size != sizeof(poll_enable)) { + dev_err(rtd->dev, + "%s: Invalid param_size %d\n", + __func__, p_info->param_size); + rc = -EINVAL; + goto done; + } + + if (copy_from_user(&poll_enable, p_info->param_data, + sizeof(poll_enable))) { + dev_err(rtd->dev, + "%s: copy_from_user failed, size = %zd\n", + __func__, sizeof(poll_enable)); + rc = -EFAULT; + goto done; + } + + if (prtd->lsm_client->poll_enable == poll_enable.poll_en) { + dev_dbg(rtd->dev, + "%s: Polling for session %d already %s\n", + __func__, prtd->lsm_client->session, + (poll_enable.poll_en ? "enabled" : "disabled")); + rc = 0; + goto done; + } + + rc = q6lsm_set_one_param(prtd->lsm_client, p_info, + &poll_enable, LSM_POLLING_ENABLE); + if (!rc) { + prtd->lsm_client->poll_enable = poll_enable.poll_en; + } else { + dev_err(rtd->dev, + "%s: Failed to set poll enable, err = %d\n", + __func__, rc); + } +done: + return rc; +} + static int msm_lsm_process_params(struct snd_pcm_substream *substream, struct snd_lsm_module_params *p_data, void *params) @@ -681,6 +758,9 @@ static int msm_lsm_process_params(struct snd_pcm_substream *substream, case LSM_CUSTOM_PARAMS: rc = msm_lsm_set_custom(substream, p_info); break; + case LSM_POLLING_ENABLE: + rc = msm_lsm_set_poll_enable(substream, p_info); + break; default: dev_err(rtd->dev, "%s: Invalid param_type %d\n", @@ -710,10 +790,8 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, struct snd_lsm_session_data session_data; int rc = 0; int xchg = 0; - u32 size = 0; struct snd_pcm_runtime *runtime; struct lsm_priv *prtd; - struct snd_lsm_event_status *user = arg; struct snd_lsm_detection_params det_params; uint8_t *confidence_level = NULL; @@ -870,6 +948,10 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, break; case SNDRV_LSM_EVENT_STATUS: + case SNDRV_LSM_EVENT_STATUS_V3: { + uint32_t ts_lsw, ts_msw; + uint16_t status = 0, payload_size = 0; + dev_dbg(rtd->dev, "%s: Get event status\n", __func__); atomic_set(&prtd->event_wait_stop, 0); rc = wait_event_freezable(prtd->event_wait, @@ -882,9 +964,12 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, dev_dbg(rtd->dev, "%s: New event available %ld\n", __func__, prtd->event_avail); spin_lock_irqsave(&prtd->event_lock, flags); + if (prtd->event_status) { - size = sizeof(*(prtd->event_status)) + - prtd->event_status->payload_size; + payload_size = prtd->event_status->payload_size; + ts_lsw = prtd->event_status->timestamp_lsw; + ts_msw = prtd->event_status->timestamp_msw; + status = prtd->event_status->status; spin_unlock_irqrestore(&prtd->event_lock, flags); } else { @@ -896,15 +981,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, __func__); break; } - if (user->payload_size < - prtd->event_status->payload_size) { - dev_dbg(rtd->dev, - "%s: provided %d bytes isn't enough, needs %d bytes\n", - __func__, user->payload_size, - prtd->event_status->payload_size); - rc = -ENOMEM; + + if (cmd == SNDRV_LSM_EVENT_STATUS) { + struct snd_lsm_event_status *user = arg; + + if (user->payload_size < payload_size) { + dev_dbg(rtd->dev, + "%s: provided %d bytes isn't enough, needs %d bytes\n", + __func__, user->payload_size, + payload_size); + rc = -ENOMEM; + } else { + user->status = status; + user->payload_size = payload_size; + memcpy(user->payload, + prtd->event_status->payload, + payload_size); + } } else { - memcpy(user, prtd->event_status, size); + struct snd_lsm_event_status_v3 *user_v3 = arg; + + if (user_v3->payload_size < payload_size) { + dev_dbg(rtd->dev, + "%s: provided %d bytes isn't enough, needs %d bytes\n", + __func__, user_v3->payload_size, + payload_size); + rc = -ENOMEM; + } else { + user_v3->timestamp_lsw = ts_lsw; + user_v3->timestamp_msw = ts_msw; + user_v3->status = status; + user_v3->payload_size = payload_size; + memcpy(user_v3->payload, + prtd->event_status->payload, + payload_size); + } + } + if (!rc) { if (prtd->lsm_client->lab_enable && !prtd->lsm_client->lab_started && prtd->event_status->status == @@ -929,6 +1042,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, rc = 0; } break; + } case SNDRV_LSM_ABORT_EVENT: dev_dbg(rtd->dev, "%s: Aborting event status wait\n", @@ -1035,6 +1149,43 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, prtd->lsm_client->lab_started = false; } break; + + case SNDRV_LSM_SET_PORT: + dev_dbg(rtd->dev, "%s: set LSM port\n", __func__); + rc = q6lsm_set_port_connected(prtd->lsm_client); + break; + + case SNDRV_LSM_SET_FWK_MODE_CONFIG: { + u32 *mode = NULL; + + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid param arg for ioctl %s session %d\n", + __func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG", + prtd->lsm_client->session); + rc = -EINVAL; + break; + } + mode = (u32 *)arg; + if (prtd->lsm_client->event_mode == *mode) { + dev_dbg(rtd->dev, + "%s: mode for %d already set to %d\n", + __func__, prtd->lsm_client->session, *mode); + rc = 0; + } else { + dev_dbg(rtd->dev, "%s: Event mode = %d\n", + __func__, *mode); + rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode); + if (!rc) + prtd->lsm_client->event_mode = *mode; + else + dev_err(rtd->dev, + "%s: set event mode failed %d\n", + __func__, rc); + } + break; + } + default: dev_dbg(rtd->dev, "%s: Falling into default snd_lib_ioctl cmd 0x%x\n", @@ -1053,6 +1204,21 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream, return rc; } #ifdef CONFIG_COMPAT + +struct snd_lsm_event_status32 { + u16 status; + u16 payload_size; + u8 payload[0]; +}; + +struct snd_lsm_event_status_v3_32 { + u32 timestamp_lsw; + u32 timestamp_msw; + u16 status; + u16 payload_size; + u8 payload[0]; +}; + struct snd_lsm_sound_model_v2_32 { compat_uptr_t data; compat_uptr_t confidence_level; @@ -1074,7 +1240,7 @@ struct lsm_params_info_32 { u32 param_id; u32 param_size; compat_uptr_t param_data; - enum LSM_PARAM_TYPE param_type; + uint32_t param_type; }; struct snd_lsm_module_params_32 { @@ -1090,6 +1256,8 @@ enum { _IOW('U', 0x0A, struct snd_lsm_detection_params_32), SNDRV_LSM_SET_MODULE_PARAMS_32 = _IOW('U', 0x0B, struct snd_lsm_module_params_32), + SNDRV_LSM_EVENT_STATUS_V3_32 = + _IOW('U', 0x0F, struct snd_lsm_event_status_v3_32), }; static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, @@ -1178,6 +1346,73 @@ static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream, break; } + case SNDRV_LSM_EVENT_STATUS_V3_32: { + struct snd_lsm_event_status_v3_32 userarg32, *user32 = NULL; + struct snd_lsm_event_status_v3 *user = NULL; + + if (copy_from_user(&userarg32, arg, sizeof(userarg32))) { + dev_err(rtd->dev, "%s: err copyuser ioctl %s\n", + __func__, "SNDRV_LSM_EVENT_STATUS_V3_32"); + return -EFAULT; + } + + if (userarg32.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg32.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + return -EINVAL; + } + + size = sizeof(*user) + userarg32.payload_size; + user = kmalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); + return -EFAULT; + } + cmd = SNDRV_LSM_EVENT_STATUS_V3; + user->payload_size = userarg32.payload_size; + err = msm_lsm_ioctl_shared(substream, cmd, user); + + /* Update size with actual payload size */ + size = sizeof(userarg32) + user->payload_size; + if (!err && !access_ok(VERIFY_WRITE, arg, size)) { + dev_err(rtd->dev, + "%s: write verify failed size %d\n", + __func__, size); + err = -EFAULT; + } + if (!err) { + user32 = kmalloc(size, GFP_KERNEL); + if (!user32) { + dev_err(rtd->dev, + "%s: Allocation event user status size %d\n", + __func__, size); + err = -EFAULT; + } else { + user32->timestamp_lsw = user->timestamp_lsw; + user32->timestamp_msw = user->timestamp_msw; + user32->status = user->status; + user32->payload_size = user->payload_size; + memcpy(user32->payload, + user->payload, user32->payload_size); + } + } + if (!err && (copy_to_user(arg, user32, size))) { + dev_err(rtd->dev, "%s: failed to copy payload %d", + __func__, size); + err = -EFAULT; + } + kfree(user); + kfree(user32); + if (err) + dev_err(rtd->dev, "%s: lsmevent failed %d", + __func__, err); + break; + } + case SNDRV_LSM_REG_SND_MODEL_V2_32: { struct snd_lsm_sound_model_v2_32 snd_modelv232; struct snd_lsm_sound_model_v2 snd_modelv2; @@ -1573,6 +1808,67 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, "%s: lsmevent failed %d", __func__, err); return err; } + + case SNDRV_LSM_EVENT_STATUS_V3: { + struct snd_lsm_event_status_v3 *user = NULL; + struct snd_lsm_event_status_v3 userarg; + + dev_dbg(rtd->dev, + "%s: SNDRV_LSM_EVENT_STATUS_V3\n", __func__); + if (!arg) { + dev_err(rtd->dev, + "%s: Invalid params event_status_v3\n", + __func__); + return -EINVAL; + } + if (copy_from_user(&userarg, arg, sizeof(userarg))) { + dev_err(rtd->dev, + "%s: err copyuser event_status_v3\n", + __func__); + return -EFAULT; + } + + if (userarg.payload_size > + LISTEN_MAX_STATUS_PAYLOAD_SIZE) { + pr_err("%s: payload_size %d is invalid, max allowed = %d\n", + __func__, userarg.payload_size, + LISTEN_MAX_STATUS_PAYLOAD_SIZE); + return -EINVAL; + } + + size = sizeof(struct snd_lsm_event_status_v3) + + userarg.payload_size; + user = kmalloc(size, GFP_KERNEL); + if (!user) { + dev_err(rtd->dev, + "%s: Allocation failed event status size %d\n", + __func__, size); + return -EFAULT; + } + user->payload_size = userarg.payload_size; + err = msm_lsm_ioctl_shared(substream, cmd, user); + + /* Update size with actual payload size */ + size = sizeof(*user) + user->payload_size; + if (!err && !access_ok(VERIFY_WRITE, arg, size)) { + dev_err(rtd->dev, + "%s: write verify failed size %d\n", + __func__, size); + err = -EFAULT; + } + if (!err && (copy_to_user(arg, user, size))) { + dev_err(rtd->dev, + "%s: failed to copy payload %d", + __func__, size); + err = -EFAULT; + } + kfree(user); + if (err) + dev_err(rtd->dev, + "%s: lsm_event_v3 failed %d", __func__, err); + break; + } + default: err = msm_lsm_ioctl_shared(substream, cmd, arg); break; @@ -1640,6 +1936,11 @@ static int msm_lsm_open(struct snd_pcm_substream *substream) return -ENOMEM; } prtd->lsm_client->opened = false; + prtd->lsm_client->session_state = IDLE; + prtd->lsm_client->poll_enable = true; + prtd->lsm_client->perf_mode = 0; + prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE; + return 0; } @@ -1648,6 +1949,7 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd; + int ret = 0; if (!substream->private_data) { pr_err("%s: Invalid private_data", __func__); @@ -1661,9 +1963,30 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream) "%s: LSM client data ptr is NULL\n", __func__); return -EINVAL; } + + if (q6lsm_set_media_fmt_params(prtd->lsm_client)) + dev_dbg(rtd->dev, + "%s: failed to set lsm media fmt params\n", __func__); + + if (prtd->lsm_client->session_state == IDLE) { + ret = msm_pcm_routing_reg_phy_compr_stream( + rtd->dai_link->be_id, + prtd->lsm_client->perf_mode, + prtd->lsm_client->session, + SNDRV_PCM_STREAM_CAPTURE, + LISTEN); + if (ret) { + dev_err(rtd->dev, + "%s: register phy compr stream failed %d\n", + __func__, ret); + return ret; + } + } + + prtd->lsm_client->session_state = RUNNING; prtd->lsm_client->started = false; runtime->private_data = prtd; - return 0; + return ret; } static int msm_lsm_close(struct snd_pcm_substream *substream) @@ -1712,6 +2035,9 @@ static int msm_lsm_close(struct snd_pcm_substream *substream) __func__); } + msm_pcm_routing_dereg_phy_stream(rtd->dai_link->be_id, + SNDRV_PCM_STREAM_CAPTURE); + if (prtd->lsm_client->opened) { q6lsm_close(prtd->lsm_client); prtd->lsm_client->opened = false; @@ -1733,7 +2059,7 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct lsm_priv *prtd = runtime->private_data; - struct lsm_lab_hw_params *hw_params = NULL; + struct lsm_hw_params *hw_params = NULL; struct snd_soc_pcm_runtime *rtd; if (!substream->private_data) { @@ -1749,25 +2075,36 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } hw_params = &prtd->lsm_client->hw_params; - hw_params->sample_rate = params_rate(params); - hw_params->sample_size = - (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 0; + hw_params->num_chs = params_channels(params); hw_params->period_count = params_periods(params); - if (hw_params->sample_rate != 16000 || hw_params->sample_size != 16 || - hw_params->period_count == 0) { + hw_params->sample_rate = params_rate(params); + if (((hw_params->sample_rate != 16000) && + (hw_params->sample_rate != 48000)) || + (hw_params->period_count == 0)) { dev_err(rtd->dev, - "%s: Invalid params sample rate %d sample size %d period count %d", + "%s: Invalid Params sample rate %d period count %d\n", __func__, hw_params->sample_rate, - hw_params->sample_size, - hw_params->period_count); + hw_params->period_count); return -EINVAL; } + + if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) { + hw_params->sample_size = 16; + } else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) { + hw_params->sample_size = 24; + } else { + dev_err(rtd->dev, "%s: Invalid Format 0x%x\n", + __func__, params_format(params)); + return -EINVAL; + } + hw_params->buf_sz = params_buffer_bytes(params) / - hw_params->period_count; + hw_params->period_count; dev_dbg(rtd->dev, - "%s: sample rate %d sample size %d buffer size %d period count %d\n", - __func__, hw_params->sample_rate, hw_params->sample_size, - hw_params->buf_sz, hw_params->period_count); + "%s: channels %d sample rate %d sample size %d buffer size %d period count %d\n", + __func__, hw_params->num_chs, hw_params->sample_rate, + hw_params->sample_size, hw_params->buf_sz, + hw_params->period_count); return 0; } @@ -1863,6 +2200,109 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch, return 0; } +static int msm_lsm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8)) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + app_type = ucontrol->value.integer.value[0]; + acdb_dev_id = ucontrol->value.integer.value[1]; + sample_rate = ucontrol->value.integer.value[2]; + + pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n", + __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX); + msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type, + acdb_dev_id, sample_rate, SESSION_TYPE_TX); + + return 0; +} + +static int msm_lsm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u64 fe_id = kcontrol->private_value; + int ret = 0; + int app_type; + int acdb_dev_id; + int sample_rate; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8)) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + + ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX, + &app_type, &acdb_dev_id, &sample_rate); + if (ret < 0) { + pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n", + __func__, ret); + goto done; + } + + ucontrol->value.integer.value[0] = app_type; + ucontrol->value.integer.value[1] = acdb_dev_id; + ucontrol->value.integer.value[2] = sample_rate; + pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", + __func__, fe_id, SESSION_TYPE_TX, + app_type, acdb_dev_id, sample_rate); +done: + return ret; +} + +static int msm_lsm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm = rtd->pcm; + struct snd_pcm_usr *app_type_info; + struct snd_kcontrol *kctl; + const char *mixer_ctl_name = "Listen Stream"; + const char *deviceNo = "NN"; + const char *suffix = "App Type Cfg"; + int ctl_len, ret = 0; + + ctl_len = strlen(mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + pr_debug("%s: Listen app type cntrl add\n", __func__); + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &app_type_info); + if (ret < 0) { + pr_err("%s: Listen app type cntrl add failed: %d\n", + __func__, ret); + return ret; + } + kctl = app_type_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_lsm_app_type_cfg_ctl_put; + kctl->get = msm_lsm_app_type_cfg_ctl_get; + return 0; +} + +static int msm_lsm_add_controls(struct snd_soc_pcm_runtime *rtd) +{ + int ret = 0; + + ret = msm_lsm_add_app_type_controls(rtd); + if (ret) + pr_err("%s, add app type controls failed:%d\n", __func__, ret); + + return ret; +} + static struct snd_pcm_ops msm_lsm_ops = { .open = msm_lsm_open, .close = msm_lsm_close, @@ -1877,11 +2317,16 @@ static struct snd_pcm_ops msm_lsm_ops = { static int msm_asoc_lsm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; + int ret = 0; if (!card->dev->coherent_dma_mask) card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - return 0; + ret = msm_lsm_add_controls(rtd); + if (ret) + pr_err("%s, kctl add failed:%d\n", __func__, ret); + + return ret; } static int msm_asoc_lsm_probe(struct snd_soc_platform *platform) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 2d410170f48d..39fdd6b49357 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -72,9 +72,12 @@ static int tert_mi2s_switch_enable; static int quat_mi2s_switch_enable; static int fm_pcmrx_switch_enable; static int usb_switch_enable; -static int lsm_mux_slim_port; +static int lsm_port_index; static int slim0_rx_aanc_fb_port; static int msm_route_ec_ref_rx; +static int msm_ec_ref_ch = 4; +static int msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_ec_ref_sampling_rate = 48000; static uint32_t voc_session_id = ALL_SESSION_VSID; static int msm_route_ext_ec_ref; static bool is_custom_stereo_on; @@ -88,6 +91,8 @@ enum { MADSWAUDIO, }; +#define ADM_LSM_PORT_INDEX 9 + #define SLIMBUS_0_TX_TEXT "SLIMBUS_0_TX" #define SLIMBUS_1_TX_TEXT "SLIMBUS_1_TX" #define SLIMBUS_2_TX_TEXT "SLIMBUS_2_TX" @@ -96,12 +101,14 @@ enum { #define SLIMBUS_TX_VI_TEXT "SLIMBUS_TX_VI" #define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX" #define TERT_MI2S_TX_TEXT "TERT_MI2S_TX" +#define QUAT_MI2S_TX_TEXT "QUAT_MI2S_TX" +#define ADM_LSM_TX_TEXT "ADM_LSM_TX" #define LSM_FUNCTION_TEXT "LSM Function" -static const char * const mad_audio_mux_text[] = { +static const char * const lsm_port_text[] = { "None", SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT, - SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_TX_VI_TEXT, - SLIMBUS_5_TX_TEXT, TERT_MI2S_TX_TEXT + SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT, + TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT }; struct msm_pcm_route_bdai_pp_params { @@ -270,254 +277,262 @@ static void msm_pcm_routng_cfg_matrix_map_pp(struct route_payload payload, #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { - { PRIMARY_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX}, - { PRIMARY_I2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX}, - { SLIMBUS_0_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX}, - { SLIMBUS_0_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX}, - { HDMI_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_HDMI}, - { INT_BT_SCO_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX}, - { INT_BT_SCO_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX}, - { INT_FM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX}, - { INT_FM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX}, - { RT_PROXY_PORT_001_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_RX}, - { RT_PROXY_PORT_001_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_AFE_PCM_TX}, - { AFE_PORT_ID_PRIMARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { PRIMARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_RX}, + { PRIMARY_I2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_I2S_TX}, + { SLIMBUS_0_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_RX}, + { SLIMBUS_0_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_0_TX}, + { HDMI_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_HDMI}, + { INT_BT_SCO_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_RX}, + { INT_BT_SCO_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_SCO_TX}, + { INT_FM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_RX}, + { INT_FM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_FM_TX}, + { RT_PROXY_PORT_001_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_AFE_PCM_RX}, + { RT_PROXY_PORT_001_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_AFE_PCM_TX}, + { AFE_PORT_ID_PRIMARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_RX}, - { AFE_PORT_ID_PRIMARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUXPCM_TX}, - { VOICE_PLAYBACK_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_VOICE_PLAYBACK_TX}, - { VOICE2_PLAYBACK_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE2_PLAYBACK_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_VOICE2_PLAYBACK_TX}, - { VOICE_RECORD_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_RX}, - { VOICE_RECORD_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INCALL_RECORD_TX}, - { MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX}, - { MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX}, - { SECONDARY_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX}, - { SLIMBUS_1_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX}, - { SLIMBUS_1_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX}, - { SLIMBUS_2_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_RX}, - { SLIMBUS_2_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_TX}, - { SLIMBUS_3_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX}, - { SLIMBUS_3_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX}, - { SLIMBUS_4_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX}, - { SLIMBUS_4_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX}, - { SLIMBUS_5_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX}, - { SLIMBUS_5_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX}, - { SLIMBUS_6_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX}, - { SLIMBUS_6_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX}, - { SLIMBUS_7_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX}, - { SLIMBUS_7_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX}, - { SLIMBUS_8_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX}, - { SLIMBUS_8_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX}, - { SLIMBUS_EXTPROC_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX}, - { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { VOICE_RECORD_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INCALL_RECORD_RX}, + { VOICE_RECORD_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_INCALL_RECORD_TX}, + { MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_RX}, + { MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_MI2S_TX}, + { SECONDARY_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_I2S_RX}, + { SLIMBUS_1_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_RX}, + { SLIMBUS_1_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_1_TX}, + { SLIMBUS_2_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_RX}, + { SLIMBUS_2_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_2_TX}, + { SLIMBUS_3_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_RX}, + { SLIMBUS_3_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_3_TX}, + { SLIMBUS_4_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_RX}, + { SLIMBUS_4_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_4_TX}, + { SLIMBUS_5_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX}, + { SLIMBUS_5_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_TX}, + { SLIMBUS_6_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_RX}, + { SLIMBUS_6_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_6_TX}, + { SLIMBUS_7_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_RX}, + { SLIMBUS_7_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_7_TX}, + { SLIMBUS_8_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_RX}, + { SLIMBUS_8_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_8_TX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_RX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_TX}, + { SLIMBUS_EXTPROC_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_STUB_1_TX}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_MI2S_RX}, - { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_MI2S_TX}, - { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_RX}, - { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_TX}, - { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_MI2S_RX}, - { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_MI2S_TX}, - { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_MI2S_RX}, - { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_MI2S_TX}, - { AUDIO_PORT_ID_I2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AUDIO_PORT_ID_I2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_AUDIO_I2S_RX}, - { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_AUXPCM_RX}, - { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_AUXPCM_TX}, - { AFE_PORT_ID_SPDIF_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX}, - { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SPDIF_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SPDIF_RX}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_SD1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_MI2S_RX_SD1}, - { AFE_PORT_ID_QUINARY_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUINARY_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUIN_MI2S_RX}, - { AFE_PORT_ID_QUINARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUINARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUIN_MI2S_TX}, - { AFE_PORT_ID_SENARY_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SENARY_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SENARY_MI2S_TX}, - { AFE_PORT_ID_PRIMARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_0}, - { AFE_PORT_ID_PRIMARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_0}, - { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_1}, - { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_1}, - { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_2}, - { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_2}, - { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_3}, - { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_3}, - { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_4}, - { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_4}, - { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_5}, - { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_5}, - { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_6}, - { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_6}, - { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_RX_7}, - { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_PRIMARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_PRI_TDM_TX_7}, - { AFE_PORT_ID_SECONDARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_0}, - { AFE_PORT_ID_SECONDARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_0}, - { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_1}, - { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_1}, - { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_2}, - { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_2}, - { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_3}, - { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_3}, - { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_4}, - { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_4}, - { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_5}, - { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_5}, - { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_6}, - { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_6}, - { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_RX_7}, - { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_SECONDARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SEC_TDM_TX_7}, - { AFE_PORT_ID_TERTIARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_0}, - { AFE_PORT_ID_TERTIARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_0}, - { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_1}, - { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_1}, - { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_2}, - { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_2}, - { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_3}, - { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_3}, - { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_4}, - { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_4}, - { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_5}, - { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_5}, - { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_6}, - { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_6}, - { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_RX_7}, - { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_TDM_TX_7}, - { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_0}, - { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_0}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_1}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_1, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_1}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_2}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_2, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_2}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_3}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_3, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_3}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_4}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_4, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_4}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_5}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_5, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_5}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_6}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_6, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_6}, - { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_RX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_RX_7}, - { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_TDM_TX_7, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_TDM_TX_7}, - { INT_BT_A2DP_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX}, - { AFE_PORT_ID_USB_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_RX}, - { AFE_PORT_ID_USB_TX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_USB_AUDIO_TX}, - { DISPLAY_PORT_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_DISPLAY_PORT}, - { AFE_PORT_ID_TERTIARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { INT_BT_A2DP_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT_BT_A2DP_RX}, + { AFE_PORT_ID_USB_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_USB_AUDIO_RX}, + { AFE_PORT_ID_USB_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, + LPASS_BE_USB_AUDIO_TX}, + { DISPLAY_PORT_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_DISPLAY_PORT}, + { AFE_PORT_ID_TERTIARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_AUXPCM_RX}, - { AFE_PORT_ID_TERTIARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_TERTIARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_TERT_AUXPCM_TX}, - { AFE_PORT_ID_QUATERNARY_PCM_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_PCM_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_AUXPCM_RX}, - { AFE_PORT_ID_QUATERNARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_QUATERNARY_PCM_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_QUAT_AUXPCM_TX}, - { AFE_PORT_ID_INT0_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT0_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT0_MI2S_RX}, - { AFE_PORT_ID_INT0_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT0_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT0_MI2S_TX}, - { AFE_PORT_ID_INT1_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT1_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT1_MI2S_RX}, - { AFE_PORT_ID_INT1_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT1_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT1_MI2S_TX}, - { AFE_PORT_ID_INT2_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT2_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT2_MI2S_RX}, - { AFE_PORT_ID_INT2_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT2_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT2_MI2S_TX}, - { AFE_PORT_ID_INT3_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT3_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT3_MI2S_RX}, - { AFE_PORT_ID_INT3_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT3_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT3_MI2S_TX}, - { AFE_PORT_ID_INT4_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT4_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT4_MI2S_RX}, - { AFE_PORT_ID_INT4_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT4_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT4_MI2S_TX}, - { AFE_PORT_ID_INT5_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT5_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT5_MI2S_RX}, - { AFE_PORT_ID_INT5_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT5_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT5_MI2S_TX}, - { AFE_PORT_ID_INT6_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT6_MI2S_RX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT6_MI2S_RX}, - { AFE_PORT_ID_INT6_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0, + { AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT6_MI2S_TX}, - { SLIMBUS_TX_VI, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI}, + { SLIMBUS_TX_VI, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI}, }; -/* Track ASM playback & capture sessions of DAI */ +/* Track ASM playback & capture sessions of DAI + * Track LSM listen sessions + */ static struct msm_pcm_routing_fdai_data - fe_dai_map[MSM_FRONTEND_DAI_MM_SIZE][2] = { + fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = { /* MULTIMEDIA1 */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, @@ -575,13 +590,80 @@ static struct msm_pcm_routing_fdai_data /* MULTIMEDIA19 */ {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* CS_VOICE */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOIP */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* AFE_RX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* AFE_TX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOLTE */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* DTMF_RX */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* QCHAT */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOLTE_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM1 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM3 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM4 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM5 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM6 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM7 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* LSM8 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICE2_STUB */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOWLAN */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICEMMODE1 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, + /* VOICEMMODE2 */ + {{0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} }, + {0, INVALID_SESSION, LEGACY_PCM_MODE, {NULL, NULL} } }, }; -static unsigned long session_copp_map[MSM_FRONTEND_DAI_MM_SIZE][2] +static unsigned long session_copp_map[MSM_FRONTEND_DAI_MAX][2] [MSM_BACKEND_DAI_MAX]; static struct msm_pcm_routing_app_type_data app_type_cfg[MAX_APP_TYPES]; +static struct msm_pcm_routing_app_type_data lsm_app_type_cfg[MAX_APP_TYPES]; static struct msm_pcm_stream_app_type_cfg - fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE][2]; + fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MAX][2]; /* The caller of this should aqcuire routing lock */ void msm_pcm_routing_get_bedai_info(int be_idx, @@ -624,13 +706,39 @@ static int msm_pcm_routing_get_app_type_idx(int app_type) return 0; } +static int msm_pcm_routing_get_lsm_app_type_idx(int app_type) +{ + int idx; + + pr_debug("%s: app_type: %d\n", __func__, app_type); + for (idx = 0; idx < MAX_APP_TYPES; idx++) { + if (lsm_app_type_cfg[idx].app_type == app_type) + return idx; + } + pr_debug("%s: App type not available, fallback to default\n", __func__); + return 0; +} + +static bool is_mm_lsm_fe_id(int fe_id) +{ + bool rc = true; + + if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID && + ((fe_id < MSM_FRONTEND_DAI_LSM1) || + (fe_id > MSM_FRONTEND_DAI_LSM8))) { + rc = false; + } + return rc; +} + + void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, int acdb_dev_id, int sample_rate, int session_type) { pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n", __func__, fedai_id, session_type, app_type, acdb_dev_id, sample_rate); - if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fedai_id)) { pr_err("%s: Invalid machine driver ID %d\n", __func__, fedai_id); return; @@ -677,7 +785,7 @@ int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type, pr_err("%s: NULL pointer sent for sample rate\n", __func__); ret = -EINVAL; goto done; - } else if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + } else if (!is_mm_lsm_fe_id(fedai_id)) { pr_err("%s: Invalid FE ID %d\n", __func__, fedai_id); ret = -EINVAL; @@ -791,7 +899,8 @@ static uint8_t is_be_dai_extproc(int be_dai) } static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, - int path_type, int perf_mode) + int path_type, int perf_mode, + uint32_t passthr_mode) { int i, port_type, j, num_copps = 0; struct route_payload payload; @@ -804,7 +913,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { for (j = 0; j < MAX_COPPS_PER_PORT; j++) { unsigned long copp = session_copp_map[fedai_id][sess_type][i]; @@ -827,7 +936,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, fe_dai_app_type_cfg[fedai_id][sess_type].acdb_dev_id; payload.sample_rate = fe_dai_app_type_cfg[fedai_id][sess_type].sample_rate; - adm_matrix_map(path_type, payload, perf_mode); + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } } @@ -861,7 +970,7 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { mode = afe_get_port_type(msm_bedais[i].port_id); adm_connect_afe_port(mode, dspst_id, msm_bedais[i].port_id); @@ -871,28 +980,51 @@ void msm_pcm_routing_reg_psthr_stream(int fedai_id, int dspst_id, mutex_unlock(&routing_lock); } +static bool route_check_fe_id_adm_support(int fe_id) +{ + bool rc = true; + + if ((fe_id >= MSM_FRONTEND_DAI_LSM1) && + (fe_id <= MSM_FRONTEND_DAI_LSM8)) { + /* fe id is listen while port is set to afe */ + if (lsm_port_index != ADM_LSM_PORT_INDEX) { + pr_debug("%s: fe_id %d, lsm mux slim port %d\n", + __func__, fe_id, lsm_port_index); + rc = false; + } + } + + return rc; +} + int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, int dspst_id, int stream_type, - uint32_t compr_passthr_mode) + uint32_t passthr_mode) { int i, j, session_type, path_type, port_type, topology, num_copps = 0; struct route_payload payload; u32 channels, sample_rate; u16 bit_width = 16; + bool is_lsm; pr_debug("%s:fe_id[%d] perf_mode[%d] id[%d] stream_type[%d] passt[%d]", __func__, fe_id, perf_mode, dspst_id, - stream_type, compr_passthr_mode); - - if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + stream_type, passthr_mode); + if (!is_mm_lsm_fe_id(fe_id)) { /* bad ID assigned in machine driver */ pr_err("%s: bad MM ID %d\n", __func__, fe_id); return -EINVAL; } + if (!route_check_fe_id_adm_support(fe_id)) { + /* ignore adm open if not supported for fe_id */ + pr_debug("%s: No ADM support for fe id %d\n", __func__, fe_id); + return 0; + } + if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) { session_type = SESSION_TYPE_RX; - if (compr_passthr_mode != LEGACY_PCM) + if (passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -906,6 +1038,8 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, return -EINVAL; } + is_lsm = (fe_id >= MSM_FRONTEND_DAI_LSM1) && + (fe_id <= MSM_FRONTEND_DAI_LSM8); mutex_lock(&routing_lock); payload.num_copps = 0; /* only RX needs to use payload */ @@ -913,14 +1047,14 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, /* re-enable EQ if active */ msm_qti_pp_send_eq_values(fe_id); for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) { - if (test_bit(fe_id, &msm_bedais[i].fe_sessions)) - msm_bedais[i].compr_passthr_mode = compr_passthr_mode; + if (test_bit(fe_id, &msm_bedais[i].fe_sessions[0])) + msm_bedais[i].passthr_mode = passthr_mode; if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fe_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fe_id, &msm_bedais[i].fe_sessions[0]))) { int app_type, app_type_idx, copp_idx, acdb_dev_id; /* @@ -936,7 +1070,15 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, msm_bedais[i].format); app_type = fe_dai_app_type_cfg[fe_id][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[fe_id][session_type]. + sample_rate; + bit_width = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx( app_type); @@ -951,9 +1093,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; topology = msm_routing_get_adm_topology(path_type, fe_id, session_type); - if (compr_passthr_mode == COMPRESSED_PASSTHROUGH_DSD) + + if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD) topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY; - pr_err("%s: Before adm open topology %d\n", __func__, + pr_debug("%s: Before adm open topology %d\n", __func__, topology); copp_idx = @@ -990,7 +1133,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, num_copps++; } } - if (compr_passthr_mode != COMPRESSED_PASSTHROUGH_DSD) { + if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD) { msm_routing_send_device_pp_params( msm_bedais[i].port_id, copp_idx); @@ -1004,7 +1147,9 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg[fe_id][session_type].app_type; payload.acdb_dev_id = fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id; - adm_matrix_map(path_type, payload, perf_mode); + payload.sample_rate = + fe_dai_app_type_cfg[fe_id][session_type].sample_rate; + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } mutex_unlock(&routing_lock); @@ -1055,6 +1200,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, struct route_payload payload; u32 channels, sample_rate; uint16_t bits_per_sample = 16; + uint32_t passthr_mode = LEGACY_PCM; if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { /* bad ID assigned in machine driver */ @@ -1084,7 +1230,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { int app_type, app_type_idx, copp_idx, acdb_dev_id; /* * check if ADM needs to be configured with different @@ -1094,7 +1240,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, channels = msm_bedais[i].channel; else channels = msm_bedais[i].adm_override_ch; - msm_bedais[i].compr_passthr_mode = + msm_bedais[i].passthr_mode = LEGACY_PCM; bits_per_sample = msm_routing_get_bit_width( @@ -1151,7 +1297,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, } } if ((perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[i].compr_passthr_mode == + (msm_bedais[i].passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(msm_bedais[i].port_id, copp_idx, topology, @@ -1167,7 +1313,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id; payload.sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate; - adm_matrix_map(path_type, payload, perf_mode); + adm_matrix_map(path_type, payload, perf_mode, passthr_mode); msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode); } mutex_unlock(&routing_lock); @@ -1196,7 +1342,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) int i, port_type, session_type, path_type, topology; struct msm_pcm_routing_fdai_data *fdai; - if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fedai_id)) { /* bad ID assigned in machine driver */ pr_err("%s: bad MM ID\n", __func__); return; @@ -1217,7 +1363,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) if (!is_be_dai_extproc(i) && (afe_get_port_type(msm_bedais[i].port_id) == port_type) && (msm_bedais[i].active) && - (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) { + (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0]))) { int idx; unsigned long copp = session_copp_map[fedai_id][session_type][i]; @@ -1242,7 +1388,7 @@ void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type) if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology || DS2_ADM_COPP_TOPOLOGY_ID == topology) && (fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[i].compr_passthr_mode == + (msm_bedais[i].passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp(msm_bedais[i].port_id, topology); @@ -1259,13 +1405,13 @@ static bool msm_pcm_routing_route_is_set(u16 be_id, u16 fe_id) { bool rc = false; - if (fe_id > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(fe_id)) { /* recheck FE ID in the mixer control defined in this file */ pr_err("%s: bad MM ID\n", __func__); return rc; } - if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions)) + if (test_bit(fe_id, &msm_bedais[be_id].fe_sessions[0])) rc = true; return rc; @@ -1277,19 +1423,27 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) u32 channels, sample_rate; uint16_t bits_per_sample = 16; struct msm_pcm_routing_fdai_data *fdai; + uint32_t passthr_mode = msm_bedais[reg].passthr_mode; + bool is_lsm; pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set); - if (val > MSM_FRONTEND_DAI_MM_MAX_ID) { + if (!is_mm_lsm_fe_id(val)) { /* recheck FE ID in the mixer control defined in this file */ pr_err("%s: bad MM ID\n", __func__); return; } + if (!route_check_fe_id_adm_support(val)) { + /* ignore adm open if not supported for fe_id */ + pr_debug("%s: No ADM support for fe id %d\n", __func__, val); + return; + } + if (afe_get_port_type(msm_bedais[reg].port_id) == MSM_AFE_PORT_TYPE_RX) { session_type = SESSION_TYPE_RX; - if (msm_bedais[reg].compr_passthr_mode != LEGACY_PCM) + if (passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -1297,15 +1451,17 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) session_type = SESSION_TYPE_TX; path_type = ADM_PATH_LIVE_REC; } + is_lsm = (val >= MSM_FRONTEND_DAI_LSM1) && + (val <= MSM_FRONTEND_DAI_LSM8); mutex_lock(&routing_lock); if (set) { - if (!test_bit(val, &msm_bedais[reg].fe_sessions) && + if (!test_bit(val, &msm_bedais[reg].fe_sessions[0]) && ((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) || (msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX))) voc_start_playback(set, msm_bedais[reg].port_id); - set_bit(val, &msm_bedais[reg].fe_sessions); + set_bit(val, &msm_bedais[reg].fe_sessions[0]); fdai = &fe_dai_map[val][session_type]; if (msm_bedais[reg].active && fdai->strm_id != INVALID_SESSION) { @@ -1336,7 +1492,15 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) app_type = fe_dai_app_type_cfg[val][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[val][session_type]. + sample_rate; + bits_per_sample = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = @@ -1381,20 +1545,20 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) msm_pcm_routing_build_matrix(val, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + passthr_mode); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[reg].compr_passthr_mode == - LEGACY_PCM)) + (passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(msm_bedais[reg].port_id, copp_idx, topology, channels); } } else { - if (test_bit(val, &msm_bedais[reg].fe_sessions) && + if (test_bit(val, &msm_bedais[reg].fe_sessions[0]) && ((msm_bedais[reg].port_id == VOICE_PLAYBACK_TX) || (msm_bedais[reg].port_id == VOICE2_PLAYBACK_TX))) voc_start_playback(set, msm_bedais[reg].port_id); - clear_bit(val, &msm_bedais[reg].fe_sessions); + clear_bit(val, &msm_bedais[reg].fe_sessions[0]); fdai = &fe_dai_map[val][session_type]; if (msm_bedais[reg].active && fdai->strm_id != INVALID_SESSION) { @@ -1419,14 +1583,14 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set) if ((DOLBY_ADM_COPP_TOPOLOGY_ID == topology || DS2_ADM_COPP_TOPOLOGY_ID == topology) && (fdai->perf_mode == LEGACY_PCM_MODE) && - (msm_bedais[reg].compr_passthr_mode == - LEGACY_PCM)) + (passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp( msm_bedais[reg].port_id, topology); msm_pcm_routing_build_matrix(val, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + passthr_mode); } } if ((msm_bedais[reg].port_id == VOICE_RECORD_RX) @@ -1442,7 +1606,7 @@ static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1476,6 +1640,51 @@ static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol, return 1; } +static int msm_routing_get_listen_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) + ucontrol->value.integer.value[0] = 1; + else + ucontrol->value.integer.value[0] = 0; + + pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift, + ucontrol->value.integer.value[0]); + + return 0; +} + +static int msm_routing_put_listen_mixer(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_widget_list *wlist = + dapm_kcontrol_get_wlist(kcontrol); + struct snd_soc_dapm_widget *widget = wlist->widgets[0]; + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + + pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift, + ucontrol->value.integer.value[0]); + + if (ucontrol->value.integer.value[0]) { + if (msm_pcm_routing_route_is_set(mc->reg, mc->shift) == false) + msm_pcm_routing_process_audio(mc->reg, mc->shift, 1); + snd_soc_dapm_mixer_update_power(widget->dapm, + kcontrol, 1, update); + } else if (!ucontrol->value.integer.value[0]) { + if (msm_pcm_routing_route_is_set(mc->reg, mc->shift) == true) + msm_pcm_routing_process_audio(mc->reg, mc->shift, 0); + snd_soc_dapm_mixer_update_power(widget->dapm, + kcontrol, 0, update); + } + + return 1; +} + static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) { u32 session_id = 0; @@ -1492,9 +1701,9 @@ static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) mutex_lock(&routing_lock); if (set) - set_bit(val, &msm_bedais[reg].fe_sessions); + set_bit(val, &msm_bedais[reg].fe_sessions[0]); else - clear_bit(val, &msm_bedais[reg].fe_sessions); + clear_bit(val, &msm_bedais[reg].fe_sessions[0]); if (val == MSM_FRONTEND_DAI_DTMF_RX && afe_get_port_type(msm_bedais[reg].port_id) == @@ -1553,7 +1762,7 @@ static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol, mutex_lock(&routing_lock); - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1595,7 +1804,7 @@ static int msm_routing_get_voice_stub_mixer(struct snd_kcontrol *kcontrol, mutex_lock(&routing_lock); - if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions)) + if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0])) ucontrol->value.integer.value[0] = 1; else ucontrol->value.integer.value[0] = 0; @@ -1620,13 +1829,13 @@ static int msm_routing_put_voice_stub_mixer(struct snd_kcontrol *kcontrol, if (ucontrol->value.integer.value[0]) { mutex_lock(&routing_lock); - set_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions); + set_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0]); mutex_unlock(&routing_lock); snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 1, update); } else { mutex_lock(&routing_lock); - clear_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions); + clear_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions[0]); mutex_unlock(&routing_lock); snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, 0, update); @@ -1928,23 +2137,19 @@ static int msm_routing_put_fm_pcmrx_switch_mixer(struct snd_kcontrol *kcontrol, return 1; } -static int msm_routing_lsm_mux_get(struct snd_kcontrol *kcontrol, +static int msm_routing_lsm_port_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - ucontrol->value.integer.value[0] = lsm_mux_slim_port; + ucontrol->value.integer.value[0] = lsm_port_index; return 0; } -static int msm_routing_lsm_mux_put(struct snd_kcontrol *kcontrol, +static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget_list *wlist = - dapm_kcontrol_get_wlist(kcontrol); - struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int mux = ucontrol->value.enumerated.item[0]; int lsm_port = AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX; - struct snd_soc_dapm_update *update = NULL; if (mux >= e->items) { pr_err("%s: Invalid mux value %d\n", __func__, mux); @@ -1975,19 +2180,18 @@ static int msm_routing_lsm_mux_put(struct snd_kcontrol *kcontrol, case 7: lsm_port = AFE_PORT_ID_TERTIARY_MI2S_TX; break; + case 8: + lsm_port = AFE_PORT_ID_QUATERNARY_MI2S_TX; + break; + case 9: + lsm_port = ADM_LSM_PORT_ID; + break; default: pr_err("Default lsm port"); break; } set_lsm_port(lsm_port); - - if (ucontrol->value.integer.value[0]) { - lsm_mux_slim_port = ucontrol->value.integer.value[0]; - snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); - } else { - snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); - lsm_mux_slim_port = ucontrol->value.integer.value[0]; - } + lsm_port_index = ucontrol->value.integer.value[0]; return 0; } @@ -2000,23 +2204,27 @@ static int msm_routing_lsm_func_get(struct snd_kcontrol *kcontrol, enum afe_mad_type mad_type; pr_debug("%s: enter\n", __func__); - for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++) - if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i], - strlen(mad_audio_mux_text[i]))) + for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++) + if (!strnstr(kcontrol->id.name, lsm_port_text[i], + strlen(lsm_port_text[i]))) break; - if (i-- == ARRAY_SIZE(mad_audio_mux_text)) { + if (i-- == ARRAY_SIZE(lsm_port_text)) { WARN(1, "Invalid id name %s\n", kcontrol->id.name); return -EINVAL; } /*Check for Tertiary TX port*/ - if (!strcmp(kcontrol->id.name, mad_audio_mux_text[7])) { + if (!strcmp(kcontrol->id.name, lsm_port_text[7])) { ucontrol->value.integer.value[0] = MADSWAUDIO; return 0; } port_id = i * 2 + 1 + SLIMBUS_0_RX; + + if (!strcmp(kcontrol->id.name, lsm_port_text[8])) + port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + mad_type = afe_port_get_mad_type(port_id); pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, mad_type); @@ -2051,12 +2259,12 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol, enum afe_mad_type mad_type; pr_debug("%s: enter\n", __func__); - for (i = 0; i < ARRAY_SIZE(mad_audio_mux_text); i++) - if (!strncmp(kcontrol->id.name, mad_audio_mux_text[i], - strlen(mad_audio_mux_text[i]))) + for (i = 0; i < ARRAY_SIZE(lsm_port_text); i++) + if (strnstr(kcontrol->id.name, lsm_port_text[i], + strlen(lsm_port_text[i]))) break; - if (i-- == ARRAY_SIZE(mad_audio_mux_text)) { + if (i-- == ARRAY_SIZE(lsm_port_text)) { WARN(1, "Invalid id name %s\n", kcontrol->id.name); return -EINVAL; } @@ -2084,11 +2292,16 @@ static int msm_routing_lsm_func_put(struct snd_kcontrol *kcontrol, } /*Check for Tertiary TX port*/ - if (!strcmp(kcontrol->id.name, mad_audio_mux_text[7])) { + if (strnstr(kcontrol->id.name, lsm_port_text[7], + strlen(lsm_port_text[7]))) { port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; mad_type = MAD_SW_AUDIO; } + if (strnstr(kcontrol->id.name, lsm_port_text[8], + strlen(lsm_port_text[8]))) + port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, mad_type); return afe_port_set_mad_type(port_id, mad_type); @@ -2253,6 +2466,144 @@ static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol, return 1; } +static int msm_ec_ref_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = msm_ec_ref_ch; + pr_debug("%s: msm_ec_ref_ch = %ld\n", __func__, + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_ec_ref_ch = ucontrol->value.integer.value[0]; + pr_debug("%s: msm_ec_ref_ch = %d\n", __func__, msm_ec_ref_ch); + adm_num_ec_ref_rx_chans(msm_ec_ref_ch); + return 0; +} + +static const char *const ec_ref_ch_text[] = {"Zero", "One", "Two", "Three", + "Four", "Five", "Six", "Seven", "Eight"}; + +static int msm_ec_ref_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_ec_ref_bit_format) { + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 2; + break; + case SNDRV_PCM_FORMAT_S16_LE: + ucontrol->value.integer.value[0] = 1; + break; + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("%s: msm_ec_ref_bit_format = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + u16 bit_width = 0; + + switch (ucontrol->value.integer.value[0]) { + case 2: + msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 1: + msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + default: + msm_ec_ref_bit_format = 0; + break; + } + + if (msm_ec_ref_bit_format == SNDRV_PCM_FORMAT_S16_LE) + bit_width = 16; + else if (msm_ec_ref_bit_format == SNDRV_PCM_FORMAT_S24_LE) + bit_width = 24; + + pr_debug("%s: msm_ec_ref_bit_format = %d\n", + __func__, msm_ec_ref_bit_format); + adm_ec_ref_rx_bit_width(bit_width); + return 0; +} + +static char const *ec_ref_bit_format_text[] = {"0", "S16_LE", "S24_LE"}; + +static int msm_ec_ref_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = msm_ec_ref_sampling_rate; + pr_debug("%s: msm_ec_ref_sampling_rate = %ld\n", + __func__, ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_ec_ref_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 0: + msm_ec_ref_sampling_rate = 0; + break; + case 1: + msm_ec_ref_sampling_rate = 8000; + break; + case 2: + msm_ec_ref_sampling_rate = 16000; + break; + case 3: + msm_ec_ref_sampling_rate = 32000; + break; + case 4: + msm_ec_ref_sampling_rate = 44100; + break; + case 5: + msm_ec_ref_sampling_rate = 48000; + break; + case 6: + msm_ec_ref_sampling_rate = 96000; + break; + case 7: + msm_ec_ref_sampling_rate = 192000; + break; + case 8: + msm_ec_ref_sampling_rate = 384000; + break; + default: + msm_ec_ref_sampling_rate = 48000; + break; + } + pr_debug("%s: msm_ec_ref_sampling_rate = %d\n", + __func__, msm_ec_ref_sampling_rate); + adm_ec_ref_rx_sampling_rate(msm_ec_ref_sampling_rate); + return 0; +} + +static const char *const ec_ref_rate_text[] = {"0", "8000", "16000", + "32000", "44100", "48000", "96000", "192000", "384000"}; + +static const struct soc_enum msm_route_ec_ref_params_enum[] = { + SOC_ENUM_SINGLE_EXT(9, ec_ref_ch_text), + SOC_ENUM_SINGLE_EXT(3, ec_ref_bit_format_text), + SOC_ENUM_SINGLE_EXT(9, ec_ref_rate_text), +}; + +static const struct snd_kcontrol_new ec_ref_param_controls[] = { + SOC_ENUM_EXT("EC Reference Channels", msm_route_ec_ref_params_enum[0], + msm_ec_ref_ch_get, msm_ec_ref_ch_put), + SOC_ENUM_EXT("EC Reference Bit Format", msm_route_ec_ref_params_enum[1], + msm_ec_ref_bit_format_get, msm_ec_ref_bit_format_put), + SOC_ENUM_EXT("EC Reference SampleRate", msm_route_ec_ref_params_enum[2], + msm_ec_ref_rate_get, msm_ec_ref_rate_put), +}; + static int msm_routing_ec_ref_rx_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -4164,6 +4515,159 @@ static const struct snd_kcontrol_new pri_tdm_rx_0_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new pri_tdm_rx_1_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new pri_tdm_rx_2_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new pri_tdm_rx_3_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new pri_tdm_tx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -4266,6 +4770,159 @@ static const struct snd_kcontrol_new sec_tdm_rx_0_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new sec_tdm_rx_1_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_2_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_3_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new sec_tdm_tx_0_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -4894,6 +5551,30 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = { SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -4966,6 +5647,30 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = { SOC_SINGLE_EXT("QUIN_MI2S_TX", MSM_BACKEND_DAI_QUINARY_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5038,6 +5743,30 @@ static const struct snd_kcontrol_new mmul3_mixer_controls[] = { SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5089,6 +5818,30 @@ static const struct snd_kcontrol_new mmul4_mixer_controls[] = { SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_1", MSM_BACKEND_DAI_TERT_TDM_TX_1, MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5170,6 +5923,30 @@ static const struct snd_kcontrol_new mmul5_mixer_controls[] = { SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5248,6 +6025,30 @@ static const struct snd_kcontrol_new mmul6_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -5317,6 +6118,30 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = { SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_TX_0, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0, MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -7146,6 +7971,542 @@ static const struct snd_kcontrol_new quat_mi2s_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new pri_tdm_rx_0_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new pri_tdm_rx_1_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new pri_tdm_rx_2_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new pri_tdm_rx_3_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_0_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SEC_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SEC_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SEC_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_SEC_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_0, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_1_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SEC_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SEC_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SEC_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_SEC_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_1, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_2_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SEC_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SEC_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SEC_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_SEC_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_2, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + +static const struct snd_kcontrol_new sec_tdm_rx_3_port_mixer_controls[] = { + SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SEC_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SEC_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SEC_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("SEC_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_SEC_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_0", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_1", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_2", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_SEC_TDM_RX_3, + MSM_BACKEND_DAI_QUAT_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), +}; + static const struct snd_kcontrol_new tert_tdm_rx_0_port_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_TERT_TDM_RX_0, MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, @@ -7721,6 +9082,198 @@ static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = { msm_routing_put_port_mixer), }; +static const struct snd_kcontrol_new lsm1_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm2_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm3_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm4_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm5_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm6_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm7_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + +static const struct snd_kcontrol_new lsm8_mixer_controls[] = { + SOC_SINGLE_EXT("SLIMBUS_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("SLIMBUS_5_TX", MSM_BACKEND_DAI_SLIMBUS_5_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), +}; + static const struct snd_kcontrol_new slim_fm_switch_mixer_controls = SOC_SINGLE_EXT("Switch", SND_SOC_NOPM, 0, 1, 0, msm_routing_get_switch_mixer, @@ -7806,53 +9359,17 @@ static const struct snd_kcontrol_new usb_switch_mixer_controls = 0, 1, 0, msm_routing_get_usb_switch_mixer, msm_routing_put_usb_switch_mixer); -static const struct soc_enum lsm_mux_enum = - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mad_audio_mux_text), mad_audio_mux_text); - -static const struct snd_kcontrol_new lsm1_mux = - SOC_DAPM_ENUM_EXT("LSM1 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm2_mux = - SOC_DAPM_ENUM_EXT("LSM2 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm3_mux = - SOC_DAPM_ENUM_EXT("LSM3 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm4_mux = - SOC_DAPM_ENUM_EXT("LSM4 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm5_mux = - SOC_DAPM_ENUM_EXT("LSM5 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm6_mux = - SOC_DAPM_ENUM_EXT("LSM6 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); -static const struct snd_kcontrol_new lsm7_mux = - SOC_DAPM_ENUM_EXT("LSM7 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - -static const struct snd_kcontrol_new lsm8_mux = - SOC_DAPM_ENUM_EXT("LSM8 MUX", lsm_mux_enum, - msm_routing_lsm_mux_get, - msm_routing_lsm_mux_put); - +static const struct soc_enum lsm_port_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_port_text), lsm_port_text); static const char * const lsm_func_text[] = { "None", "AUDIO", "BEACON", "ULTRASOUND", "SWAUDIO", }; static const struct soc_enum lsm_func_enum = SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lsm_func_text), lsm_func_text); -static const struct snd_kcontrol_new lsm_function[] = { + +static const struct snd_kcontrol_new lsm_controls[] = { + /* kcontrol of lsm_function */ SOC_ENUM_EXT(SLIMBUS_0_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, msm_routing_lsm_func_get, msm_routing_lsm_func_put), SOC_ENUM_EXT(SLIMBUS_1_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, @@ -7867,6 +9384,33 @@ static const struct snd_kcontrol_new lsm_function[] = { msm_routing_lsm_func_get, msm_routing_lsm_func_put), SOC_ENUM_EXT(TERT_MI2S_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, msm_routing_lsm_func_get, msm_routing_lsm_func_put), + SOC_ENUM_EXT(QUAT_MI2S_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, + msm_routing_lsm_func_get, msm_routing_lsm_func_put), + /* kcontrol of lsm_port */ + SOC_ENUM_EXT("LSM1 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM2 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM3 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM4 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM5 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM6 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM7 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), + SOC_ENUM_EXT("LSM8 Port", lsm_port_enum, + msm_routing_lsm_port_get, + msm_routing_lsm_port_put), }; static const char * const aanc_slim_0_rx_text[] = { @@ -7923,7 +9467,7 @@ static int msm_routing_put_stereo_to_custom_stereo_control( (port_id != AFE_PORT_ID_INT4_MI2S_RX)) continue; - for_each_set_bit(i, &msm_bedais[be_index].fe_sessions, + for_each_set_bit(i, &msm_bedais[be_index].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { if (fe_dai_map[i][SESSION_TYPE_RX].perf_mode != LEGACY_PCM_MODE) @@ -8029,6 +9573,45 @@ static const struct snd_kcontrol_new app_type_cfg_controls[] = { msm_routing_put_app_type_cfg_control), }; +static int msm_routing_get_lsm_app_type_cfg_control( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_routing_put_lsm_app_type_cfg_control( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int i = 0, j; + int num_app_types = ucontrol->value.integer.value[i++]; + + memset(lsm_app_type_cfg, 0, MAX_APP_TYPES* + sizeof(struct msm_pcm_routing_app_type_data)); + if (num_app_types > MAX_APP_TYPES) { + pr_err("%s: number of app types exceed the max supported\n", + __func__); + return -EINVAL; + } + for (j = 0; j < num_app_types; j++) { + lsm_app_type_cfg[j].app_type = + ucontrol->value.integer.value[i++]; + lsm_app_type_cfg[j].sample_rate = + ucontrol->value.integer.value[i++]; + lsm_app_type_cfg[j].bit_width = + ucontrol->value.integer.value[i++]; + } + + return 0; +} + +static const struct snd_kcontrol_new lsm_app_type_cfg_controls[] = { + SOC_SINGLE_MULTI_EXT("Listen App Type Config", SND_SOC_NOPM, 0, + 0xFFFFFFFF, 0, 128, msm_routing_get_lsm_app_type_cfg_control, + msm_routing_put_lsm_app_type_cfg_control), +}; + static int msm_routing_get_use_ds1_or_ds2_control( struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -8224,7 +9807,7 @@ static int msm_audio_get_copp_idx_from_port_id(int port_id, int session_type, goto done; } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions, + for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { copp = session_copp_map[i] @@ -9298,16 +10881,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_SWITCH("USB_DL_HL", SND_SOC_NOPM, 0, 0, &usb_switch_mixer_controls), - /* Mux Definitions */ - SND_SOC_DAPM_MUX("LSM1 MUX", SND_SOC_NOPM, 0, 0, &lsm1_mux), - SND_SOC_DAPM_MUX("LSM2 MUX", SND_SOC_NOPM, 0, 0, &lsm2_mux), - SND_SOC_DAPM_MUX("LSM3 MUX", SND_SOC_NOPM, 0, 0, &lsm3_mux), - SND_SOC_DAPM_MUX("LSM4 MUX", SND_SOC_NOPM, 0, 0, &lsm4_mux), - SND_SOC_DAPM_MUX("LSM5 MUX", SND_SOC_NOPM, 0, 0, &lsm5_mux), - SND_SOC_DAPM_MUX("LSM6 MUX", SND_SOC_NOPM, 0, 0, &lsm6_mux), - SND_SOC_DAPM_MUX("LSM7 MUX", SND_SOC_NOPM, 0, 0, &lsm7_mux), - SND_SOC_DAPM_MUX("LSM8 MUX", SND_SOC_NOPM, 0, 0, &lsm8_mux), - /* Mixer definitions */ SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0, pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)), @@ -9356,12 +10929,30 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("PRI_TDM_RX_0 Audio Mixer", SND_SOC_NOPM, 0, 0, pri_tdm_rx_0_mixer_controls, ARRAY_SIZE(pri_tdm_rx_0_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_1_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_1_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_2_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_2_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_3_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_3_mixer_controls)), SND_SOC_DAPM_MIXER("PRI_TDM_TX_0 Audio Mixer", SND_SOC_NOPM, 0, 0, pri_tdm_tx_0_mixer_controls, ARRAY_SIZE(pri_tdm_tx_0_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_TDM_RX_0 Audio Mixer", SND_SOC_NOPM, 0, 0, sec_tdm_rx_0_mixer_controls, ARRAY_SIZE(sec_tdm_rx_0_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_1_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_1_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_2_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_2_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_3_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_3_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_TDM_TX_0 Audio Mixer", SND_SOC_NOPM, 0, 0, sec_tdm_tx_0_mixer_controls, ARRAY_SIZE(sec_tdm_tx_0_mixer_controls)), @@ -9626,6 +11217,30 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, quat_mi2s_rx_port_mixer_controls, ARRAY_SIZE(quat_mi2s_rx_port_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_0_port_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_0_port_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_1 Port Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_1_port_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_1_port_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_2 Port Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_2_port_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_2_port_mixer_controls)), + SND_SOC_DAPM_MIXER("PRI_TDM_RX_3 Port Mixer", SND_SOC_NOPM, 0, 0, + pri_tdm_rx_3_port_mixer_controls, + ARRAY_SIZE(pri_tdm_rx_3_port_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_0_port_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_0_port_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_1 Port Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_1_port_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_1_port_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_2 Port Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_2_port_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_2_port_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_TDM_RX_3 Port Mixer", SND_SOC_NOPM, 0, 0, + sec_tdm_rx_3_port_mixer_controls, + ARRAY_SIZE(sec_tdm_rx_3_port_mixer_controls)), SND_SOC_DAPM_MIXER("TERT_TDM_RX_0 Port Mixer", SND_SOC_NOPM, 0, 0, tert_tdm_rx_0_port_mixer_controls, ARRAY_SIZE(tert_tdm_rx_0_port_mixer_controls)), @@ -9665,6 +11280,23 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("USB_AUDIO_RX Port Mixer", SND_SOC_NOPM, 0, 0, usb_rx_port_mixer_controls, ARRAY_SIZE(usb_rx_port_mixer_controls)), + /* lsm mixer definitions */ + SND_SOC_DAPM_MIXER("LSM1 Mixer", SND_SOC_NOPM, 0, 0, + lsm1_mixer_controls, ARRAY_SIZE(lsm1_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM2 Mixer", SND_SOC_NOPM, 0, 0, + lsm2_mixer_controls, ARRAY_SIZE(lsm2_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM3 Mixer", SND_SOC_NOPM, 0, 0, + lsm3_mixer_controls, ARRAY_SIZE(lsm3_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM4 Mixer", SND_SOC_NOPM, 0, 0, + lsm4_mixer_controls, ARRAY_SIZE(lsm4_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM5 Mixer", SND_SOC_NOPM, 0, 0, + lsm5_mixer_controls, ARRAY_SIZE(lsm5_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM6 Mixer", SND_SOC_NOPM, 0, 0, + lsm6_mixer_controls, ARRAY_SIZE(lsm6_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM7 Mixer", SND_SOC_NOPM, 0, 0, + lsm7_mixer_controls, ARRAY_SIZE(lsm7_mixer_controls)), + SND_SOC_DAPM_MIXER("LSM8 Mixer", SND_SOC_NOPM, 0, 0, + lsm8_mixer_controls, ARRAY_SIZE(lsm8_mixer_controls)), /* Virtual Pins to force backends ON atm */ SND_SOC_DAPM_OUTPUT("BE_OUT"), SND_SOC_DAPM_INPUT("BE_IN"), @@ -10109,6 +11741,60 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Audio Mixer"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"PRI_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"PRI_TDM_RX_1", NULL, "PRI_TDM_RX_1 Audio Mixer"}, + + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"PRI_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"PRI_TDM_RX_2", NULL, "PRI_TDM_RX_2 Audio Mixer"}, + + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"PRI_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"PRI_TDM_RX_3", NULL, "PRI_TDM_RX_3 Audio Mixer"}, + {"PRI_TDM_TX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, {"PRI_TDM_TX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, {"PRI_TDM_TX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -10145,6 +11831,60 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Audio Mixer"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_TDM_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_TDM_RX_1", NULL, "SEC_TDM_RX_1 Audio Mixer"}, + + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_TDM_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_TDM_RX_2", NULL, "SEC_TDM_RX_2 Audio Mixer"}, + + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_TDM_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3 Audio Mixer"}, + {"SEC_TDM_TX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, {"SEC_TDM_TX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, {"SEC_TDM_TX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -10392,6 +12132,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia6 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"MultiMedia6 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"MultiMedia1 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia1 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia1 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia1 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia1 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia1 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia1 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia1 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia1 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia1 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia1 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10401,6 +12149,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia1 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia1 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia2 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia2 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia2 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia2 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia2 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia2 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia2 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia2 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia2 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia2 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia2 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10410,6 +12166,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia2 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia2 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia3 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia3 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia3 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia3 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia3 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia3 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia3 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia3 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia3 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia3 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia3 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10419,6 +12183,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia3 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia3 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia4 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia4 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia4 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia4 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia4 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia4 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia4 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia4 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia4 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia4 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia4 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10428,6 +12200,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia4 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia4 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia5 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia5 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia5 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia5 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia5 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia5 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia5 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia5 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia5 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia5 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia5 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10437,6 +12217,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia5 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia5 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia6 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia6 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia6 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia6 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia6 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia6 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia6 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia6 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia6 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia6 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia6 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -10446,6 +12234,14 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia6 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia6 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia8 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"MultiMedia8 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"MultiMedia8 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"MultiMedia8 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"MultiMedia8 Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"MultiMedia8 Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"MultiMedia8 Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"MultiMedia8 Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, {"MultiMedia8 Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"MultiMedia8 Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"MultiMedia8 Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -11124,70 +12920,77 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIM4_UL_HL", NULL, "SLIMBUS_4_TX"}, {"SLIM8_UL_HL", NULL, "SLIMBUS_8_TX"}, - {"LSM1 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM1 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM1 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM1 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM1 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM1 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM1_UL_HL", NULL, "LSM1 MUX"}, - - {"LSM2 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM2 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM2 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM2 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM2 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM2 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM2_UL_HL", NULL, "LSM2 MUX"}, - - - {"LSM3 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM3 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM3 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM3 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM3 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM3 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM3_UL_HL", NULL, "LSM3 MUX"}, - - - {"LSM4 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM4 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM4 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM4 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM4 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM4 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM4_UL_HL", NULL, "LSM4 MUX"}, - - {"LSM5 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM5 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM5 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM5 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM5 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM5 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"}, - {"LSM5_UL_HL", NULL, "LSM5 MUX"}, - - {"LSM6 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM6 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM6 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM6 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM6 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM6_UL_HL", NULL, "LSM6 MUX"}, - - - {"LSM7 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM7 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM7 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM7 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM7 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM7_UL_HL", NULL, "LSM7 MUX"}, - - - {"LSM8 MUX", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, - {"LSM8 MUX", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, - {"LSM8 MUX", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, - {"LSM8 MUX", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, - {"LSM8 MUX", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, - {"LSM8_UL_HL", NULL, "LSM8 MUX"}, + + {"LSM1 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM1 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM1 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM1 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM1 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM1_UL_HL", NULL, "LSM1 Mixer"}, + + {"LSM2 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM2 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM2 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM2 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM2 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM2_UL_HL", NULL, "LSM2 Mixer"}, + + + {"LSM3 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM3 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM3 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM3 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM3 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM3 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM3_UL_HL", NULL, "LSM3 Mixer"}, + + + {"LSM4 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM4 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM4 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM4 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM4 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM4 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM4 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM4_UL_HL", NULL, "LSM4 Mixer"}, + + {"LSM5 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM5 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM5 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM5 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM5 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, + {"LSM5 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM5_UL_HL", NULL, "LSM5 Mixer"}, + + {"LSM6 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM6 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM6 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM6 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM6 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM6 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM6_UL_HL", NULL, "LSM6 Mixer"}, + + {"LSM7 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM7 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM7 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM7 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM7 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM7 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM7_UL_HL", NULL, "LSM7 Mixer"}, + + {"LSM8 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, + {"LSM8 Mixer", "SLIMBUS_1_TX", "SLIMBUS_1_TX"}, + {"LSM8 Mixer", "SLIMBUS_3_TX", "SLIMBUS_3_TX"}, + {"LSM8 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, + {"LSM8 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, + {"LSM8 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM8_UL_HL", NULL, "LSM8 Mixer"}, {"CPE_LSM_UL_HL", NULL, "BE_IN"}, @@ -11251,17 +13054,29 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_MI2S_UL_HL", NULL, "QUAT_MI2S_TX"}, {"PRI_TDM_TX_0_UL_HL", NULL, "PRI_TDM_TX_0"}, + {"PRI_TDM_TX_1_UL_HL", NULL, "PRI_TDM_TX_1"}, + {"PRI_TDM_TX_2_UL_HL", NULL, "PRI_TDM_TX_2"}, + {"PRI_TDM_TX_3_UL_HL", NULL, "PRI_TDM_TX_3"}, {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0_DL_HL"}, + {"PRI_TDM_RX_1", NULL, "PRI_TDM_RX_1_DL_HL"}, + {"PRI_TDM_RX_2", NULL, "PRI_TDM_RX_2_DL_HL"}, + {"PRI_TDM_RX_3", NULL, "PRI_TDM_RX_3_DL_HL"}, {"SEC_TDM_TX_0_UL_HL", NULL, "SEC_TDM_TX_0"}, + {"SEC_TDM_TX_1_UL_HL", NULL, "SEC_TDM_TX_1"}, + {"SEC_TDM_TX_2_UL_HL", NULL, "SEC_TDM_TX_2"}, + {"SEC_TDM_TX_3_UL_HL", NULL, "SEC_TDM_TX_3"}, {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0_DL_HL"}, + {"SEC_TDM_RX_1", NULL, "SEC_TDM_RX_1_DL_HL"}, + {"SEC_TDM_RX_2", NULL, "SEC_TDM_RX_2_DL_HL"}, + {"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3_DL_HL"}, {"TERT_TDM_TX_0_UL_HL", NULL, "TERT_TDM_TX_0"}, {"TERT_TDM_TX_1_UL_HL", NULL, "TERT_TDM_TX_1"}, {"TERT_TDM_TX_2_UL_HL", NULL, "TERT_TDM_TX_2"}, {"TERT_TDM_TX_3_UL_HL", NULL, "TERT_TDM_TX_3"}, {"TERT_TDM_RX_0", NULL, "TERT_TDM_RX_0_DL_HL"}, - {"TERT_TDM_RX_1", NULL, "TERT_TDM_RX_0_DL_HL"}, - {"TERT_TDM_RX_2", NULL, "TERT_TDM_RX_0_DL_HL"}, - {"TERT_TDM_RX_3", NULL, "TERT_TDM_RX_0_DL_HL"}, + {"TERT_TDM_RX_1", NULL, "TERT_TDM_RX_1_DL_HL"}, + {"TERT_TDM_RX_2", NULL, "TERT_TDM_RX_2_DL_HL"}, + {"TERT_TDM_RX_3", NULL, "TERT_TDM_RX_3_DL_HL"}, {"QUAT_TDM_TX_0_UL_HL", NULL, "QUAT_TDM_TX_0"}, {"QUAT_TDM_TX_1_UL_HL", NULL, "QUAT_TDM_TX_1"}, {"QUAT_TDM_TX_2_UL_HL", NULL, "QUAT_TDM_TX_2"}, @@ -11271,6 +13086,150 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_2", NULL, "QUAT_TDM_RX_2_DL_HL"}, {"QUAT_TDM_RX_3", NULL, "QUAT_TDM_RX_3_DL_HL"}, + {"PRI_TDM_RX_0 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"PRI_TDM_RX_0 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"PRI_TDM_RX_0 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"PRI_TDM_RX_0 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"PRI_TDM_RX_0 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"PRI_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"PRI_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"PRI_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"PRI_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Port Mixer"}, + + {"PRI_TDM_RX_1 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"PRI_TDM_RX_1 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"PRI_TDM_RX_1 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"PRI_TDM_RX_1 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"PRI_TDM_RX_1 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"PRI_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"PRI_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"PRI_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"PRI_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"PRI_TDM_RX_1", NULL, "PRI_TDM_RX_1 Port Mixer"}, + + {"PRI_TDM_RX_2 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"PRI_TDM_RX_2 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"PRI_TDM_RX_2 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"PRI_TDM_RX_2 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"PRI_TDM_RX_2 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"PRI_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"PRI_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"PRI_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"PRI_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"PRI_TDM_RX_2", NULL, "PRI_TDM_RX_2 Port Mixer"}, + + {"PRI_TDM_RX_3 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"PRI_TDM_RX_3 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"PRI_TDM_RX_3 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"PRI_TDM_RX_3 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"PRI_TDM_RX_3 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"PRI_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"PRI_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"PRI_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"PRI_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"PRI_TDM_RX_3", NULL, "PRI_TDM_RX_3 Port Mixer"}, + + {"SEC_TDM_RX_0 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"SEC_TDM_RX_0 Port Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, + {"SEC_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"SEC_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"SEC_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"SEC_TDM_RX_0 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Port Mixer"}, + + {"SEC_TDM_RX_1 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"SEC_TDM_RX_1 Port Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, + {"SEC_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"SEC_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"SEC_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"SEC_TDM_RX_1 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"SEC_TDM_RX_1", NULL, "SEC_TDM_RX_1 Port Mixer"}, + + {"SEC_TDM_RX_2 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"SEC_TDM_RX_2 Port Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, + {"SEC_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"SEC_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"SEC_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"SEC_TDM_RX_2 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"SEC_TDM_RX_2", NULL, "SEC_TDM_RX_2 Port Mixer"}, + + {"SEC_TDM_RX_3 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_TDM_TX_0", "SEC_TDM_TX_0"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_TDM_TX_1", "SEC_TDM_TX_1"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_TDM_TX_2", "SEC_TDM_TX_2"}, + {"SEC_TDM_RX_3 Port Mixer", "SEC_TDM_TX_3", "SEC_TDM_TX_3"}, + {"SEC_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_0", "QUAT_TDM_TX_0"}, + {"SEC_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, + {"SEC_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, + {"SEC_TDM_RX_3 Port Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"SEC_TDM_RX_3", NULL, "SEC_TDM_RX_3 Port Mixer"}, + {"TERT_TDM_RX_0 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"TERT_TDM_RX_0 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, {"TERT_TDM_RX_0 Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, @@ -11690,7 +13649,13 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "VOICE_PLAYBACK_TX"}, {"BE_OUT", NULL, "VOICE2_PLAYBACK_TX"}, {"BE_OUT", NULL, "PRI_TDM_RX_0"}, + {"BE_OUT", NULL, "PRI_TDM_RX_1"}, + {"BE_OUT", NULL, "PRI_TDM_RX_2"}, + {"BE_OUT", NULL, "PRI_TDM_RX_3"}, {"BE_OUT", NULL, "SEC_TDM_RX_0"}, + {"BE_OUT", NULL, "SEC_TDM_RX_1"}, + {"BE_OUT", NULL, "SEC_TDM_RX_2"}, + {"BE_OUT", NULL, "SEC_TDM_RX_3"}, {"BE_OUT", NULL, "TERT_TDM_RX_0"}, {"BE_OUT", NULL, "TERT_TDM_RX_1"}, {"BE_OUT", NULL, "TERT_TDM_RX_2"}, @@ -11746,7 +13711,13 @@ static const struct snd_soc_dapm_route intercon[] = { {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_VI_FB_MONO_CH_MUX"}, {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_VI_FB_STEREO_CH_MUX"}, {"PRI_TDM_TX_0", NULL, "BE_IN"}, + {"PRI_TDM_TX_1", NULL, "BE_IN"}, + {"PRI_TDM_TX_2", NULL, "BE_IN"}, + {"PRI_TDM_TX_3", NULL, "BE_IN"}, {"SEC_TDM_TX_0", NULL, "BE_IN"}, + {"SEC_TDM_TX_1", NULL, "BE_IN"}, + {"SEC_TDM_TX_2", NULL, "BE_IN"}, + {"SEC_TDM_TX_3", NULL, "BE_IN"}, {"TERT_TDM_TX_0", NULL, "BE_IN"}, {"TERT_TDM_TX_1", NULL, "BE_IN"}, {"TERT_TDM_TX_2", NULL, "BE_IN"}, @@ -11804,7 +13775,9 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream) path_type = ADM_PATH_LIVE_REC; mutex_lock(&routing_lock); - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { + if (!is_mm_lsm_fe_id(i)) + continue; fdai = &fe_dai_map[i][session_type]; if (fdai->strm_id != INVALID_SESSION) { int idx; @@ -11825,13 +13798,12 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream) clear_bit(idx, &session_copp_map[i][session_type][be_id]); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (bedai->compr_passthr_mode == LEGACY_PCM)) + (bedai->passthr_mode == LEGACY_PCM)) msm_pcm_routing_deinit_pp(bedai->port_id, topology); } } - bedai->compr_passthr_mode = LEGACY_PCM; bedai->active = 0; bedai->sample_rate = 0; bedai->channel = 0; @@ -11851,6 +13823,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) struct msm_pcm_routing_fdai_data *fdai; u32 session_id; struct media_format_info voc_be_media_format; + bool is_lsm; pr_debug("%s: substream->pcm->id:%s\n", __func__, substream->pcm->id); @@ -11863,7 +13836,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) bedai = &msm_bedais[be_id]; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (bedai->compr_passthr_mode != LEGACY_PCM) + if (bedai->passthr_mode != LEGACY_PCM) path_type = ADM_PATH_COMPRESSED_RX; else path_type = ADM_PATH_PLAYBACK; @@ -11884,7 +13857,13 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) */ bedai->active = 1; - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { + if (!(is_mm_lsm_fe_id(i) && + route_check_fe_id_adm_support(i))) + continue; + + is_lsm = (i >= MSM_FRONTEND_DAI_LSM1) && + (i <= MSM_FRONTEND_DAI_LSM8); fdai = &fe_dai_map[i][session_type]; if (fdai->strm_id != INVALID_SESSION) { int app_type, app_type_idx, copp_idx, acdb_dev_id; @@ -11906,7 +13885,15 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) app_type = fe_dai_app_type_cfg[i][session_type].app_type; - if (app_type) { + if (app_type && is_lsm) { + app_type_idx = + msm_pcm_routing_get_lsm_app_type_idx(app_type); + sample_rate = + fe_dai_app_type_cfg[i][session_type]. + sample_rate; + bits_per_sample = + lsm_app_type_cfg[app_type_idx].bit_width; + } else if (app_type) { app_type_idx = msm_pcm_routing_get_app_type_idx(app_type); sample_rate = @@ -11951,16 +13938,16 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) bedai->sample_rate); msm_pcm_routing_build_matrix(i, session_type, path_type, - fdai->perf_mode); + fdai->perf_mode, + bedai->passthr_mode); if ((fdai->perf_mode == LEGACY_PCM_MODE) && - (bedai->compr_passthr_mode == - LEGACY_PCM)) + (bedai->passthr_mode == LEGACY_PCM)) msm_pcm_routing_cfg_pp(bedai->port_id, copp_idx, topology, channels); } } - for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) { + for_each_set_bit(i, &bedai->fe_sessions[0], MSM_FRONTEND_DAI_MAX) { session_id = msm_pcm_routing_get_voc_sessionid(i); if (session_id) { pr_debug("%s voice session_id: 0x%x\n", __func__, @@ -12025,6 +14012,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) unsigned long pp_config = 0; bool mute_on; int latency; + bool compr_passthr_mode = true; pr_debug("%s: port_id %d, copp_idx %d\n", __func__, port_id, copp_idx); @@ -12061,14 +14049,16 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) return -EINVAL; } + if ((msm_bedais[be_idx].passthr_mode == LEGACY_PCM) || + (msm_bedais[be_idx].passthr_mode == LISTEN)) + compr_passthr_mode = false; + pp_config = msm_bedais_pp_params[index].pp_params_config; if (test_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config)) { pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); clear_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config); mute_on = msm_bedais_pp_params[index].mute_on; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, copp_idx, mute_on); @@ -12078,9 +14068,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx) clear_bit(ADM_PP_PARAM_LATENCY_BIT, &pp_config); latency = msm_bedais_pp_params[index].latency; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, copp_idx, latency); @@ -12096,6 +14084,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, int index, be_idx, i, topo_id, idx; bool mute; int latency; + bool compr_passthr_mode = true; pr_debug("%s: pp_id: 0x%x\n", __func__, pp_id); @@ -12120,7 +14109,11 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, return -EINVAL; } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions, + if ((msm_bedais[be_idx].passthr_mode == LEGACY_PCM) || + (msm_bedais[be_idx].passthr_mode == LISTEN)) + compr_passthr_mode = false; + + for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { unsigned long copp = @@ -12134,7 +14127,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, continue; pr_debug("%s: port: 0x%x, copp %ld, be active: %d, passt: %d\n", __func__, port_id, copp, msm_bedais[be_idx].active, - msm_bedais[be_idx].compr_passthr_mode); + msm_bedais[be_idx].passthr_mode); switch (pp_id) { case ADM_PP_PARAM_MUTE_ID: pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); @@ -12142,9 +14135,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, msm_bedais_pp_params[index].mute_on = mute; set_bit(ADM_PP_PARAM_MUTE_BIT, &msm_bedais_pp_params[index].pp_params_config); - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, idx, mute); break; @@ -12156,9 +14147,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, &msm_bedais_pp_params[index].pp_params_config); latency = msm_bedais_pp_params[index].latency = ucontrol->value.integer.value[1]; - if ((msm_bedais[be_idx].active) && - (msm_bedais[be_idx].compr_passthr_mode != - LEGACY_PCM)) + if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, idx, latency); break; @@ -12228,8 +14217,8 @@ static int msm_routing_probe(struct snd_soc_platform *platform) snd_soc_dapm_new_widgets(platform->component.dapm.card); - snd_soc_add_platform_controls(platform, lsm_function, - ARRAY_SIZE(lsm_function)); + snd_soc_add_platform_controls(platform, lsm_controls, + ARRAY_SIZE(lsm_controls)); snd_soc_add_platform_controls(platform, aanc_slim_0_rx_mux, ARRAY_SIZE(aanc_slim_0_rx_mux)); @@ -12240,10 +14229,16 @@ static int msm_routing_probe(struct snd_soc_platform *platform) snd_soc_add_platform_controls(platform, app_type_cfg_controls, ARRAY_SIZE(app_type_cfg_controls)); + snd_soc_add_platform_controls(platform, lsm_app_type_cfg_controls, + ARRAY_SIZE(lsm_app_type_cfg_controls)); + snd_soc_add_platform_controls(platform, stereo_to_custom_stereo_controls, ARRAY_SIZE(stereo_to_custom_stereo_controls)); + snd_soc_add_platform_controls(platform, ec_ref_param_controls, + ARRAY_SIZE(ec_ref_param_controls)); + msm_qti_pp_add_controls(platform); msm_dts_srs_tm_add_controls(platform); @@ -12326,7 +14321,7 @@ int msm_routing_check_backend_enabled(int fedai_id) return 0; } for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) { - if (test_bit(fedai_id, &msm_bedais[i].fe_sessions)) + if (test_bit(fedai_id, &msm_bedais[i].fe_sessions[0])) return msm_bedais[i].active; } return 0; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 0bb069154512..a066e9afc9e5 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -392,6 +392,7 @@ enum { #define ADM_PP_PARAM_LATENCY_ID 1 #define ADM_PP_PARAM_LATENCY_BIT 2 #define BE_DAI_PORT_SESSIONS_IDX_MAX 4 +#define BE_DAI_FE_SESSIONS_IDX_MAX 2 struct msm_pcm_routing_evt { void (*event_func)(enum msm_pcm_routing_event, void *); @@ -401,7 +402,9 @@ struct msm_pcm_routing_evt { struct msm_pcm_routing_bdai_data { u16 port_id; /* AFE port ID */ u8 active; /* track if this backend is enabled */ - unsigned long fe_sessions; /* Front-end sessions */ + + /* Front-end sessions */ + unsigned long fe_sessions[BE_DAI_FE_SESSIONS_IDX_MAX]; /* * Track Tx BE ports -> Rx BE ports. * port_sessions[0] used to track BE 0 to BE 63. @@ -415,7 +418,7 @@ struct msm_pcm_routing_bdai_data { unsigned int channel; unsigned int format; unsigned int adm_override_ch; - u32 compr_passthr_mode; + u32 passthr_mode; char *name; }; diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 32826d38f65a..16ae05034662 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -2574,7 +2574,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, return copp_idx; } - void adm_copp_mfc_cfg(int port_id, int copp_idx, int dst_sample_rate) { struct audproc_mfc_output_media_fmt mfc_cfg; @@ -2677,8 +2676,43 @@ fail_cmd: return; } +static void route_set_opcode_matrix_id( + struct adm_cmd_matrix_map_routings_v5 **route_addr, + int path, uint32_t passthr_mode) +{ + struct adm_cmd_matrix_map_routings_v5 *route = *route_addr; -int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode) + switch (path) { + case ADM_PATH_PLAYBACK: + route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; + break; + case ADM_PATH_LIVE_REC: + if (passthr_mode == LISTEN) { + route->hdr.opcode = + ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_LISTEN_TX; + break; + } + /* fall through to set matrix id for non-listen case */ + case ADM_PATH_NONLIVE_REC: + route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; + break; + case ADM_PATH_COMPRESSED_RX: + route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; + route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX; + break; + default: + pr_err("%s: Wrong path set[%d]\n", __func__, path); + break; + } + pr_debug("%s: opcode 0x%x, matrix id %d\n", + __func__, route->hdr.opcode, route->matrix_id); +} + +int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode, + uint32_t passthr_mode) { struct adm_cmd_matrix_map_routings_v5 *route; struct adm_session_map_node_v5 *node; @@ -2711,32 +2745,9 @@ int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode) route->hdr.dest_domain = APR_DOMAIN_ADSP; route->hdr.dest_port = 0; /* Ignored */; route->hdr.token = 0; - if (path == ADM_PATH_COMPRESSED_RX) { - pr_debug("%s: ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5 0x%x\n", - __func__, ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5); - route->hdr.opcode = ADM_CMD_STREAM_DEVICE_MAP_ROUTINGS_V5; - } else { - pr_debug("%s: DM_CMD_MATRIX_MAP_ROUTINGS_V5 0x%x\n", - __func__, ADM_CMD_MATRIX_MAP_ROUTINGS_V5); - route->hdr.opcode = ADM_CMD_MATRIX_MAP_ROUTINGS_V5; - } route->num_sessions = 1; + route_set_opcode_matrix_id(&route, path, passthr_mode); - switch (path) { - case ADM_PATH_PLAYBACK: - route->matrix_id = ADM_MATRIX_ID_AUDIO_RX; - break; - case ADM_PATH_LIVE_REC: - case ADM_PATH_NONLIVE_REC: - route->matrix_id = ADM_MATRIX_ID_AUDIO_TX; - break; - case ADM_PATH_COMPRESSED_RX: - route->matrix_id = ADM_MATRIX_ID_COMPRESSED_AUDIO_RX; - break; - default: - pr_err("%s: Wrong path set[%d]\n", __func__, path); - break; - } payload = ((u8 *)matrix_map + sizeof(struct adm_cmd_matrix_map_routings_v5)); node = (struct adm_session_map_node_v5 *)payload; diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index f1607b8e5d66..9a141a11d002 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -145,7 +145,7 @@ int afe_get_topology(int port_id) int topology; int port_index = afe_get_port_index(port_id); - if ((port_index < 0) || (port_index > AFE_MAX_PORTS)) { + if ((port_index < 0) || (port_index >= AFE_MAX_PORTS)) { pr_err("%s: Invalid port index %d\n", __func__, port_index); topology = -EINVAL; goto done; @@ -726,7 +726,7 @@ static int afe_send_cal_block(u16 port_id, struct cal_block_data *cal_block) } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); result = -EINVAL; @@ -870,7 +870,7 @@ static int afe_spk_ramp_dn_cfg(int port) goto fail_cmd; } index = q6audio_get_port_index(port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -951,7 +951,7 @@ static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id, goto fail_cmd; } index = q6audio_get_port_index(src_port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -1196,7 +1196,7 @@ static int afe_send_hw_delay(u16 port_id, u32 rate) } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -1318,7 +1318,7 @@ static int afe_send_port_topology_id(u16 port_id) u32 topology_id = 0; index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS - 1) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -1675,7 +1675,7 @@ static int afe_send_slimbus_slave_port_cfg( pr_debug("%s: enter, port_id = 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -1729,7 +1729,7 @@ static int afe_aanc_port_cfg(void *apr, uint16_t tx_port, uint16_t rx_port) } index = q6audio_get_port_index(tx_port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -1814,7 +1814,7 @@ static int afe_aanc_mod_enable(void *apr, uint16_t tx_port, uint16_t enable) } index = q6audio_get_port_index(tx_port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2036,7 +2036,7 @@ int afe_send_spdif_clk_cfg(struct afe_param_id_spdif_clk_cfg *cfg, return ret; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2122,7 +2122,7 @@ int afe_send_spdif_ch_status_cfg(struct afe_param_id_spdif_ch_status_cfg return ret; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2196,7 +2196,7 @@ static int afe_send_cmd_port_start(u16 port_id) pr_debug("%s: enter\n", __func__); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2267,7 +2267,7 @@ int afe_spdif_port_start(u16 port_id, struct afe_spdif_port_config *spdif_port, pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2342,7 +2342,7 @@ int afe_send_slot_mapping_cfg( pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2421,7 +2421,7 @@ int afe_send_custom_tdm_header_cfg( pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2501,7 +2501,7 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -2623,7 +2623,7 @@ int afe_port_send_usb_dev_param(u16 port_id, union afe_port_config *afe_config) goto exit; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid! for port ID 0x%x\n", __func__, index, port_id); ret = -EINVAL; @@ -2824,7 +2824,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3383,7 +3383,7 @@ int afe_open(u16 port_id, pr_err("%s: port_id 0x%x rate %d\n", __func__, port_id, rate); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3551,7 +3551,7 @@ int afe_loopback(u16 enable, u16 rx_port, u16 tx_port) } index = q6audio_get_port_index(rx_port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3617,7 +3617,7 @@ int afe_loopback_gain(u16 port_id, u16 volume) goto fail_cmd; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3720,7 +3720,7 @@ int afe_start_pseudo_port(u16 port_id) } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3763,7 +3763,7 @@ int afe_pseudo_port_stop_nowait(u16 port_id) return -EINVAL; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -3924,7 +3924,7 @@ int afe_stop_pseudo_port(u16 port_id) } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -4213,7 +4213,7 @@ int afe_cmd_memory_map_nowait(int port_id, phys_addr_t dma_addr_p, rtac_set_afe_handle(this_afe.apr); } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -4477,7 +4477,7 @@ int afe_unregister_get_events(u16 port_id) } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -4821,7 +4821,7 @@ int afe_dtmf_generate_rx(int64_t duration_in_ms, goto fail_cmd; } index = q6audio_get_port_index(this_afe.dtmf_gen_rx_portid); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -5059,7 +5059,7 @@ int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable) int index; index = q6audio_get_port_index(rx_port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -5072,7 +5072,7 @@ int afe_sidetone_enable(u16 tx_port_id, u16 rx_port_id, bool enable) goto done; } index = q6audio_get_port_index(tx_port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; @@ -5367,7 +5367,7 @@ int afe_close(int port_id) port_id = q6audio_convert_virtual_to_portid(port_id); index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -5525,7 +5525,7 @@ int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg) return ret; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -5691,7 +5691,7 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg) int ret = 0; index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -5724,7 +5724,7 @@ int afe_set_lpass_internal_digital_codec_clock(u16 port_id, return ret; } index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -5805,7 +5805,7 @@ int afe_enable_lpass_core_shared_clock(u16 port_id, u32 enable) int ret = 0; index = q6audio_get_port_index(port_id); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); return -EINVAL; @@ -6084,7 +6084,7 @@ int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) goto fail_cmd; } index = q6audio_get_port_index(port); - if (index < 0 || index > AFE_MAX_PORTS) { + if (index < 0 || index >= AFE_MAX_PORTS) { pr_err("%s: AFE port index[%d] invalid!\n", __func__, index); ret = -EINVAL; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 2c501ce3d6ff..74fbe984e6e9 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -8343,14 +8343,17 @@ int q6asm_get_apr_service_id(int session_id) int q6asm_get_asm_topology(int session_id) { - int topology; + int topology = -EINVAL; if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) { pr_err("%s: invalid session_id = %d\n", __func__, session_id); - topology = -EINVAL; goto done; } - + if (session[session_id] == NULL) { + pr_err("%s: session not created for session id = %d\n", + __func__, session_id); + goto done; + } topology = session[session_id]->topology; done: return topology; @@ -8358,14 +8361,17 @@ done: int q6asm_get_asm_app_type(int session_id) { - int app_type; + int app_type = -EINVAL; if (session_id <= 0 || session_id > ASM_ACTIVE_STREAMS_ALLOWED) { pr_err("%s: invalid session_id = %d\n", __func__, session_id); - app_type = -EINVAL; goto done; } - + if (session[session_id] == NULL) { + pr_err("%s: session not created for session id = %d\n", + __func__, session_id); + goto done; + } app_type = session[session_id]->app_type; done: return app_type; diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c index 2bf0c490e834..525ec1c30f48 100644 --- a/sound/soc/msm/qdsp6v2/q6lsm.c +++ b/sound/soc/msm/qdsp6v2/q6lsm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -38,6 +38,8 @@ #define LSM_ALIGN_BOUNDARY 512 #define LSM_SAMPLE_RATE 16000 #define QLSM_PARAM_ID_MINOR_VERSION 1 +#define QLSM_PARAM_ID_MINOR_VERSION_2 2 + static int lsm_afe_port; enum { @@ -707,29 +709,28 @@ static int q6lsm_send_confidence_levels( return rc; } -static int q6lsm_send_params(struct lsm_client *client, +static int q6lsm_send_param_opmode(struct lsm_client *client, struct lsm_module_param_ids *opmode_ids, - struct lsm_module_param_ids *connectport_ids, u32 set_param_opcode) { int rc; - struct lsm_cmd_set_opmode_connectport opmode_connectport; + struct lsm_cmd_set_params_opmode opmode_params; struct apr_hdr *msg_hdr; - struct lsm_param_connect_to_port *connect_to_port; + struct lsm_param_op_mode *op_mode; u32 data_payload_size, param_size; - msg_hdr = &opmode_connectport.msg_hdr; + msg_hdr = &opmode_params.msg_hdr; q6lsm_add_hdr(client, msg_hdr, - sizeof(opmode_connectport), true); + sizeof(opmode_params), true); msg_hdr->opcode = set_param_opcode; - data_payload_size = sizeof(opmode_connectport) - + data_payload_size = sizeof(opmode_params) - sizeof(*msg_hdr) - - sizeof(opmode_connectport.params_hdr); - q6lsm_set_param_hdr_info(&opmode_connectport.params_hdr, + sizeof(opmode_params.params_hdr); + q6lsm_set_param_hdr_info(&opmode_params.params_hdr, data_payload_size, 0, 0, 0); - connect_to_port = &opmode_connectport.connect_to_port; - op_mode = &opmode_connectport.op_mode; + op_mode = &opmode_params.op_mode; + param_size = sizeof(struct lsm_param_op_mode) - sizeof(op_mode->common); @@ -741,10 +742,61 @@ static int q6lsm_send_params(struct lsm_client *client, op_mode->reserved = 0; pr_debug("%s: mode = 0x%x", __func__, op_mode->mode); + rc = q6lsm_apr_send_pkt(client, client->apr, + &opmode_params, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + + pr_debug("%s: leave %d\n", __func__, rc); + return rc; +} + +void set_lsm_port(int lsm_port) +{ + lsm_afe_port = lsm_port; +} + +int get_lsm_port(void) +{ + return lsm_afe_port; +} + +int q6lsm_set_port_connected(struct lsm_client *client) +{ + int rc; + struct lsm_cmd_set_connectport connectport; + struct lsm_module_param_ids connectport_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_connect_to_port *connect_to_port; + u32 data_payload_size, param_size, set_param_opcode; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; + } else { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS; + connectport_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; + connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; + } + client->connect_to_port = get_lsm_port(); + + msg_hdr = &connectport.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(connectport), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(connectport) - + sizeof(*msg_hdr) - + sizeof(connectport.params_hdr); + q6lsm_set_param_hdr_info(&connectport.params_hdr, + data_payload_size, 0, 0, 0); + connect_to_port = &connectport.connect_to_port; + param_size = (sizeof(struct lsm_param_connect_to_port) - sizeof(connect_to_port->common)); q6lsm_set_param_common(&connect_to_port->common, - connectport_ids, param_size, + &connectport_ids, param_size, set_param_opcode); connect_to_port->minor_version = QLSM_PARAM_ID_MINOR_VERSION; connect_to_port->port_id = client->connect_to_port; @@ -752,23 +804,191 @@ static int q6lsm_send_params(struct lsm_client *client, pr_debug("%s: port= %d", __func__, connect_to_port->port_id); rc = q6lsm_apr_send_pkt(client, client->apr, - &opmode_connectport, true, NULL); + &connectport, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + + return rc; +} +static int q6lsm_send_param_polling_enable(struct lsm_client *client, + bool poll_en, + struct lsm_module_param_ids *poll_enable_ids, + u32 set_param_opcode) +{ + int rc = 0; + struct lsm_cmd_poll_enable cmd; + struct apr_hdr *msg_hdr; + struct lsm_param_poll_enable *poll_enable; + u32 data_payload_size, param_size; + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_poll_enable), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_poll_enable) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + poll_enable = &cmd.poll_enable; + + param_size = (sizeof(struct lsm_param_poll_enable) - + sizeof(poll_enable->common)); + q6lsm_set_param_common(&poll_enable->common, + poll_enable_ids, param_size, + set_param_opcode); + poll_enable->minor_version = QLSM_PARAM_ID_MINOR_VERSION; + poll_enable->polling_enable = (poll_en) ? 1 : 0; + pr_debug("%s: poll enable= %d", __func__, poll_enable->polling_enable); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); if (rc) pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", __func__, msg_hdr->opcode, rc); - pr_debug("%s: leave %d\n", __func__, rc); return rc; } -void set_lsm_port(int lsm_port) +int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, + uint32_t event_mode) { - lsm_afe_port = lsm_port; + int rc = 0; + struct lsm_cmd_set_fwk_mode_cfg cmd; + struct lsm_module_param_ids fwk_mode_cfg_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_fwk_mode_cfg *fwk_mode_cfg; + u32 data_payload_size, param_size, set_param_opcode; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + fwk_mode_cfg_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + fwk_mode_cfg_ids.param_id = LSM_PARAM_ID_FWK_MODE_CONFIG; + } else { + pr_debug("%s: Ignore sending event mode\n", __func__); + return rc; + } + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_set_fwk_mode_cfg), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_set_fwk_mode_cfg) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + fwk_mode_cfg = &cmd.fwk_mode_cfg; + + param_size = (sizeof(struct lsm_param_fwk_mode_cfg) - + sizeof(fwk_mode_cfg->common)); + q6lsm_set_param_common(&fwk_mode_cfg->common, + &fwk_mode_cfg_ids, param_size, + set_param_opcode); + + fwk_mode_cfg->minor_version = QLSM_PARAM_ID_MINOR_VERSION; + fwk_mode_cfg->mode = event_mode; + pr_debug("%s: mode = %d\n", __func__, fwk_mode_cfg->mode); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); + return rc; } -int get_lsm_port() +static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt, + int channel_count) { - return lsm_afe_port; + int rc = 0; + + memset(media_fmt->channel_mapping, 0, LSM_MAX_NUM_CHANNELS); + + switch (channel_count) { + case 1: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FC; + break; + case 2: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + break; + case 3: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + media_fmt->channel_mapping[2] = PCM_CHANNEL_FC; + break; + case 4: + media_fmt->channel_mapping[0] = PCM_CHANNEL_FL; + media_fmt->channel_mapping[1] = PCM_CHANNEL_FR; + media_fmt->channel_mapping[2] = PCM_CHANNEL_LS; + media_fmt->channel_mapping[3] = PCM_CHANNEL_RS; + break; + default: + pr_err("%s: invalid num_chan %d\n", __func__, channel_count); + rc = -EINVAL; + break; + } + return rc; +} + +int q6lsm_set_media_fmt_params(struct lsm_client *client) +{ + int rc = 0; + struct lsm_cmd_set_media_fmt cmd; + struct lsm_module_param_ids media_fmt_ids; + struct apr_hdr *msg_hdr; + struct lsm_param_media_fmt *media_fmt; + u32 data_payload_size, param_size, set_param_opcode; + struct lsm_hw_params param = client->hw_params; + + if (client->use_topology) { + set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2; + media_fmt_ids.module_id = LSM_MODULE_ID_FRAMEWORK; + media_fmt_ids.param_id = LSM_PARAM_ID_MEDIA_FMT; + } else { + pr_debug("%s: Ignore sending media format\n", __func__); + goto err_ret; + } + + msg_hdr = &cmd.msg_hdr; + q6lsm_add_hdr(client, msg_hdr, + sizeof(struct lsm_cmd_set_media_fmt), true); + msg_hdr->opcode = set_param_opcode; + data_payload_size = sizeof(struct lsm_cmd_set_media_fmt) - + sizeof(struct apr_hdr) - + sizeof(struct lsm_set_params_hdr); + q6lsm_set_param_hdr_info(&cmd.params_hdr, + data_payload_size, 0, 0, 0); + media_fmt = &cmd.media_fmt; + + param_size = (sizeof(struct lsm_param_media_fmt) - + sizeof(media_fmt->common)); + q6lsm_set_param_common(&media_fmt->common, + &media_fmt_ids, param_size, + set_param_opcode); + + media_fmt->minor_version = QLSM_PARAM_ID_MINOR_VERSION_2; + media_fmt->sample_rate = param.sample_rate; + media_fmt->num_channels = param.num_chs; + media_fmt->bit_width = param.sample_size; + + rc = q6lsm_arrange_mch_map(media_fmt, media_fmt->num_channels); + if (rc) + goto err_ret; + + pr_debug("%s: sample rate= %d, channels %d bit width %d\n", + __func__, media_fmt->sample_rate, media_fmt->num_channels, + media_fmt->bit_width); + + rc = q6lsm_apr_send_pkt(client, client->apr, + &cmd, true, NULL); + if (rc) + pr_err("%s: Failed set_params opcode 0x%x, rc %d\n", + __func__, msg_hdr->opcode, rc); +err_ret: + return rc; } int q6lsm_set_data(struct lsm_client *client, @@ -776,7 +996,7 @@ int q6lsm_set_data(struct lsm_client *client, bool detectfailure) { int rc = 0; - struct lsm_module_param_ids opmode_ids, connectport_ids; + struct lsm_module_param_ids opmode_ids; struct lsm_module_param_ids conf_levels_ids; if (!client->confidence_levels) { @@ -800,16 +1020,12 @@ int q6lsm_set_data(struct lsm_client *client, goto err_ret; } client->mode |= detectfailure << 2; - client->connect_to_port = get_lsm_port(); opmode_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; opmode_ids.param_id = LSM_PARAM_ID_OPERATION_MODE; - connectport_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = q6lsm_send_params(client, &opmode_ids, &connectport_ids, - LSM_SESSION_CMD_SET_PARAMS); + rc = q6lsm_send_param_opmode(client, &opmode_ids, + LSM_SESSION_CMD_SET_PARAMS); if (rc) { pr_err("%s: Failed to set lsm config params %d\n", __func__, rc); @@ -1390,7 +1606,7 @@ static int q6lsm_send_param_gain( int q6lsm_set_one_param(struct lsm_client *client, struct lsm_params_info *p_info, void *data, - enum LSM_PARAM_TYPE param_type) + uint32_t param_type) { int rc = 0, pkt_sz; struct lsm_module_param_ids ids; @@ -1409,7 +1625,6 @@ int q6lsm_set_one_param(struct lsm_client *client, case LSM_OPERATION_MODE: { struct snd_lsm_detect_mode *det_mode = data; struct lsm_module_param_ids opmode_ids; - struct lsm_module_param_ids connectport_ids; if (det_mode->mode == LSM_MODE_KEYWORD_ONLY_DETECTION) { client->mode = 0x01; @@ -1422,16 +1637,12 @@ int q6lsm_set_one_param(struct lsm_client *client, } client->mode |= det_mode->detect_failure << 2; - client->connect_to_port = get_lsm_port(); opmode_ids.module_id = p_info->module_id; opmode_ids.param_id = p_info->param_id; - connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK; - connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT; - - rc = q6lsm_send_params(client, &opmode_ids, &connectport_ids, - LSM_SESSION_CMD_SET_PARAMS_V2); + rc = q6lsm_send_param_opmode(client, &opmode_ids, + LSM_SESSION_CMD_SET_PARAMS_V2); if (rc) pr_err("%s: OPERATION_MODE failed, rc %d\n", __func__, rc); @@ -1458,6 +1669,20 @@ int q6lsm_set_one_param(struct lsm_client *client, pr_err("%s: CONFIDENCE_LEVELS cmd failed, rc %d\n", __func__, rc); break; + case LSM_POLLING_ENABLE: { + struct snd_lsm_poll_enable *lsm_poll_enable = + (struct snd_lsm_poll_enable *) data; + ids.module_id = p_info->module_id; + ids.param_id = p_info->param_id; + rc = q6lsm_send_param_polling_enable(client, + lsm_poll_enable->poll_en, &ids, + LSM_SESSION_CMD_SET_PARAMS_V2); + if (rc) + pr_err("%s: POLLING ENABLE cmd failed, rc %d\n", + __func__, rc); + break; + } + case LSM_REG_SND_MODEL: { struct lsm_cmd_set_params model_param; u32 payload_size; diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index e7619c0ca0dd..d352133b7c32 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -3990,6 +3990,10 @@ static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v) { int ret; + ret = voice_send_cvp_device_channels_cmd(v); + if (ret < 0) + goto done; + if (voice_get_cvd_int_version(common.cvd_version) >= CVD_INT_VERSION_2_3) { ret = voice_send_cvp_media_format_cmd(v, RX_PATH); @@ -4002,8 +4006,6 @@ static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v) if (common.ec_ref_ext) ret = voice_send_cvp_media_format_cmd(v, EC_REF_PATH); - } else { - ret = voice_send_cvp_device_channels_cmd(v); } done: diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c index 28728a186f92..8b0a12a46338 100644 --- a/sound/soc/msm/sdm660-internal.c +++ b/sound/soc/msm/sdm660-internal.c @@ -910,9 +910,6 @@ static const struct snd_kcontrol_new msm_sdw_controls[] = { SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate, int_mi2s_sample_rate_get, int_mi2s_sample_rate_put), - SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate, - int_mi2s_sample_rate_get, - int_mi2s_sample_rate_put), SOC_ENUM_EXT("INT4_MI2S_RX Channels", int4_mi2s_rx_chs, int_mi2s_ch_get, int_mi2s_ch_put), SOC_ENUM_EXT("VI_FEED_TX Channels", int5_mi2s_tx_chs, @@ -2316,7 +2313,7 @@ static struct snd_soc_dai_link msm_int_be_dai[] = { .async_ops = ASYNC_DPCM_SND_SOC_PREPARE | ASYNC_DPCM_SND_SOC_HW_PARAMS, .be_id = MSM_BACKEND_DAI_INT3_MI2S_TX, - .be_hw_params_fixup = msm_be_hw_params_fixup, + .be_hw_params_fixup = int_mi2s_be_hw_params_fixup, .ops = &msm_int_mi2s_be_ops, .ignore_suspend = 1, }, |
