summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt35
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt8
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-cmd.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-video.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-video.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi65
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi30
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi30
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi401
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-blsp.dtsi340
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-common.dtsi196
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi336
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-rumi.dts32
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-sim.dts16
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi34
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton-rumi.dts31
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton.dtsi18
-rw-r--r--arch/arm/configs/msmfalcon_defconfig1
-rw-r--r--drivers/char/diag/diagchar_core.c7
-rw-r--r--drivers/char/diag/diagfwd_glink.c3
-rw-r--r--drivers/char/diag/diagfwd_mhi.c6
-rw-r--r--drivers/char/diag/diagfwd_mhi.h3
-rw-r--r--drivers/char/diag/diagfwd_peripheral.c37
-rw-r--r--drivers/char/diag/diagfwd_peripheral.h1
-rw-r--r--drivers/clk/clk.c356
-rw-r--r--drivers/clk/clk.h4
-rw-r--r--drivers/clk/msm/clock-mmss-cobalt.c81
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c216
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h1
-rw-r--r--drivers/clk/qcom/clk-branch.c59
-rw-r--r--drivers/clk/qcom/clk-rcg.h1
-rw-r--r--drivers/clk/qcom/clk-rcg2.c74
-rw-r--r--drivers/clk/qcom/clk-regmap.h8
-rw-r--r--drivers/gpu/msm/a5xx_reg.h6
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c40
-rw-r--r--drivers/gpu/msm/adreno_a5xx.h1
-rw-r--r--drivers/gpu/msm/kgsl.c182
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c33
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c27
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h5
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.c33
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.h9
-rw-r--r--drivers/iio/adc/qcom-rradc.c110
-rw-r--r--drivers/leds/leds-qpnp-flash-v2.c664
-rw-r--r--drivers/leds/leds-qpnp-flash.c3
-rw-r--r--drivers/leds/leds-qpnp-wled.c178
-rw-r--r--drivers/misc/qseecom.c47
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-v3.h12
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msmfalcon.c31
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c59
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c17
-rw-r--r--drivers/power/qcom-charger/smb-lib.c60
-rw-r--r--drivers/power/qcom-charger/smb-lib.h4
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c4
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c84
-rw-r--r--drivers/scsi/ufs/ufshcd.c178
-rw-r--r--drivers/scsi/ufs/ufshcd.h17
-rw-r--r--drivers/scsi/ufs/ufshci.h1
-rw-r--r--drivers/soc/qcom/icnss.c24
-rw-r--r--drivers/soc/qcom/msm_smem.c137
-rw-r--r--drivers/soc/qcom/smem_debug.c9
-rw-r--r--drivers/soc/qcom/smem_private.h3
-rw-r--r--drivers/thermal/msm_thermal.c16
-rw-r--r--drivers/usb/core/driver.c12
-rw-r--r--drivers/usb/host/xhci-plat.c4
-rw-r--r--drivers/usb/pd/policy_engine.c97
-rw-r--r--drivers/usb/phy/phy-msm-qusb.c148
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_clk.c27
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_clk.h15
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_host.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c106
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_trace.h16
-rw-r--r--drivers/video/fbdev/msm/mdss_util.c25
-rw-r--r--drivers/video/fbdev/msm/mhl3/si_mhl2_edid_3d.c9
-rw-r--r--drivers/video/fbdev/msm/msm_mdss_io_8974.c52
-rw-r--r--include/linux/clk-provider.h12
-rw-r--r--include/linux/filter.h6
-rw-r--r--include/linux/ipa.h64
-rw-r--r--include/linux/sched/sysctl.h2
-rw-r--r--include/linux/usb.h9
-rw-r--r--include/net/tcp.h1
-rw-r--r--include/trace/events/sched.h25
-rw-r--r--include/uapi/media/msm_sde_rotator.h6
-rw-r--r--kernel/sched/Makefile2
-rw-r--r--kernel/sched/boost.c226
-rw-r--r--kernel/sched/core.c3
-rw-r--r--kernel/sched/fair.c153
-rw-r--r--kernel/sched/hmp.c512
-rw-r--r--kernel/sched/rt.c12
-rw-r--r--kernel/sched/sched.h47
-rw-r--r--kernel/sched/tune.c184
-rw-r--r--kernel/sysctl.c19
-rw-r--r--net/core/filter.c9
-rw-r--r--net/ipv4/tcp_ipv4.c19
-rw-r--r--net/ipv6/tcp_ipv6.c6
-rw-r--r--net/rose/rose_in.c3
-rw-r--r--net/wireless/db.txt95
-rw-r--r--sound/soc/codecs/wcd-mbhc-v2.c5
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c78
-rw-r--r--sound/soc/msm/msmfalcon-common.c1146
-rw-r--r--sound/soc/msm/msmfalcon-common.h36
-rw-r--r--sound/soc/msm/msmfalcon-ext-dai-links.c452
-rw-r--r--sound/soc/msm/msmfalcon-external.c83
-rw-r--r--sound/soc/msm/msmfalcon-external.h8
-rw-r--r--sound/soc/msm/msmfalcon-internal.c521
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c153
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h22
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c4
123 files changed, 7254 insertions, 1705 deletions
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index 8844a816052e..4808d1dda5c1 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -11,6 +11,8 @@ Main node:
Required properties:
- compatible : Should be "qcom,qpnp-flash-led-v2"
- reg : Base address and size for flash LED modules
+- qcom,pmic-revid : phandle of PMIC revid module. This is used to
+ identify the PMIC subtype.
Optional properties:
- interrupts : Specifies the interrupts associated with flash-led.
@@ -76,6 +78,39 @@ Optional properties:
- qcom,thermal-derate-current : Array of currrent limits for thermal mitigation. Required if
qcom,thermal-derate-en is specified. Unit is mA. Format is
qcom,thermal-derate-current = <OTST1_LIMIT, OTST2_LIMIT, OTST3_LIMIT>.
+- qcom,otst-ramp-back-up-dis : Boolean property to disable current ramp
+ backup after thermal derate trigger is
+ deasserted.
+- qcom,thermal-derate-slow : Integer property to specify slow ramping
+ down thermal rate. Unit is in uS. Allowed
+ values are: 128, 256, 512, 1024, 2048, 4096,
+ 8192 and 314592.
+- qcom,thermal-derate-fast : Integer property to specify fast ramping
+ down thermal rate. Unit is in uS. Allowed
+ values are: 32, 64, 96, 128, 256, 384 and
+ 512.
+- qcom,thermal-debounce : Integer property to specify thermal debounce
+ time. It is only used if qcom,thermal-derate-en
+ is specified. Unit is in uS. Allowed values
+ are: 0, 16, 32, 64.
+- qcom,thermal-hysteresis : Integer property to specify thermal derating
+ hysteresis. Unit is in deciDegC. It is only
+ used if qcom,thermal-derate-en is specified.
+ Allowed values are:
+ 0, 15, 30, 45 for pmicobalt.
+ 0, 20, 40, 60 for pm2falcon.
+- qcom,thermal-thrsh1 : Integer property to specify OTST1 threshold
+ for thermal mitigation. Unit is in Celsius.
+ Accepted values are:
+ 85, 79, 73, 67, 109, 103, 97, 91.
+- qcom,thermal-thrsh2 : Integer property to specify OTST2 threshold
+ for thermal mitigation. Unit is in Celsius.
+ Accepted values are:
+ 110, 104, 98, 92, 134, 128, 122, 116.
+- qcom,thermal-thrsh3 : Integer property to specify OTST3 threshold
+ for thermal mitigation. Unit is in Celsius.
+ Accepted values are:
+ 125, 119, 113, 107, 149, 143, 137, 131.
- qcom,hw-strobe-option : Integer type to specify hardware strobe option. Based on the specified
value, additional GPIO configuration may be required to provide strobing
support. Supported values are:
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
index 07f3fd274658..4b23cb1e9a9c 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-wled.txt
@@ -68,9 +68,15 @@ Optional properties for WLED:
- qcom,cons-sync-write-delay-us : Specify in 'us' the duration of delay between two consecutive writes to
SYNC register.
- qcom,sc-deb-cycles : debounce time for short circuit detection
+- qcom,loop-ea-gm : control the gm for gm stage in control loop. default is 3.
+- qcom,loop-auto-gm-en : A boolean property to specify if auto gm is enabled.
+- qcom,loop-auto-gm-thresh : Specify auto gm threshold if "loop-auto-gm-en" is defined.
+ Supported values are: 0 - 3.
+- qcom,lcd-auto-pfm-thresh : Specify the auto-pfm threshold, if the headroom voltage level
+ falls below this threshold and auto PFM is enabled, boost
+ controller will enter into PFM mode automatically.
Optional properties if 'qcom,disp-type-amoled' is mentioned in DT:
-- qcom,loop-ea-gm : control the gm for gm stage in control loop. default is 3.
- qcom,loop-comp-res-kohm : control to select the compensation resistor in kohm. default is 320.
- qcom,vref-psm-mv : reference psm voltage in mv. default for amoled is 450.
- qcom,avdd-mode-spmi: Boolean property to enable AMOLED_VOUT programming via SPMI. If not specified,
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-cmd.dtsi
index 9ad9e4adce00..94ca102c9dc0 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-cmd.dtsi
@@ -44,6 +44,8 @@
qcom,mdss-dsi-dma-trigger = "trigger_sw";
qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-pan-physical-width-dimension = <74>;
+ qcom,mdss-pan-physical-height-dimension = <131>;
qcom,mdss-dsi-te-pin-select = <1>;
qcom,mdss-dsi-wr-mem-start = <0x2c>;
qcom,mdss-dsi-wr-mem-continue = <0x3c>;
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-video.dtsi
index 6b549a4af6eb..49130cc96f79 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-video.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dsc-wqxga-video.dtsi
@@ -77,6 +77,8 @@
qcom,mdss-dsi-dma-trigger = "trigger_sw";
qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-pan-physical-width-dimension = <74>;
+ qcom,mdss-pan-physical-height-dimension = <131>;
qcom,compression-mode = "dsc";
qcom,config-select = <&dsi_nt35597_dsc_video_config0>;
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
index 1e42d0846acf..10be9cc183f6 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-nt35597-dualmipi-wqxga-cmd.dtsi
@@ -47,6 +47,8 @@
04 00];
qcom,adjust-timer-wakeup-ms = <1>;
qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-pan-physical-width-dimension = <74>;
+ qcom,mdss-pan-physical-height-dimension = <131>;
qcom,mdss-dsi-t-clk-post = <0x0d>;
qcom,mdss-dsi-t-clk-pre = <0x2d>;
qcom,mdss-dsi-bl-max-level = <4095>;
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 82413bfbca89..a2cac50325c5 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
@@ -70,6 +70,8 @@
qcom,mdss-dsi-dma-trigger = "trigger_sw";
qcom,mdss-dsi-mdp-trigger = "none";
qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+ qcom,mdss-pan-physical-width-dimension = <74>;
+ qcom,mdss-pan-physical-height-dimension = <131>;
qcom,mdss-dsi-min-refresh-rate = <55>;
qcom,mdss-dsi-max-refresh-rate = <60>;
qcom,mdss-dsi-pan-enable-dynamic-fps;
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
index 3de3cd5f8de9..1ad8f99e4186 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-cobalt.dtsi
@@ -22,17 +22,13 @@
#iommu-cells = <0>;
qcom,register-save;
qcom,skip-init;
- #global-interrupts = <2>;
- interrupts = <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 231 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 364 IRQ_TYPE_EDGE_RISING>,
+ #global-interrupts = <0>;
+ interrupts = <GIC_SPI 364 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 365 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 366 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 367 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 368 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 369 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 370 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 431 IRQ_TYPE_EDGE_RISING>;
+ <GIC_SPI 369 IRQ_TYPE_EDGE_RISING>;
clocks = <&clock_gcc clk_aggre1_noc_clk>;
clock-names = "smmu_aggre1_noc_clk";
#clock-cells = <1>;
@@ -45,10 +41,8 @@
#iommu-cells = <1>;
qcom,register-save;
qcom,skip-init;
- #global-interrupts = <2>;
- interrupts = <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 231 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
+ #global-interrupts = <0>;
+ interrupts = <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 374 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 375 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>,
@@ -57,17 +51,7 @@
<GIC_SPI 462 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 463 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 353 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 354 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 356 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 357 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 358 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 359 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 360 IRQ_TYPE_EDGE_RISING>;
+ <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>;
clocks = <&clock_gcc clk_aggre2_noc_clk>;
clock-names = "smmu_aggre2_noc_clk";
#clock-cells = <1>;
@@ -81,10 +65,8 @@
qcom,tz-device-id = "LPASS";
qcom,register-save;
qcom,skip-init;
- #global-interrupts = <2>;
- interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
+ #global-interrupts = <0>;
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>,
@@ -96,11 +78,7 @@
<GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
vdd-supply = <&gdsc_hlos1_vote_lpass_adsp>;
clocks = <&clock_gcc clk_hlos1_vote_lpass_adsp_smmu_clk>;
clock-names = "lpass_q6_smmu_clk";
@@ -115,10 +93,8 @@
qcom,register-save;
qcom,no-smr-check;
qcom,skip-init;
- #global-interrupts = <2>;
- interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
+ #global-interrupts = <0>;
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
@@ -137,11 +113,7 @@
<GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>;
+ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
vdd-supply = <&gdsc_bimc_smmu>;
clocks = <&clock_mmss clk_mmss_mnoc_ahb_clk>,
<&clock_gcc clk_mmssnoc_axi_clk>,
@@ -164,15 +136,10 @@
qcom,dynamic;
qcom,register-save;
qcom,skip-init;
- #global-interrupts = <2>;
- interrupts = <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 231 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+ #global-interrupts = <0>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>;
vdd-supply = <&gdsc_gpu_cx>;
clocks = <&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gcc clk_gcc_bimc_gfx_clk>,
diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi
index 33a4c1521e85..79883db10d06 100644
--- a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi
@@ -269,6 +269,7 @@
qcom,thermal-derate-en;
qcom,thermal-derate-current = <200 500 1000>;
qcom,isc-delay = <192>;
+ qcom,pmic-revid = <&pm2falcon_revid>;
status = "disabled";
pm2falcon_flash0: qcom,flash_0 {
diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
index a122e04a3f5c..baeda86bc976 100644
--- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
@@ -613,6 +613,7 @@
qcom,led-strings-list = [00 01 02 03];
qcom,en-ext-pfet-sc-pro;
qcom,pmic-revid = <&pmicobalt_revid>;
+ qcom,loop-auto-gm-en;
};
pmicobalt_haptics: qcom,haptic@c000 {
@@ -657,6 +658,7 @@
qcom,thermal-derate-en;
qcom,thermal-derate-current = <200 500 1000>;
qcom,isc-delay = <192>;
+ qcom,pmic-revid = <&pmicobalt_revid>;
pmicobalt_flash0: qcom,flash_0 {
label = "flash";
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 7e88f524367f..2735cfb93be0 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -1948,6 +1948,8 @@
clock-names = "core_clk", "iface_clk", "bus_aggr_clk", "utmi_clk",
"sleep_clk", "xo", "cfg_ahb_clk";
+ qcom,core-clk-rate = <120000000>;
+
resets = <&clock_gcc USB_30_BCR>;
reset-names = "core_reset";
@@ -2056,6 +2058,7 @@
<&clock_gcc clk_gcc_usb_phy_cfg_ahb2phy_clk>;
clock-names = "core_clk", "iface_clk", "utmi_clk", "sleep_clk",
"xo", "cfg_ahb_clk";
+ qcom,core-clk-rate = <60000000>;
resets = <&clock_gcc USB_20_BCR>;
reset-names = "core_reset";
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi
index 4822823aa63f..9663ef5a383f 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi
@@ -44,9 +44,9 @@
};
&ufsphy1 {
- vdda-phy-supply = <&pmcobalt_l1>;
- vdda-pll-supply = <&pmcobalt_l2>;
- vddp-ref-clk-supply = <&pmcobalt_l26>;
+ vdda-phy-supply = <&pm2falcon_l1>;
+ vdda-pll-supply = <&pmfalcon_l1>;
+ vddp-ref-clk-supply = <&pmfalcon_l1>;
vdda-phy-max-microamp = <51400>;
vdda-pll-max-microamp = <14600>;
vddp-ref-clk-max-microamp = <100>;
@@ -57,12 +57,10 @@
&ufs1 {
vdd-hba-supply = <&gdsc_ufs>;
vdd-hba-fixed-regulator;
- vcc-supply = <&pmcobalt_l20>;
- vccq-supply = <&pmcobalt_l26>;
- vccq2-supply = <&pmcobalt_s4>;
- vcc-max-microamp = <750000>;
- vccq-max-microamp = <560000>;
- vccq2-max-microamp = <750000>;
+ vcc-supply = <&pm2falcon_l4>;
+ vccq2-supply = <&pmfalcon_l8>;
+ vcc-max-microamp = <500000>;
+ vccq2-max-microamp = <600000>;
status = "ok";
};
@@ -275,10 +273,15 @@
&mdss_dsi {
hw-config = "split_dsi";
+ vdda-1p2-supply = <&pmfalcon_l1>;
+ vdda-0p9-supply = <&pm2falcon_l1>;
};
&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_truly_video>;
+ wqhd-vddio-supply = <&pmfalcon_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
@@ -288,7 +291,10 @@
};
&mdss_dsi1 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_truly_video>;
+ wqhd-vddio-supply = <&pmfalcon_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
@@ -424,6 +430,8 @@
};
&mdss_dp_ctrl {
+ vdda-1p2-supply = <&pmfalcon_l1>;
+ vdda-0p9-supply = <&pm2falcon_l1>;
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>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi
index b77bab712ecf..0c8b6ff56124 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi
@@ -45,9 +45,9 @@
};
&ufsphy1 {
- vdda-phy-supply = <&pmcobalt_l1>;
- vdda-pll-supply = <&pmcobalt_l2>;
- vddp-ref-clk-supply = <&pmcobalt_l26>;
+ vdda-phy-supply = <&pm2falcon_l1>;
+ vdda-pll-supply = <&pmfalcon_l1>;
+ vddp-ref-clk-supply = <&pmfalcon_l1>;
vdda-phy-max-microamp = <51400>;
vdda-pll-max-microamp = <14600>;
vddp-ref-clk-max-microamp = <100>;
@@ -58,12 +58,10 @@
&ufs1 {
vdd-hba-supply = <&gdsc_ufs>;
vdd-hba-fixed-regulator;
- vcc-supply = <&pmcobalt_l20>;
- vccq-supply = <&pmcobalt_l26>;
- vccq2-supply = <&pmcobalt_s4>;
- vcc-max-microamp = <750000>;
- vccq-max-microamp = <560000>;
- vccq2-max-microamp = <750000>;
+ vcc-supply = <&pm2falcon_l4>;
+ vccq2-supply = <&pmfalcon_l8>;
+ vcc-max-microamp = <500000>;
+ vccq2-max-microamp = <600000>;
status = "ok";
};
@@ -314,6 +312,8 @@
};
&mdss_dp_ctrl {
+ vdda-1p2-supply = <&pmfalcon_l1>;
+ vdda-0p9-supply = <&pm2falcon_l1>;
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>;
@@ -328,10 +328,15 @@
&mdss_dsi {
hw-config = "split_dsi";
+ vdda-1p2-supply = <&pmfalcon_l1>;
+ vdda-0p9-supply = <&pm2falcon_l1>;
};
&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_truly_video>;
+ wqhd-vddio-supply = <&pmfalcon_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
@@ -341,7 +346,10 @@
};
&mdss_dsi1 {
- qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_truly_video>;
+ wqhd-vddio-supply = <&pmfalcon_l11>;
+ lab-supply = <&lcdb_ldo_vreg>;
+ ibb-supply = <&lcdb_ncp_vreg>;
pinctrl-names = "mdss_default", "mdss_sleep";
pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi
index 274281f7c982..f5d5c7f400f9 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi
@@ -81,18 +81,6 @@
/delete-property/qca,bt-chip-pwd-supply;
};
-&ufsphy1 {
- /delete-property/vdda-phy-supply;
- /delete-property/vdda-pll-supply;
- /delete-property/vddp-ref-clk-supply;
-};
-
-&ufs1 {
- /delete-property/vcc-supply;
- /delete-property/vccq-supply;
- /delete-property/vccq2-supply;
-};
-
&sdhc_2 {
/delete-property/vdd-supply;
/delete-property/vdd-io-supply;
@@ -277,3 +265,19 @@
#include "msm-pm2falcon.dtsi"
#include "msmfalcon-regulator.dtsi"
+/* dummy LCDB regulator nodes */
+&soc {
+ lcdb_ldo_vreg: regulator-vdisp-vreg {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "lcdb_ldo";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+
+ lcdb_ncp_vreg: regulator-vdisn-vreg {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "lcdb_ncp";
+ regulator-min-microvolt = <4000000>;
+ regulator-max-microvolt = <6000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 9b0d3f674032..cee85ff63ca8 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -1441,184 +1441,6 @@
};
};
- pcie0: qcom,pcie@01c00000 {
- compatible = "qcom,pci-msm";
- cell-index = <0>;
-
- reg = <0x1c00000 0x2000>,
- <0x1c06000 0x1000>,
- <0x1b000000 0xf1d>,
- <0x1b000f20 0xa8>,
- <0x1b100000 0x100000>,
- <0x1b200000 0x100000>,
- <0x1b300000 0xd00000>;
-
- reg-names = "parf", "phy", "dm_core", "elbi",
- "conf", "io", "bars";
-
- #address-cells = <3>;
- #size-cells = <2>;
- ranges = <0x01000000 0x0 0x1b200000 0x1b200000 0x0 0x100000>,
- <0x02000000 0x0 0x1b300000 0x1b300000 0x0 0xd00000>;
- interrupt-parent = <&pcie0>;
- interrupts = <0 1 2 3 4 5>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 0xffffffff>;
- interrupt-map = <0 0 0 0 &intc 0 0 405 0
- 0 0 0 1 &intc 0 0 135 0
- 0 0 0 2 &intc 0 0 136 0
- 0 0 0 3 &intc 0 0 138 0
- 0 0 0 4 &intc 0 0 139 0
- 0 0 0 5 &intc 0 0 278 0>;
-
- interrupt-names = "int_msi", "int_a", "int_b", "int_c",
- "int_d", "int_global_int";
-
- qcom,phy-sequence = <0x804 0x01 0x00
- 0x034 0x14 0x00
- 0x138 0x30 0x00
- 0x048 0x0f 0x00
- 0x15c 0x06 0x00
- 0x090 0x01 0x00
- 0x088 0x20 0x00
- 0x0f0 0x00 0x00
- 0x0f8 0x01 0x00
- 0x0f4 0xc9 0x00
- 0x11c 0xff 0x00
- 0x120 0x3f 0x00
- 0x164 0x01 0x00
- 0x154 0x00 0x00
- 0x148 0x0a 0x00
- 0x05C 0x19 0x00
- 0x038 0x90 0x00
- 0x0b0 0x82 0x00
- 0x0c0 0x03 0x00
- 0x0bc 0x55 0x00
- 0x0b8 0x55 0x00
- 0x0a0 0x00 0x00
- 0x09c 0x0d 0x00
- 0x098 0x04 0x00
- 0x13c 0x00 0x00
- 0x060 0x08 0x00
- 0x068 0x16 0x00
- 0x070 0x34 0x00
- 0x15c 0x06 0x00
- 0x138 0x33 0x00
- 0x03c 0x02 0x00
- 0x040 0x0e 0x00
- 0x080 0x04 0x00
- 0x0dc 0x00 0x00
- 0x0d8 0x3f 0x00
- 0x00c 0x09 0x00
- 0x010 0x01 0x00
- 0x01c 0x40 0x00
- 0x020 0x01 0x00
- 0x014 0x02 0x00
- 0x018 0x00 0x00
- 0x024 0x7e 0x00
- 0x028 0x15 0x00
- 0x244 0x02 0x00
- 0x2a4 0x12 0x00
- 0x260 0x10 0x00
- 0x28c 0x06 0x00
- 0x504 0x03 0x00
- 0x500 0x1c 0x00
- 0x50c 0x14 0x00
- 0x4d4 0x0a 0x00
- 0x4d8 0x04 0x00
- 0x4dc 0x1a 0x00
- 0x434 0x4b 0x00
- 0x414 0x04 0x00
- 0x40c 0x04 0x00
- 0x4f8 0x00 0x00
- 0x4fc 0x80 0x00
- 0x51c 0x40 0x00
- 0x444 0x71 0x00
- 0x43c 0x40 0x00
- 0x854 0x04 0x00
- 0x62c 0x52 0x00
- 0x9ac 0x00 0x00
- 0x8a0 0x01 0x00
- 0x9e0 0x00 0x00
- 0x9dc 0x01 0x00
- 0x9a8 0x00 0x00
- 0x8a4 0x01 0x00
- 0x8a8 0x73 0x00
- 0x9d8 0x99 0x00
- 0x9b0 0x03 0x00
- 0x804 0x03 0x00
- 0x800 0x00 0x00
- 0x808 0x03 0x00>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pcie0_clkreq_default
- &pcie0_perst_default
- &pcie0_wake_default>;
-
- perst-gpio = <&tlmm 35 0>;
- wake-gpio = <&tlmm 37 0>;
-
- gdsc-vdd-supply = <&gdsc_pcie_0>;
- vreg-1.8-supply = <&pmcobalt_l2>;
- vreg-0.9-supply = <&pmcobalt_l1>;
- vreg-cx-supply = <&pmcobalt_s1_level>;
-
- qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
- qcom,vreg-0.9-voltage-level = <880000 880000 24000>;
- qcom,vreg-cx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_BINNING
- RPM_SMD_REGULATOR_LEVEL_SVS 0>;
-
- qcom,l1-supported;
- qcom,l1ss-supported;
- qcom,aux-clk-sync;
-
- qcom,ep-latency = <10>;
-
- qcom,ep-wakeirq;
-
- linux,pci-domain = <0>;
-
- qcom,pcie-phy-ver = <0x20>;
- qcom,use-19p2mhz-aux-clk;
-
- iommus = <&anoc1_smmu>;
- qcom,smmu-exist;
- qcom,smmu-sid-base = <0x1480>;
-
- qcom,msm-bus,name = "pcie0";
- qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,num-paths = <1>;
- qcom,msm-bus,vectors-KBps =
- <45 512 0 0>,
- <45 512 500 800>;
-
- clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>,
- <&clock_gcc clk_ln_bb_clk1>,
- <&clock_gcc clk_gcc_pcie_0_aux_clk>,
- <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>,
- <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>,
- <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>,
- <&clock_gcc clk_gcc_pcie_clkref_clk>;
-
- clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src",
- "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk",
- "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
- "pcie_0_ldo";
-
- max-clock-frequency-hz = <0>, <0>, <19200000>,
- <0>, <0>, <0>, <0>, <0>, <0>,
- <0>, <0>, <0>, <0>, <0>, <0>,
- <0>, <0>;
-
- resets = <&clock_gcc PCIE_PHY_BCR>,
- <&clock_gcc PCIE_0_PHY_BCR>,
- <&clock_gcc PCIE_0_PHY_BCR>;
-
- reset-names = "pcie_phy_reset",
- "pcie_0_phy_reset",
- "pcie_0_phy_pipe_reset";
- };
-
qcom,ipc_router {
compatible = "qcom,ipc_router";
qcom,node-id = <1>;
@@ -2614,6 +2436,229 @@
};
};
+ pcie0: qcom,pcie@01c00000 {
+ compatible = "qcom,pci-msm";
+ cell-index = <0>;
+
+ reg = <0x1c00000 0x2000>,
+ <0x1c06000 0x1000>,
+ <0x1b000000 0xf1d>,
+ <0x1b000f20 0xa8>,
+ <0x1b100000 0x100000>,
+ <0x1b200000 0x100000>,
+ <0x1b300000 0xd00000>;
+
+ reg-names = "parf", "phy", "dm_core", "elbi",
+ "conf", "io", "bars";
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x1b200000 0x1b200000 0x0 0x100000>,
+ <0x02000000 0x0 0x1b300000 0x1b300000 0x0 0xd00000>;
+ interrupt-parent = <&pcie0>;
+ interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
+ 36 37>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0xffffffff>;
+ interrupt-map = <0 0 0 0 &intc 0 0 405 0
+ 0 0 0 1 &intc 0 0 135 0
+ 0 0 0 2 &intc 0 0 136 0
+ 0 0 0 3 &intc 0 0 138 0
+ 0 0 0 4 &intc 0 0 139 0
+ 0 0 0 5 &intc 0 0 278 0
+ 0 0 0 6 &intc 0 0 576 0
+ 0 0 0 7 &intc 0 0 577 0
+ 0 0 0 8 &intc 0 0 578 0
+ 0 0 0 9 &intc 0 0 579 0
+ 0 0 0 10 &intc 0 0 580 0
+ 0 0 0 11 &intc 0 0 581 0
+ 0 0 0 12 &intc 0 0 582 0
+ 0 0 0 13 &intc 0 0 583 0
+ 0 0 0 14 &intc 0 0 584 0
+ 0 0 0 15 &intc 0 0 585 0
+ 0 0 0 16 &intc 0 0 586 0
+ 0 0 0 17 &intc 0 0 587 0
+ 0 0 0 18 &intc 0 0 588 0
+ 0 0 0 19 &intc 0 0 589 0
+ 0 0 0 20 &intc 0 0 590 0
+ 0 0 0 21 &intc 0 0 591 0
+ 0 0 0 22 &intc 0 0 592 0
+ 0 0 0 23 &intc 0 0 593 0
+ 0 0 0 24 &intc 0 0 594 0
+ 0 0 0 25 &intc 0 0 595 0
+ 0 0 0 26 &intc 0 0 596 0
+ 0 0 0 27 &intc 0 0 597 0
+ 0 0 0 28 &intc 0 0 598 0
+ 0 0 0 29 &intc 0 0 599 0
+ 0 0 0 30 &intc 0 0 600 0
+ 0 0 0 31 &intc 0 0 601 0
+ 0 0 0 32 &intc 0 0 602 0
+ 0 0 0 33 &intc 0 0 603 0
+ 0 0 0 34 &intc 0 0 604 0
+ 0 0 0 35 &intc 0 0 605 0
+ 0 0 0 36 &intc 0 0 606 0
+ 0 0 0 37 &intc 0 0 607 0>;
+
+ interrupt-names = "int_msi", "int_a", "int_b", "int_c",
+ "int_d", "int_global_int",
+ "msi_0", "msi_1", "msi_2", "msi_3",
+ "msi_4", "msi_5", "msi_6", "msi_7",
+ "msi_8", "msi_9", "msi_10", "msi_11",
+ "msi_12", "msi_13", "msi_14", "msi_15",
+ "msi_16", "msi_17", "msi_18", "msi_19",
+ "msi_20", "msi_21", "msi_22", "msi_23",
+ "msi_24", "msi_25", "msi_26", "msi_27",
+ "msi_28", "msi_29", "msi_30", "msi_31";
+
+ qcom,phy-sequence = <0x804 0x01 0x00
+ 0x034 0x14 0x00
+ 0x138 0x30 0x00
+ 0x048 0x0f 0x00
+ 0x15c 0x06 0x00
+ 0x090 0x01 0x00
+ 0x088 0x20 0x00
+ 0x0f0 0x00 0x00
+ 0x0f8 0x01 0x00
+ 0x0f4 0xc9 0x00
+ 0x11c 0xff 0x00
+ 0x120 0x3f 0x00
+ 0x164 0x01 0x00
+ 0x154 0x00 0x00
+ 0x148 0x0a 0x00
+ 0x05C 0x19 0x00
+ 0x038 0x90 0x00
+ 0x0b0 0x82 0x00
+ 0x0c0 0x03 0x00
+ 0x0bc 0x55 0x00
+ 0x0b8 0x55 0x00
+ 0x0a0 0x00 0x00
+ 0x09c 0x0d 0x00
+ 0x098 0x04 0x00
+ 0x13c 0x00 0x00
+ 0x060 0x08 0x00
+ 0x068 0x16 0x00
+ 0x070 0x34 0x00
+ 0x15c 0x06 0x00
+ 0x138 0x33 0x00
+ 0x03c 0x02 0x00
+ 0x040 0x0e 0x00
+ 0x080 0x04 0x00
+ 0x0dc 0x00 0x00
+ 0x0d8 0x3f 0x00
+ 0x00c 0x09 0x00
+ 0x010 0x01 0x00
+ 0x01c 0x40 0x00
+ 0x020 0x01 0x00
+ 0x014 0x02 0x00
+ 0x018 0x00 0x00
+ 0x024 0x7e 0x00
+ 0x028 0x15 0x00
+ 0x244 0x02 0x00
+ 0x2a4 0x12 0x00
+ 0x260 0x10 0x00
+ 0x28c 0x06 0x00
+ 0x504 0x03 0x00
+ 0x500 0x1c 0x00
+ 0x50c 0x14 0x00
+ 0x4d4 0x0a 0x00
+ 0x4d8 0x04 0x00
+ 0x4dc 0x1a 0x00
+ 0x434 0x4b 0x00
+ 0x414 0x04 0x00
+ 0x40c 0x04 0x00
+ 0x4f8 0x00 0x00
+ 0x4fc 0x80 0x00
+ 0x51c 0x40 0x00
+ 0x444 0x71 0x00
+ 0x43c 0x40 0x00
+ 0x854 0x04 0x00
+ 0x62c 0x52 0x00
+ 0x9ac 0x00 0x00
+ 0x8a0 0x01 0x00
+ 0x9e0 0x00 0x00
+ 0x9dc 0x01 0x00
+ 0x9a8 0x00 0x00
+ 0x8a4 0x01 0x00
+ 0x8a8 0x73 0x00
+ 0x9d8 0x99 0x00
+ 0x9b0 0x03 0x00
+ 0x804 0x03 0x00
+ 0x800 0x00 0x00
+ 0x808 0x03 0x00>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_clkreq_default
+ &pcie0_perst_default
+ &pcie0_wake_default>;
+
+ perst-gpio = <&tlmm 35 0>;
+ wake-gpio = <&tlmm 37 0>;
+
+ gdsc-vdd-supply = <&gdsc_pcie_0>;
+ vreg-1.8-supply = <&pmcobalt_l2>;
+ vreg-0.9-supply = <&pmcobalt_l1>;
+ vreg-cx-supply = <&pmcobalt_s1_level>;
+
+ qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
+ qcom,vreg-0.9-voltage-level = <880000 880000 24000>;
+ qcom,vreg-cx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_BINNING
+ RPM_SMD_REGULATOR_LEVEL_SVS 0>;
+
+ qcom,l1-supported;
+ qcom,l1ss-supported;
+ qcom,aux-clk-sync;
+
+ qcom,ep-latency = <10>;
+
+ qcom,ep-wakeirq;
+
+ linux,pci-domain = <0>;
+
+ qcom,msi-gicm-addr = <0x17a00040>;
+ qcom,msi-gicm-base = <0x260>;
+
+ qcom,pcie-phy-ver = <0x20>;
+ qcom,use-19p2mhz-aux-clk;
+
+ iommus = <&anoc1_smmu>;
+ qcom,smmu-exist;
+ qcom,smmu-sid-base = <0x1480>;
+
+ qcom,msm-bus,name = "pcie0";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>,
+ <45 512 500 800>;
+
+ clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>,
+ <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_pcie_0_aux_clk>,
+ <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_clkref_clk>;
+
+ clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src",
+ "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk",
+ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
+ "pcie_0_ldo";
+
+ max-clock-frequency-hz = <0>, <0>, <19200000>,
+ <0>, <0>, <0>, <0>, <0>, <0>,
+ <0>, <0>, <0>, <0>, <0>, <0>,
+ <0>, <0>;
+
+ resets = <&clock_gcc PCIE_PHY_BCR>,
+ <&clock_gcc PCIE_0_PHY_BCR>,
+ <&clock_gcc PCIE_0_PHY_BCR>;
+
+ reset-names = "pcie_phy_reset",
+ "pcie_0_phy_reset",
+ "pcie_0_phy_pipe_reset";
+ };
+
qcom,bcl {
compatible = "qcom,bcl";
qcom,bcl-enable;
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-blsp.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-blsp.dtsi
index 61764a095a29..c401d364409b 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-blsp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-blsp.dtsi
@@ -22,11 +22,203 @@
spi6 = &spi_6;
spi7 = &spi_7;
spi8 = &spi_8;
+ i2c1 = &i2c_1;
+ i2c2 = &i2c_2;
+ i2c3 = &i2c_3;
+ i2c4 = &i2c_4;
+ i2c5 = &i2c_5;
+ i2c6 = &i2c_6;
+ i2c7 = &i2c_7;
+ i2c8 = &i2c_8;
};
};
&soc {
+ i2c_1: i2c@c175000 { /* BLSP1 QUP1 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc175000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 95 0>;
+ dmas = <&dma_blsp1 4 64 0x20000020 0x20>,
+ <&dma_blsp1 5 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <86>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP1_AHB_CLK>,
+ <&clock_gcc GCC_BLSP1_QUP1_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_1_active>;
+ pinctrl-1 = <&i2c_1_sleep>;
+ status = "disabled";
+ };
+
+ i2c_2: i2c@c176000 { /* BLSP1 QUP2 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc176000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 96 0>;
+ dmas = <&dma_blsp1 6 64 0x20000020 0x20>,
+ <&dma_blsp1 7 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <86>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP1_AHB_CLK>,
+ <&clock_gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_2_active>;
+ pinctrl-1 = <&i2c_2_sleep>;
+ status = "disabled";
+ };
+
+ i2c_3: i2c@c177000 { /* BLSP1 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc177000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 97 0>;
+ dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
+ <&dma_blsp1 9 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <86>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP1_AHB_CLK>,
+ <&clock_gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_3_active>;
+ pinctrl-1 = <&i2c_3_sleep>;
+ status = "disabled";
+ };
+
+ i2c_4: i2c@c178000 { /* BLSP1 QUP4 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc178000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 98 0>;
+ dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+ <&dma_blsp1 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <86>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP1_AHB_CLK>,
+ <&clock_gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_4_active>;
+ pinctrl-1 = <&i2c_4_sleep>;
+ status = "disabled";
+ };
+
+ i2c_5: i2c@c1b5000 { /* BLSP2 QUP1 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc1b5000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 101 0>;
+ dmas = <&dma_blsp2 4 64 0x20000020 0x20>,
+ <&dma_blsp2 5 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <84>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP2_AHB_CLK>,
+ <&clock_gcc GCC_BLSP2_QUP1_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_5_active>;
+ pinctrl-1 = <&i2c_5_sleep>;
+ status = "disabled";
+ };
+
+ i2c_6: i2c@c1b6000 { /* BLSP2 QUP2 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc1b6000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 102 0>;
+ dmas = <&dma_blsp2 6 64 0x20000020 0x20>,
+ <&dma_blsp2 7 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <84>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP2_AHB_CLK>,
+ <&clock_gcc GCC_BLSP2_QUP2_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_6_active>;
+ pinctrl-1 = <&i2c_6_sleep>;
+ status = "disabled";
+ };
+
+ i2c_7: i2c@c1b7000 { /* BLSP2 QUP3 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc1b7000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 103 0>;
+ dmas = <&dma_blsp2 8 64 0x20000020 0x20>,
+ <&dma_blsp2 9 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <84>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP2_AHB_CLK>,
+ <&clock_gcc GCC_BLSP2_QUP3_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_7_active>;
+ pinctrl-1 = <&i2c_7_sleep>;
+ status = "disabled";
+ };
+
+ i2c_8: i2c@c1b8000 { /* BLSP2 QUP4 */
+ compatible = "qcom,i2c-msm-v2";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc1b8000 0x600>;
+ reg-names = "qup_phys_addr";
+ interrupt-names = "qup_irq";
+ interrupts = <0 104 0>;
+ dmas = <&dma_blsp2 10 64 0x20000020 0x20>,
+ <&dma_blsp2 11 32 0x20000020 0x20>;
+ dma-names = "tx", "rx";
+ qcom,master-id = <84>;
+ qcom,clk-freq-out = <400000>;
+ qcom,clk-freq-in = <19200000>;
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc GCC_BLSP2_AHB_CLK>,
+ <&clock_gcc GCC_BLSP2_QUP4_I2C_APPS_CLK>;
+ pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-0 = <&i2c_8_active>;
+ pinctrl-1 = <&i2c_8_sleep>;
+ status = "disabled";
+ };
+
spi_1: spi@c175000 { /* BLSP1 QUP1 */
compatible = "qcom,spi-qup-v2";
#address-cells = <1>;
@@ -226,4 +418,152 @@
<&clock_gcc GCC_BLSP2_QUP4_SPI_APPS_CLK>;
status = "disabled";
};
+
+ blsp1_uart1_hs: uart@c16f000 { /* BLSP1 UART1 */
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0xc16f000 0x200>,
+ <0xc144000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp1_uart1_hs>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 107 0
+ 1 &intc 0 0 238 0
+ 2 &tlmm 1 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xfd>;
+
+ qcom,bam-tx-ep-pipe-index = <0>;
+ qcom,bam-rx-ep-pipe-index = <1>;
+ qcom,master-id = <86>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc GCC_BLSP1_UART1_APPS_CLK>,
+ <&clock_gcc GCC_BLSP1_AHB_CLK>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp1_uart1_sleep>;
+ pinctrl-1 = <&blsp1_uart1_active>;
+
+ qcom,msm-bus,name = "buart1";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <86 512 0 0>,
+ <86 512 500 800>;
+ status = "disabled";
+ };
+
+ blsp1_uart2_hs: uart@c170000 { /* BLSP1 UART2 */
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0xc170000 0x200>,
+ <0xc144000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp1_uart2_hs>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 108 0
+ 1 &intc 0 0 238 0
+ 2 &tlmm 5 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xfd>;
+
+ qcom,bam-tx-ep-pipe-index = <2>;
+ qcom,bam-rx-ep-pipe-index = <3>;
+ qcom,master-id = <86>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>,
+ <&clock_gcc GCC_BLSP1_AHB_CLK>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp1_uart2_sleep>;
+ pinctrl-1 = <&blsp1_uart2_active>;
+
+ qcom,msm-bus,name = "buart2";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <86 512 0 0>,
+ <86 512 500 800>;
+ status = "disabled";
+ };
+
+ blsp2_uart1_hs: uart@c1af000 { /* BLSP2 UART1 */
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0xc1af000 0x200>,
+ <0xc184000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp2_uart1_hs>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 113 0
+ 1 &intc 0 0 239 0
+ 2 &tlmm 17 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xfd>;
+
+ qcom,bam-tx-ep-pipe-index = <0>;
+ qcom,bam-rx-ep-pipe-index = <1>;
+ qcom,master-id = <84>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc GCC_BLSP2_UART1_APPS_CLK>,
+ <&clock_gcc GCC_BLSP2_AHB_CLK>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp2_uart1_sleep>;
+ pinctrl-1 = <&blsp2_uart1_active>;
+
+ qcom,msm-bus,name = "buart3";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <84 512 0 0>,
+ <84 512 500 800>;
+ status = "disabled";
+ };
+
+ blsp2_uart2_hs: uart@c1b0000 { /* BLSP2 UART2 */
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0xc1b0000 0x200>,
+ <0xc184000 0x1f000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp2_uart2_hs>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 0 114 0
+ 1 &intc 0 0 239 0
+ 2 &tlmm 25 0>;
+
+ qcom,inject-rx-on-wakeup;
+ qcom,rx-char-to-inject = <0xfd>;
+
+ qcom,bam-tx-ep-pipe-index = <2>;
+ qcom,bam-rx-ep-pipe-index = <3>;
+ qcom,master-id = <84>;
+ clock-names = "core_clk", "iface_clk";
+ clocks = <&clock_gcc GCC_BLSP2_UART2_APPS_CLK>,
+ <&clock_gcc GCC_BLSP2_AHB_CLK>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&blsp2_uart2_sleep>;
+ pinctrl-1 = <&blsp2_uart2_active>;
+
+ qcom,msm-bus,name = "buart4";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <84 512 0 0>,
+ <84 512 500 800>;
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-common.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-common.dtsi
new file mode 100644
index 000000000000..b3be67bd8c32
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmfalcon-common.dtsi
@@ -0,0 +1,196 @@
+/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+ usb3: ssusb@a800000 {
+ compatible = "qcom,dwc-usb3-msm";
+ reg = <0x0a800000 0xfc100>,
+ <0x0c016000 0x400>;
+ reg-names = "core_base",
+ "ahb2phy_base";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ interrupts = <0 347 0>, <0 243 0>, <0 180 0>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq", "pwr_event_irq";
+
+ USB3_GDSC-supply = <&gdsc_usb30>;
+
+ qcom,usb-dbm = <&dbm_1p5>;
+ qcom,msm-bus,name = "usb3";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <61 512 0 0>,
+ <61 512 240000 800000>;
+
+ qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
+
+ clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
+ <&clock_gcc GCC_CFG_NOC_USB3_AXI_CLK>,
+ <&clock_gcc GCC_AGGRE2_USB3_AXI_CLK>,
+ <&clock_gcc GCC_USB30_MOCK_UTMI_CLK>,
+ <&clock_gcc GCC_USB30_SLEEP_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&clock_rpmcc CXO_DWC3_CLK>;
+
+ clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
+ "utmi_clk", "sleep_clk", "cfg_ahb_clk", "xo";
+
+ resets = <&clock_gcc GCC_USB_30_BCR>;
+ reset-names = "core_reset";
+
+ dwc3@a800000 {
+ compatible = "snps,dwc3";
+ reg = <0x0a800000 0xc8d0>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 131 0>;
+ usb-phy = <&qusb_phy0>, <&ssphy>;
+ tx-fifo-resize;
+ snps,usb3-u1u2-disable;
+ snps,nominal-elastic-buffer;
+ snps,is-utmi-l1-suspend;
+ snps,hird-threshold = /bits/ 8 <0x0>;
+ };
+
+ qcom,usbbam@a904000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0x0a904000 0x17000>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 132 0>;
+
+ qcom,bam-type = <0>;
+ qcom,usb-bam-fifo-baseaddr = <0x066bb000>;
+ qcom,usb-bam-num-pipes = <8>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+ qcom,usb-bam-override-threshold = <0x4001>;
+ qcom,usb-bam-max-mbps-highspeed = <400>;
+ qcom,usb-bam-max-mbps-superspeed = <3600>;
+ qcom,reset-bam-on-connect;
+
+ qcom,pipe0 {
+ label = "ssusb-ipa-out-0";
+ qcom,usb-bam-mem-type = <1>;
+ qcom,dir = <0>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <1>;
+ qcom,src-bam-pipe-index = <1>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
+ };
+ qcom,pipe1 {
+ label = "ssusb-ipa-in-0";
+ qcom,usb-bam-mem-type = <1>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <1>;
+ qcom,dst-bam-pipe-index = <0>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
+ };
+ qcom,pipe2 {
+ label = "ssusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <2>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <0>;
+ qcom,peer-bam-physical-address = <0x06064000>;
+ qcom,src-bam-pipe-index = <0>;
+ qcom,dst-bam-pipe-index = <2>;
+ qcom,data-fifo-offset = <0x0>;
+ qcom,data-fifo-size = <0x1800>;
+ qcom,descriptor-fifo-offset = <0x1800>;
+ qcom,descriptor-fifo-size = <0x800>;
+ };
+ qcom,pipe3 {
+ label = "ssusb-dpl-ipa-in-1";
+ qcom,usb-bam-mem-type = <1>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <1>;
+ qcom,peer-bam = <1>;
+ qcom,dst-bam-pipe-index = <2>;
+ qcom,data-fifo-size = <0x8000>;
+ qcom,descriptor-fifo-size = <0x2000>;
+ };
+ };
+ };
+
+ qusb_phy0: qusb@c012000 {
+ compatible = "qcom,qusb2phy";
+ reg = <0x0c012000 0x180>,
+ <0x00188018 0x4>;
+ reg-names = "qusb_phy_base",
+ "ref_clk_addr";
+ vdd-supply = <&pm2falcon_l1>;
+ vdda18-supply = <&pmfalcon_l10>;
+ vdda33-supply = <&pm2falcon_l7>;
+ qcom,vdd-voltage-level = <0 925000 925000>;
+ qcom,tune2-efuse-bit-pos = <21>;
+ qcom,tune2-efuse-num-bits = <4>;
+ qcom,enable-dpdm-pulsing;
+ qcom,qusb-phy-init-seq = <0xf8 0x80
+ 0xb3 0x84
+ 0x83 0x88
+ 0xc0 0x8c
+ 0x30 0x08
+ 0x79 0x0c
+ 0x21 0x10
+ 0x14 0x9c
+ 0x9f 0x1c
+ 0x00 0x18>;
+ phy_type= "utmi";
+
+ clocks = <&clock_rpmcc RPM_LN_BB_CLK1>,
+ <&clock_gcc GCC_RX0_USB2_CLKREF_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
+
+ clock-names = "ref_clk_src", "ref_clk", "cfg_ahb_clk";
+
+ resets = <&clock_gcc GCC_QUSB2PHY_PRIM_BCR>;
+ reset-names = "phy_reset";
+ };
+
+ ssphy: ssphy@c010000 {
+ compatible = "qcom,usb-ssphy-qmp-v2";
+ reg = <0xc010000 0x7a8>,
+ <0x01fcb244 0x4>,
+ <0x01fcb248 0x4>;
+ reg-names = "qmp_phy_base",
+ "vls_clamp_reg",
+ "tcsr_usb3_dp_phymode";
+ vdd-supply = <&pm2falcon_l1>;
+ core-supply = <&pmfalcon_l10>;
+ qcom,vdd-voltage-level = <0 925000 925000>;
+ qcom,vbus-valid-override;
+
+ clocks = <&clock_gcc GCC_USB3_PHY_AUX_CLK>,
+ <&clock_gcc GCC_USB3_PHY_PIPE_CLK>,
+ <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&clock_rpmcc RPM_LN_BB_CLK1>,
+ <&clock_gcc GCC_USB3_CLKREF_CLK>;
+
+ clock-names = "aux_clk", "pipe_clk", "cfg_ahb_clk",
+ "ref_clk_src", "ref_clk";
+
+ resets = <&clock_gcc GCC_USB3_PHY_BCR>,
+ <&clock_gcc GCC_USB3PHY_PHY_BCR>;
+ reset-names = "phy_reset", "phy_phy_reset";
+ };
+
+ dbm_1p5: dbm@a8f8000 {
+ compatible = "qcom,usb-dbm-1p5";
+ reg = <0xa8f8000 0x300>;
+ qcom,reset-ep-after-lpm-resume;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
index f13e34f8296b..90aa771332a3 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi
@@ -22,12 +22,12 @@
uart_console_active: uart_console_active {
mux {
- pins = "gpio0", "gpio1";
- function = "blsp_uart1";
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
};
config {
- pins = "gpio0", "gpio1";
+ pins = "gpio4", "gpio5";
drive-strength = <2>;
bias-disable;
};
@@ -113,6 +113,231 @@
};
};
+ /* I2C CONFIGURATION */
+ i2c_1 {
+ i2c_1_active: i2c_1_active {
+ mux {
+ pins = "gpio2", "gpio3";
+ function = "blsp_i2c1";
+ };
+
+ config {
+ pins = "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_1_sleep: i2c_1_sleep {
+ mux {
+ pins = "gpio2", "gpio3";
+ function = "blsp_i2c1";
+ };
+
+ config {
+ pins = "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_2 {
+ i2c_2_active: i2c_2_active {
+ mux {
+ pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
+ };
+
+ config {
+ pins = "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_2_sleep: i2c_2_sleep {
+ mux {
+ pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
+ };
+
+ config {
+ pins = "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_3 {
+ i2c_3_active: i2c_3_active {
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "blsp_i2c3";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_3_sleep: i2c_3_sleep {
+ mux {
+ pins = "gpio10", "gpio11";
+ function = "blsp_i2c3";
+ };
+
+ config {
+ pins = "gpio10", "gpio11";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_4 {
+ i2c_4_active: i2c_4_active {
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ mux {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ };
+
+ config {
+ pins = "gpio14", "gpio15";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_5 {
+ i2c_5_active: i2c_5_active {
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "blsp_i2c5";
+ };
+
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_5_sleep: i2c_5_sleep {
+ mux {
+ pins = "gpio18", "gpio19";
+ function = "blsp_i2c5";
+ };
+
+ config {
+ pins = "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_6 {
+ i2c_6_active: i2c_6_active {
+ mux {
+ pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
+ };
+
+ config {
+ pins = "gpio22", "gpio23";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_6_sleep: i2c_6_sleep {
+ mux {
+ pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
+ };
+
+ config {
+ pins = "gpio22", "gpio23";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_7 {
+ i2c_7_active: i2c_7_active {
+ mux {
+ pins = "gpio26", "gpio27";
+ function = "blsp_i2c7";
+ };
+
+ config {
+ pins = "gpio26", "gpio27";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_7_sleep: i2c_7_sleep {
+ mux {
+ pins = "gpio26", "gpio27";
+ function = "blsp_i2c7";
+ };
+
+ config {
+ pins = "gpio26", "gpio27";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ i2c_8 {
+ i2c_8_active: i2c_8_active {
+ mux {
+ pins = "gpio30", "gpio31";
+ function = "blsp_i2c8_a";
+ };
+
+ config {
+ pins = "gpio30", "gpio31";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ i2c_8_sleep: i2c_8_sleep {
+ mux {
+ pins = "gpio30", "gpio31";
+ function = "blsp_i2c8_a";
+ };
+
+ config {
+ pins = "gpio30", "gpio31";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
/* SPI CONFIGURATION */
spi_1 {
spi_1_active: spi_1_active {
@@ -369,5 +594,110 @@
};
};
};
+
+ /* HS UART CONFIGURATION */
+ blsp1_uart1_active: blsp1_uart1_active {
+ mux {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "blsp_uart1";
+ };
+
+ config {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart1_sleep: blsp1_uart1_sleep {
+ mux {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart2_active: blsp1_uart2_active {
+ mux {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ function = "blsp_uart2 ";
+ };
+
+ config {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart2_sleep: blsp1_uart2_sleep {
+ mux {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart1_active: blsp2_uart1_active {
+ mux {
+ pins = "gpio16", "gpio17", "gpio18", "gpio19";
+ function = "blsp_uart5";
+ };
+
+ config {
+ pins = "gpio16", "gpio17", "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart1_sleep: blsp2_uart1_sleep {
+ mux {
+ pins = "gpio16", "gpio17", "gpio18", "gpio19";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio16", "gpio17", "gpio18", "gpio19";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart2_active: blsp2_uart2_active {
+ mux {
+ pins = "gpio24", "gpio25", "gpio26", "gpio27";
+ function = "blsp_uart6_a";
+ };
+
+ config {
+ pins = "gpio24", "gpio25", "gpio26", "gpio27";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp2_uart2_sleep: blsp2_uart2_sleep {
+ mux {
+ pins = "gpio24", "gpio25", "gpio26", "gpio27";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio24", "gpio25", "gpio26", "gpio27";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
index c94ba0df3e6e..1840221359e3 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
@@ -26,6 +26,38 @@
};
};
+&usb3 {
+ /delete-property/ USB3_GDSC-supply;
+ dwc3@a800000 {
+ maximum-speed = "high-speed";
+ };
+};
+
+&ssphy {
+ compatible = "usb-nop-xceiv";
+};
+
+&qusb_phy0 {
+ reg = <0x0a928000 0x8000>,
+ <0x0a8f8800 0x400>,
+ <0x0a920000 0x100>;
+ reg-names = "qusb_phy_base",
+ "qscratch_base",
+ "emu_phy_base";
+ qcom,emulation;
+ qcom,qusb-phy-init-seq = <0x19 0x1404
+ 0x20 0x1414
+ 0x79 0x1410
+ 0x00 0x1418
+ 0x99 0x1404
+ 0x04 0x1408
+ 0xd9 0x1404>;
+ qcom,emu-dcm-reset-seq = <0x100000 0x20
+ 0x0 0x20
+ 0x1a0 0x20
+ 0x5 0x14>;
+};
+
&uartblsp1dm1 {
status = "ok";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
index 00d97c8fdd32..47759c9ce3ff 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
@@ -26,6 +26,22 @@
};
};
+&usb3 {
+ reg = <0xa800000 0xfc000>;
+ reg-names = "core_base";
+ dwc3@a800000 {
+ maximum-speed = "high-speed";
+ };
+};
+
+&ssphy {
+ compatible = "usb-nop-xceiv";
+};
+
+&qusb_phy0 {
+ compatible = "usb-nop-xceiv";
+};
+
&uartblsp1dm1 {
status = "ok";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 473270d6e87d..23d3043fcc3b 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -249,6 +249,22 @@
clock-frequency = <19200000>;
};
+ dma_blsp1: qcom,sps-dma@0xc144000{ /* BLSP1 */
+ #dma-cells = <4>;
+ compatible = "qcom,sps-dma";
+ reg = <0xc144000 0x1F000>;
+ interrupts = <0 238 0>;
+ qcom,summing-threshold = <0x10>;
+ };
+
+ dma_blsp2: qcom,sps-dma@0xc184000{ /* BLSP2 */
+ #dma-cells = <4>;
+ compatible = "qcom,sps-dma";
+ reg = <0xc184000 0x1F000>;
+ interrupts = <0 239 0>;
+ qcom,summing-threshold = <0x10>;
+ };
+
spmi_bus: qcom,spmi@800f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x800f000 0x1000>,
@@ -873,6 +889,23 @@
reg = <0x94c 200>;
};
};
+
+ qcom,ghd {
+ compatible = "qcom,gladiator-hang-detect";
+ qcom,threshold-arr = <0x179d141c 0x179d1420
+ 0x179d1424 0x179d1428
+ 0x179d142c 0x179d1430>;
+ qcom,config-reg = <0x179d1434>;
+ };
+
+ qcom,msm-gladiator-v2@17900000 {
+ compatible = "qcom,msm-gladiator-v2";
+ reg = <0x17900000 0xe000>;
+ reg-names = "gladiator_base";
+ interrupts = <0 22 0>;
+ clock-names = "atb_clk";
+ clocks = <&clock_rpmcc RPM_QDSS_CLK>;
+ };
};
#include "msmfalcon-ion.dtsi"
@@ -967,4 +1000,5 @@
#include "msm-pm2falcon.dtsi"
#include "msm-arm-smmu-falcon.dtsi"
#include "msm-arm-smmu-impl-defs-falcon.dtsi"
+#include "msmfalcon-common.dtsi"
#include "msmfalcon-blsp.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts
index 0317c35d1f44..08809fb38cae 100644
--- a/arch/arm/boot/dts/qcom/msmtriton-rumi.dts
+++ b/arch/arm/boot/dts/qcom/msmtriton-rumi.dts
@@ -22,6 +22,37 @@
qcom,board-id = <15 0>;
};
+&usb3 {
+ dwc3@a800000 {
+ maximum-speed = "high-speed";
+ };
+};
+
+&ssphy {
+ compatible = "usb-nop-xceiv";
+};
+
+&qusb_phy0 {
+ reg = <0x0a928000 0x8000>,
+ <0x0a8f8800 0x400>,
+ <0x0a920000 0x100>;
+ reg-names = "qusb_phy_base",
+ "qscratch_base",
+ "emu_phy_base";
+ qcom,emulation;
+ qcom,qusb-phy-init-seq = <0x19 0x1404
+ 0x20 0x1414
+ 0x79 0x1410
+ 0x00 0x1418
+ 0x99 0x1404
+ 0x04 0x1408
+ 0xd9 0x1404>;
+ qcom,emu-dcm-reset-seq = <0x100000 0x20
+ 0x0 0x20
+ 0x1a0 0x20
+ 0x5 0x14>;
+};
+
&uartblsp1dm1 {
status = "ok";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi
index 06f296a49113..cd751f3181ee 100644
--- a/arch/arm/boot/dts/qcom/msmtriton.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi
@@ -710,11 +710,29 @@
reg = <0x94c 200>;
};
};
+
+ qcom,ghd {
+ compatible = "qcom,gladiator-hang-detect";
+ qcom,threshold-arr = <0x179d141c 0x179d1420
+ 0x179d1424 0x179d1428
+ 0x179d142c 0x179d1430>;
+ qcom,config-reg = <0x179d1434>;
+ };
+
+ qcom,msm-gladiator-v2@17900000 {
+ compatible = "qcom,msm-gladiator-v2";
+ reg = <0x17900000 0xe000>;
+ reg-names = "gladiator_base";
+ interrupts = <0 22 0>;
+ clock-names = "atb_clk";
+ clocks = <&clock_rpmcc RPM_QDSS_CLK>;
+ };
};
#include "msmtriton-ion.dtsi"
#include "msmtriton-regulator.dtsi"
#include "msm-gdsc-falcon.dtsi"
+#include "msmfalcon-common.dtsi"
&gdsc_usb30 {
clock-names = "core_clk";
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 511b9fe32b9b..d10fba1dc4b5 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -337,6 +337,7 @@ CONFIG_FB_MSM=y
CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
CONFIG_FB_MSM_MDSS_HDMI_PANEL=y
+CONFIG_FB_MSM_MDSS_DP_PANEL=y
CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a5781f6db269..9d0955289796 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -3434,9 +3434,6 @@ static int __init diagchar_init(void)
ret = diagfwd_init();
if (ret)
goto fail;
- ret = diagfwd_bridge_init();
- if (ret)
- goto fail;
ret = diagfwd_cntl_init();
if (ret)
goto fail;
@@ -3467,6 +3464,9 @@ static int __init diagchar_init(void)
goto fail;
pr_debug("diagchar initialized now");
+ ret = diagfwd_bridge_init();
+ if (ret)
+ diagfwd_bridge_exit();
return 0;
fail:
@@ -3482,6 +3482,7 @@ fail:
diag_masks_exit();
diag_remote_exit();
return -1;
+
}
static void diagchar_exit(void)
diff --git a/drivers/char/diag/diagfwd_glink.c b/drivers/char/diag/diagfwd_glink.c
index a2ffabe43c86..ce523ac35a51 100644
--- a/drivers/char/diag/diagfwd_glink.c
+++ b/drivers/char/diag/diagfwd_glink.c
@@ -455,6 +455,8 @@ static void diag_glink_transport_notify_state(void *handle, const void *priv,
"%s received channel remote disconnect for periph:%d\n",
glink_info->name, glink_info->peripheral);
atomic_set(&glink_info->opened, 0);
+ diagfwd_channel_close(glink_info->fwd_ctxt);
+ atomic_set(&glink_info->tx_intent_ready, 0);
break;
default:
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
@@ -501,6 +503,7 @@ static void diag_glink_close_work_fn(struct work_struct *work)
glink_close(glink_info->hdl);
atomic_set(&glink_info->opened, 0);
+ atomic_set(&glink_info->tx_intent_ready, 0);
glink_info->hdl = NULL;
diagfwd_channel_close(glink_info->fwd_ctxt);
}
diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c
index f7b1e98f22b0..df26e2522baf 100644
--- a/drivers/char/diag/diagfwd_mhi.c
+++ b/drivers/char/diag/diagfwd_mhi.c
@@ -49,6 +49,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV] = {
.enabled = 0,
.num_read = 0,
.mempool = POOL_TYPE_MDM,
+ .mempool_init = 0,
.mhi_wq = NULL,
.read_ch = {
.chan = MHI_CLIENT_DIAG_IN,
@@ -68,6 +69,7 @@ struct diag_mhi_info diag_mhi[NUM_MHI_DEV] = {
.enabled = 0,
.num_read = 0,
.mempool = POOL_TYPE_MDM_DCI,
+ .mempool_init = 0,
.mhi_wq = NULL,
.read_ch = {
.chan = MHI_CLIENT_DCI_IN,
@@ -684,6 +686,7 @@ int diag_mhi_init()
strlcpy(wq_name, "diag_mhi_", DIAG_MHI_STRING_SZ);
strlcat(wq_name, mhi_info->name, sizeof(mhi_info->name));
diagmem_init(driver, mhi_info->mempool);
+ mhi_info->mempool_init = 1;
mhi_info->mhi_wq = create_singlethread_workqueue(wq_name);
if (!mhi_info->mhi_wq)
goto fail;
@@ -725,7 +728,8 @@ void diag_mhi_exit()
if (mhi_info->mhi_wq)
destroy_workqueue(mhi_info->mhi_wq);
mhi_close(mhi_info->id);
- diagmem_exit(driver, mhi_info->mempool);
+ if (mhi_info->mempool_init)
+ diagmem_exit(driver, mhi_info->mempool);
}
}
diff --git a/drivers/char/diag/diagfwd_mhi.h b/drivers/char/diag/diagfwd_mhi.h
index 8332efdf5efb..a4466977ca97 100644
--- a/drivers/char/diag/diagfwd_mhi.h
+++ b/drivers/char/diag/diagfwd_mhi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 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
@@ -65,6 +65,7 @@ struct diag_mhi_info {
int id;
int dev_id;
int mempool;
+ int mempool_init;
int num_read;
uint8_t enabled;
char name[DIAG_MHI_NAME_SZ];
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 40fdcbaaf31a..c78a5f4fbe74 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -438,6 +438,7 @@ int diagfwd_peripheral_init(void)
fwd_info->read_bytes = 0;
fwd_info->write_bytes = 0;
spin_lock_init(&fwd_info->buf_lock);
+ spin_lock_init(&fwd_info->write_buf_lock);
mutex_init(&fwd_info->data_mutex);
}
}
@@ -453,6 +454,7 @@ int diagfwd_peripheral_init(void)
fwd_info->read_bytes = 0;
fwd_info->write_bytes = 0;
spin_lock_init(&fwd_info->buf_lock);
+ spin_lock_init(&fwd_info->write_buf_lock);
mutex_init(&fwd_info->data_mutex);
/*
* This state shouldn't be set for Control channels
@@ -686,16 +688,19 @@ void *diagfwd_request_write_buf(struct diagfwd_info *fwd_info)
{
void *buf = NULL;
int index;
+ unsigned long flags;
+ spin_lock_irqsave(&fwd_info->write_buf_lock, flags);
for (index = 0 ; index < NUM_WRITE_BUFFERS; index++) {
if (!atomic_read(&(fwd_info->buf_ptr[index]->in_busy))) {
+ atomic_set(&(fwd_info->buf_ptr[index]->in_busy), 1);
buf = fwd_info->buf_ptr[index]->data;
if (!buf)
return NULL;
- atomic_set(&(fwd_info->buf_ptr[index]->in_busy), 1);
break;
}
}
+ spin_unlock_irqrestore(&fwd_info->write_buf_lock, flags);
return buf;
}
@@ -760,7 +765,6 @@ int diagfwd_write(uint8_t peripheral, uint8_t type, void *buf, int len)
static void __diag_fwd_open(struct diagfwd_info *fwd_info)
{
- int i;
if (!fwd_info)
return;
@@ -775,10 +779,7 @@ static void __diag_fwd_open(struct diagfwd_info *fwd_info)
if (fwd_info->p_ops && fwd_info->p_ops->open)
fwd_info->p_ops->open(fwd_info->ctxt);
- for (i = 0; i < NUM_WRITE_BUFFERS; i++) {
- if (fwd_info->buf_ptr[i])
- atomic_set(&fwd_info->buf_ptr[i]->in_busy, 0);
- }
+
diagfwd_queue_read(fwd_info);
}
@@ -839,6 +840,7 @@ void diagfwd_close(uint8_t peripheral, uint8_t type)
int diagfwd_channel_open(struct diagfwd_info *fwd_info)
{
+ int i;
if (!fwd_info)
return -EIO;
@@ -859,6 +861,10 @@ int diagfwd_channel_open(struct diagfwd_info *fwd_info)
diagfwd_write_buffers_init(fwd_info);
if (fwd_info && fwd_info->c_ops && fwd_info->c_ops->open)
fwd_info->c_ops->open(fwd_info);
+ for (i = 0; i < NUM_WRITE_BUFFERS; i++) {
+ if (fwd_info->buf_ptr[i])
+ atomic_set(&fwd_info->buf_ptr[i]->in_busy, 0);
+ }
diagfwd_queue_read(fwd_info);
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "p: %d t: %d considered opened\n",
fwd_info->peripheral, fwd_info->type);
@@ -873,6 +879,7 @@ int diagfwd_channel_open(struct diagfwd_info *fwd_info)
int diagfwd_channel_close(struct diagfwd_info *fwd_info)
{
+ int i;
if (!fwd_info)
return -EIO;
@@ -885,6 +892,10 @@ int diagfwd_channel_close(struct diagfwd_info *fwd_info)
if (fwd_info->buf_2 && fwd_info->buf_2->data)
atomic_set(&fwd_info->buf_2->in_busy, 0);
+ for (i = 0; i < NUM_WRITE_BUFFERS; i++) {
+ if (fwd_info->buf_ptr[i])
+ atomic_set(&fwd_info->buf_ptr[i]->in_busy, 1);
+ }
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "p: %d t: %d considered closed\n",
fwd_info->peripheral, fwd_info->type);
@@ -940,10 +951,11 @@ int diagfwd_write_buffer_done(struct diagfwd_info *fwd_info, const void *ptr)
int found = 0;
int index = 0;
+ unsigned long flags;
if (!fwd_info || !ptr)
return found;
-
+ spin_lock_irqsave(&fwd_info->write_buf_lock, flags);
for (index = 0; index < NUM_WRITE_BUFFERS; index++) {
if (fwd_info->buf_ptr[index]->data == ptr) {
atomic_set(&fwd_info->buf_ptr[index]->in_busy, 0);
@@ -951,6 +963,7 @@ int diagfwd_write_buffer_done(struct diagfwd_info *fwd_info, const void *ptr)
break;
}
}
+ spin_unlock_irqrestore(&fwd_info->write_buf_lock, flags);
return found;
}
@@ -1197,7 +1210,7 @@ void diagfwd_write_buffers_init(struct diagfwd_info *fwd_info)
return;
}
- spin_lock_irqsave(&fwd_info->buf_lock, flags);
+ spin_lock_irqsave(&fwd_info->write_buf_lock, flags);
for (i = 0; i < NUM_WRITE_BUFFERS; i++) {
if (!fwd_info->buf_ptr[i])
fwd_info->buf_ptr[i] =
@@ -1215,11 +1228,11 @@ void diagfwd_write_buffers_init(struct diagfwd_info *fwd_info)
kmemleak_not_leak(fwd_info->buf_ptr[i]->data);
}
}
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ spin_unlock_irqrestore(&fwd_info->write_buf_lock, flags);
return;
err:
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ spin_unlock_irqrestore(&fwd_info->write_buf_lock, flags);
pr_err("diag:unable to allocate write buffers\n");
diagfwd_write_buffers_exit(fwd_info);
@@ -1233,7 +1246,7 @@ static void diagfwd_write_buffers_exit(struct diagfwd_info *fwd_info)
if (!fwd_info)
return;
- spin_lock_irqsave(&fwd_info->buf_lock, flags);
+ spin_lock_irqsave(&fwd_info->write_buf_lock, flags);
for (i = 0; i < NUM_WRITE_BUFFERS; i++) {
if (fwd_info->buf_ptr[i]) {
kfree(fwd_info->buf_ptr[i]->data);
@@ -1242,5 +1255,5 @@ static void diagfwd_write_buffers_exit(struct diagfwd_info *fwd_info)
fwd_info->buf_ptr[i] = NULL;
}
}
- spin_unlock_irqrestore(&fwd_info->buf_lock, flags);
+ spin_unlock_irqrestore(&fwd_info->write_buf_lock, flags);
}
diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h
index b511bf495bc2..cbbab86a9425 100644
--- a/drivers/char/diag/diagfwd_peripheral.h
+++ b/drivers/char/diag/diagfwd_peripheral.h
@@ -71,6 +71,7 @@ struct diagfwd_info {
unsigned long read_bytes;
unsigned long write_bytes;
spinlock_t buf_lock;
+ spinlock_t write_buf_lock;
struct mutex data_mutex;
void *ctxt;
struct diagfwd_buf_t *buf_1;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1eb6e32e0d51..25ab30063072 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2267,6 +2267,7 @@ EXPORT_SYMBOL_GPL(clk_set_flags);
static struct dentry *rootdir;
static int inited = 0;
+static u32 debug_suspend;
static DEFINE_MUTEX(clk_debug_lock);
static HLIST_HEAD(clk_debug_list);
@@ -2409,6 +2410,309 @@ static const struct file_operations clk_dump_fops = {
.release = single_release,
};
+static int clock_debug_rate_set(void *data, u64 val)
+{
+ struct clk_core *core = data;
+ int ret;
+
+ ret = clk_set_rate(core->hw->clk, val);
+ if (ret)
+ pr_err("clk_set_rate(%lu) failed (%d)\n",
+ (unsigned long)val, ret);
+
+ return ret;
+}
+
+static int clock_debug_rate_get(void *data, u64 *val)
+{
+ struct clk_core *core = data;
+
+ *val = core->hw->core->rate;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
+ clock_debug_rate_set, "%llu\n");
+
+static ssize_t clock_parent_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char name[256] = {0};
+ struct clk_core *core = filp->private_data;
+ struct clk_core *p = core->hw->core->parent;
+
+ snprintf(name, sizeof(name), "%s\n", p ? p->name : "None\n");
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, name, strlen(name));
+}
+
+static const struct file_operations clock_parent_fops = {
+ .open = simple_open,
+ .read = clock_parent_read,
+};
+
+static int clock_debug_enable_set(void *data, u64 val)
+{
+ struct clk_core *core = data;
+ int rc = 0;
+
+ if (val)
+ rc = clk_prepare_enable(core->hw->clk);
+ else
+ clk_disable_unprepare(core->hw->clk);
+
+ return rc;
+}
+
+static int clock_debug_enable_get(void *data, u64 *val)
+{
+ struct clk_core *core = data;
+ int enabled = 0;
+
+ enabled = core->enable_count;
+
+ *val = enabled;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
+ clock_debug_enable_set, "%lld\n");
+
+#define clock_debug_output(m, c, fmt, ...) \
+do { \
+ if (m) \
+ seq_printf(m, fmt, ##__VA_ARGS__); \
+ else if (c) \
+ pr_cont(fmt, ##__VA_ARGS__); \
+ else \
+ pr_info(fmt, ##__VA_ARGS__); \
+} while (0)
+
+int clock_debug_print_clock(struct clk_core *c, struct seq_file *s)
+{
+ char *start = "";
+ struct clk *clk;
+
+ if (!c || !c->prepare_count)
+ return 0;
+
+ clk = c->hw->clk;
+
+ clock_debug_output(s, 0, "\t");
+
+ do {
+ if (clk->core->vdd_class)
+ clock_debug_output(s, 1, "%s%s:%u:%u [%ld, %d]", start,
+ clk->core->name,
+ clk->core->prepare_count,
+ clk->core->enable_count,
+ clk->core->rate,
+ clk_find_vdd_level(clk->core, clk->core->rate));
+ else
+ clock_debug_output(s, 1, "%s%s:%u:%u [%ld]", start,
+ clk->core->name,
+ clk->core->prepare_count,
+ clk->core->enable_count,
+ clk->core->rate);
+ start = " -> ";
+ } while ((clk = clk_get_parent(clk)));
+
+ clock_debug_output(s, 1, "\n");
+
+ return 1;
+}
+
+/*
+ * clock_debug_print_enabled_clocks() - Print names of enabled clocks
+ */
+static void clock_debug_print_enabled_clocks(struct seq_file *s)
+{
+ struct clk_core *core;
+ int cnt = 0;
+
+ clock_debug_output(s, 0, "Enabled clocks:\n");
+
+ mutex_lock(&clk_debug_lock);
+
+ hlist_for_each_entry(core, &clk_debug_list, debug_node)
+ cnt += clock_debug_print_clock(core, s);
+
+ mutex_unlock(&clk_debug_lock);
+
+ if (cnt)
+ clock_debug_output(s, 0, "Enabled clock count: %d\n", cnt);
+ else
+ clock_debug_output(s, 0, "No clocks enabled.\n");
+}
+
+static int enabled_clocks_show(struct seq_file *s, void *unused)
+{
+ clock_debug_print_enabled_clocks(s);
+
+ return 0;
+}
+
+static int enabled_clocks_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, enabled_clocks_show, inode->i_private);
+}
+
+static const struct file_operations clk_enabled_list_fops = {
+ .open = enabled_clocks_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static void clk_debug_print_hw(struct clk_core *clk, struct seq_file *f)
+{
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
+ clk_debug_print_hw(clk->parent, f);
+
+ clock_debug_output(f, false, "%s\n", clk->name);
+
+ if (!clk->ops->list_registers)
+ return;
+
+ clk->ops->list_registers(f, clk->hw);
+}
+
+static int print_hw_show(struct seq_file *m, void *unused)
+{
+ struct clk_core *c = m->private;
+
+ clk_debug_print_hw(c, m);
+
+ return 0;
+}
+
+static int print_hw_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, print_hw_show, inode->i_private);
+}
+
+static const struct file_operations clock_print_hw_fops = {
+ .open = print_hw_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int list_rates_show(struct seq_file *s, void *unused)
+{
+ struct clk_core *core = s->private;
+ int level = 0, i = 0;
+ unsigned long rate, rate_max = 0;
+
+ /* Find max frequency supported within voltage constraints. */
+ if (!core->vdd_class) {
+ rate_max = ULONG_MAX;
+ } else {
+ for (level = 0; level < core->num_rate_max; level++)
+ if (core->rate_max[level])
+ rate_max = core->rate_max[level];
+ }
+
+ /*
+ * List supported frequencies <= rate_max. Higher frequencies may
+ * appear in the frequency table, but are not valid and should not
+ * be listed.
+ */
+ while (!IS_ERR_VALUE(rate =
+ core->ops->list_rate(core->hw, i++, rate_max))) {
+ if (rate <= 0)
+ break;
+ if (rate <= rate_max)
+ seq_printf(s, "%lu\n", rate);
+ }
+
+ return 0;
+}
+
+static int list_rates_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, list_rates_show, inode->i_private);
+}
+
+static const struct file_operations list_rates_fops = {
+ .open = list_rates_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static void clock_print_rate_max_by_level(struct seq_file *s, int level)
+{
+ struct clk_core *core = s->private;
+ struct clk_vdd_class *vdd_class = core->vdd_class;
+ int off, i, vdd_level, nregs = vdd_class->num_regulators;
+
+ vdd_level = clk_find_vdd_level(core, core->rate);
+
+ seq_printf(s, "%2s%10lu", vdd_level == level ? "[" : "",
+ core->rate_max[level]);
+
+ for (i = 0; i < nregs; i++) {
+ off = nregs*level + i;
+ if (vdd_class->vdd_uv)
+ seq_printf(s, "%10u", vdd_class->vdd_uv[off]);
+ }
+
+ if (vdd_level == level)
+ seq_puts(s, "]");
+
+ seq_puts(s, "\n");
+}
+
+static int rate_max_show(struct seq_file *s, void *unused)
+{
+ struct clk_core *core = s->private;
+ struct clk_vdd_class *vdd_class = core->vdd_class;
+ int level = 0, i, nregs = vdd_class->num_regulators;
+ char reg_name[10];
+
+ int vdd_level = clk_find_vdd_level(core, core->rate);
+
+ if (vdd_level < 0) {
+ seq_printf(s, "could not find_vdd_level for %s, %ld\n",
+ core->name, core->rate);
+ return 0;
+ }
+
+ seq_printf(s, "%12s", "");
+ for (i = 0; i < nregs; i++) {
+ snprintf(reg_name, ARRAY_SIZE(reg_name), "reg %d", i);
+ seq_printf(s, "%10s", reg_name);
+ }
+
+ seq_printf(s, "\n%12s", "freq");
+ for (i = 0; i < nregs; i++)
+ seq_printf(s, "%10s", "uV");
+
+ seq_puts(s, "\n");
+
+ for (level = 0; level < core->num_rate_max; level++)
+ clock_print_rate_max_by_level(s, level);
+
+ return 0;
+}
+
+static int rate_max_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, rate_max_show, inode->i_private);
+}
+
+static const struct file_operations rate_max_fops = {
+ .open = rate_max_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
struct dentry *d;
@@ -2425,11 +2729,21 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
core->dentry = d;
- d = debugfs_create_u32("clk_rate", S_IRUGO, core->dentry,
- (u32 *)&core->rate);
+ d = debugfs_create_file("clk_rate", S_IRUGO, core->dentry, core,
+ &clock_rate_fops);
if (!d)
goto err_out;
+ if (core->ops->list_rate) {
+ if (!debugfs_create_file("clk_list_rates",
+ S_IRUGO, core->dentry, core, &list_rates_fops))
+ goto err_out;
+ }
+
+ if (core->vdd_class && !debugfs_create_file("clk_rate_max",
+ S_IRUGO, core->dentry, core, &rate_max_fops))
+ goto err_out;
+
d = debugfs_create_u32("clk_accuracy", S_IRUGO, core->dentry,
(u32 *)&core->accuracy);
if (!d)
@@ -2450,8 +2764,8 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
if (!d)
goto err_out;
- d = debugfs_create_u32("clk_enable_count", S_IRUGO, core->dentry,
- (u32 *)&core->enable_count);
+ d = debugfs_create_file("clk_enable_count", S_IRUGO, core->dentry,
+ core, &clock_enable_fops);
if (!d)
goto err_out;
@@ -2460,6 +2774,16 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
if (!d)
goto err_out;
+ d = debugfs_create_file("clk_parent", S_IRUGO, core->dentry, core,
+ &clock_parent_fops);
+ if (!d)
+ goto err_out;
+
+ d = debugfs_create_file("clk_print_regs", S_IRUGO, core->dentry,
+ core, &clock_print_hw_fops);
+ if (!d)
+ goto err_out;
+
if (core->ops->debug_init) {
ret = core->ops->debug_init(core->hw, core->dentry);
if (ret)
@@ -2531,6 +2855,19 @@ struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
+/*
+ * Print the names of all enabled clocks and their parents if
+ * debug_suspend is set from debugfs.
+ */
+void clock_debug_print_enabled(void)
+{
+ if (likely(!debug_suspend))
+ return;
+
+ clock_debug_print_enabled_clocks(NULL);
+}
+EXPORT_SYMBOL_GPL(clock_debug_print_enabled);
+
/**
* clk_debug_init - lazily populate the debugfs clk directory
*
@@ -2570,6 +2907,17 @@ static int __init clk_debug_init(void)
if (!d)
return -ENOMEM;
+ d = debugfs_create_file("clk_enabled_list", S_IRUGO, rootdir,
+ &clk_debug_list, &clk_enabled_list_fops);
+ if (!d)
+ return -ENOMEM;
+
+
+ d = debugfs_create_u32("debug_suspend", S_IRUGO | S_IWUSR,
+ rootdir, &debug_suspend);
+ if (!d)
+ return -ENOMEM;
+
mutex_lock(&clk_debug_lock);
hlist_for_each_entry(core, &clk_debug_list, debug_node)
clk_debug_create_one(core, rootdir);
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 97941b0f8f32..179b27c08022 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -20,6 +20,10 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec,
struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
const char *con_id);
void __clk_free_clk(struct clk *clk);
+
+/* Debugfs API to print the enabled clocks */
+void clock_debug_print_enabled(void);
+
#else
/* All these casts to avoid ifdefs in clkdev... */
static inline struct clk *
diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c
index 9c1cdf967fb1..9e2a8fcab2a6 100644
--- a/drivers/clk/msm/clock-mmss-cobalt.c
+++ b/drivers/clk/msm/clock-mmss-cobalt.c
@@ -245,6 +245,7 @@ static struct rcg_clk ahb_clk_src = {
.c = {
.dbg_name = "ahb_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 40000000,
NOMINAL, 80800000),
CLK_INIT(ahb_clk_src.c),
@@ -277,6 +278,7 @@ static struct rcg_clk csi0_clk_src = {
.c = {
.dbg_name = "csi0_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 164571429, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi0_clk_src.c),
@@ -315,6 +317,7 @@ static struct rcg_clk vfe0_clk_src = {
.c = {
.dbg_name = "vfe0_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 200000000, LOW, 384000000,
NOMINAL, 576000000, HIGH, 600000000),
CLK_INIT(vfe0_clk_src.c),
@@ -330,6 +333,7 @@ static struct rcg_clk vfe1_clk_src = {
.c = {
.dbg_name = "vfe1_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 200000000, LOW, 384000000,
NOMINAL, 576000000, HIGH, 600000000),
CLK_INIT(vfe1_clk_src.c),
@@ -358,6 +362,7 @@ static struct rcg_clk mdp_clk_src = {
.c = {
.dbg_name = "mdp_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 171430000, LOW, 275000000,
NOMINAL, 330000000, HIGH, 412500000),
CLK_INIT(mdp_clk_src.c),
@@ -382,6 +387,7 @@ static struct rcg_clk maxi_clk_src = {
.c = {
.dbg_name = "maxi_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 75000000, LOW, 171428571,
NOMINAL, 323200000, HIGH, 406000000),
CLK_INIT(maxi_clk_src.c),
@@ -416,6 +422,7 @@ static struct rcg_clk cpp_clk_src = {
.c = {
.dbg_name = "cpp_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 100000000, LOW, 200000000,
NOMINAL, 576000000, HIGH, 600000000),
CLK_INIT(cpp_clk_src.c),
@@ -446,6 +453,7 @@ static struct rcg_clk jpeg0_clk_src = {
.c = {
.dbg_name = "jpeg0_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 75000000, LOW, 150000000,
NOMINAL, 480000000),
CLK_INIT(jpeg0_clk_src.c),
@@ -469,6 +477,7 @@ static struct rcg_clk rot_clk_src = {
.c = {
.dbg_name = "rot_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 171430000, LOW, 275000000,
NOMINAL, 330000000, HIGH, 412500000),
CLK_INIT(rot_clk_src.c),
@@ -501,6 +510,7 @@ static struct rcg_clk video_core_clk_src = {
.c = {
.dbg_name = "video_core_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 100000000, LOW, 186000000,
NOMINAL, 360000000, HIGH, 465000000),
CLK_INIT(video_core_clk_src.c),
@@ -531,6 +541,7 @@ static struct rcg_clk csiphy_clk_src = {
.c = {
.dbg_name = "csiphy_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 164570000, LOW, 256000000,
NOMINAL, 384000000),
CLK_INIT(csiphy_clk_src.c),
@@ -546,6 +557,7 @@ static struct rcg_clk csi1_clk_src = {
.c = {
.dbg_name = "csi1_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 164570000, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi1_clk_src.c),
@@ -561,6 +573,7 @@ static struct rcg_clk csi2_clk_src = {
.c = {
.dbg_name = "csi2_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 164570000, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi2_clk_src.c),
@@ -576,6 +589,7 @@ static struct rcg_clk csi3_clk_src = {
.c = {
.dbg_name = "csi3_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 164570000, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi3_clk_src.c),
@@ -607,6 +621,7 @@ static struct rcg_clk fd_core_clk_src = {
.c = {
.dbg_name = "fd_core_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 100000000, LOW, 200000000,
NOMINAL, 576000000),
CLK_INIT(fd_core_clk_src.c),
@@ -755,6 +770,7 @@ static struct rcg_clk video_subcore0_clk_src = {
.c = {
.dbg_name = "video_subcore0_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 100000000, LOW, 186000000,
NOMINAL, 360000000, HIGH, 465000000),
CLK_INIT(video_subcore0_clk_src.c),
@@ -771,6 +787,7 @@ static struct rcg_clk video_subcore1_clk_src = {
.c = {
.dbg_name = "video_subcore1_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP4(LOWER, 100000000, LOW, 186000000,
NOMINAL, 360000000, HIGH, 465000000),
CLK_INIT(video_subcore1_clk_src.c),
@@ -793,6 +810,7 @@ static struct rcg_clk cci_clk_src = {
.c = {
.dbg_name = "cci_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 37500000, LOW, 50000000,
NOMINAL, 100000000),
CLK_INIT(cci_clk_src.c),
@@ -818,6 +836,7 @@ static struct rcg_clk camss_gp0_clk_src = {
.c = {
.dbg_name = "camss_gp0_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
NOMINAL, 200000000),
CLK_INIT(camss_gp0_clk_src.c),
@@ -833,6 +852,7 @@ static struct rcg_clk camss_gp1_clk_src = {
.c = {
.dbg_name = "camss_gp1_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
NOMINAL, 200000000),
CLK_INIT(camss_gp1_clk_src.c),
@@ -862,6 +882,7 @@ static struct rcg_clk mclk0_clk_src = {
.c = {
.dbg_name = "mclk0_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 33333333, LOW, 66666667,
NOMINAL, 68571429),
CLK_INIT(mclk0_clk_src.c),
@@ -877,6 +898,7 @@ static struct rcg_clk mclk1_clk_src = {
.c = {
.dbg_name = "mclk1_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 33333333, LOW, 66666667,
NOMINAL, 68571429),
CLK_INIT(mclk1_clk_src.c),
@@ -892,6 +914,7 @@ static struct rcg_clk mclk2_clk_src = {
.c = {
.dbg_name = "mclk2_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 33333333, LOW, 66666667,
NOMINAL, 68571429),
CLK_INIT(mclk2_clk_src.c),
@@ -907,6 +930,7 @@ static struct rcg_clk mclk3_clk_src = {
.c = {
.dbg_name = "mclk3_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 33333333, LOW, 66666667,
NOMINAL, 68571429),
CLK_INIT(mclk3_clk_src.c),
@@ -928,6 +952,7 @@ static struct rcg_clk csi0phytimer_clk_src = {
.c = {
.dbg_name = "csi0phytimer_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 100000000, LOW, 200000000,
NOMINAL, 269333333),
CLK_INIT(csi0phytimer_clk_src.c),
@@ -943,6 +968,7 @@ static struct rcg_clk csi1phytimer_clk_src = {
.c = {
.dbg_name = "csi1phytimer_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 100000000, LOW, 200000000,
NOMINAL, 269333333),
CLK_INIT(csi1phytimer_clk_src.c),
@@ -958,6 +984,7 @@ static struct rcg_clk csi2phytimer_clk_src = {
.c = {
.dbg_name = "csi2phytimer_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 100000000, LOW, 200000000,
NOMINAL, 269333333),
CLK_INIT(csi2phytimer_clk_src.c),
@@ -978,6 +1005,7 @@ static struct rcg_clk dp_gtc_clk_src = {
.c = {
.dbg_name = "dp_gtc_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 40000000, LOW, 300000000),
CLK_INIT(dp_gtc_clk_src.c),
},
@@ -997,6 +1025,7 @@ static struct rcg_clk esc0_clk_src = {
.c = {
.dbg_name = "esc0_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 19200000, NOMINAL, 19200000),
CLK_INIT(esc0_clk_src.c),
},
@@ -1011,6 +1040,7 @@ static struct rcg_clk esc1_clk_src = {
.c = {
.dbg_name = "esc1_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 19200000, NOMINAL, 19200000),
CLK_INIT(esc1_clk_src.c),
},
@@ -1033,6 +1063,7 @@ static struct rcg_clk extpclk_clk_src = {
.dbg_name = "extpclk_clk_src",
.parent = &ext_extpclk_clk_src.c,
.ops = &clk_ops_byte,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 150000000, LOW, 300000000,
NOMINAL, 600000000),
CLK_INIT(extpclk_clk_src.c),
@@ -1053,6 +1084,7 @@ static struct rcg_clk hdmi_clk_src = {
.c = {
.dbg_name = "hdmi_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 19200000, NOMINAL, 19200000),
CLK_INIT(hdmi_clk_src.c),
},
@@ -1072,6 +1104,7 @@ static struct rcg_clk vsync_clk_src = {
.c = {
.dbg_name = "vsync_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 19200000, NOMINAL, 19200000),
CLK_INIT(vsync_clk_src.c),
},
@@ -1091,6 +1124,7 @@ static struct rcg_clk dp_aux_clk_src = {
.c = {
.dbg_name = "dp_aux_clk_src",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP2(LOWER, 19200000, NOMINAL, 19200000),
CLK_INIT(dp_aux_clk_src.c),
},
@@ -1165,6 +1199,7 @@ static struct rcg_clk dp_crypto_clk_src = {
.c = {
.dbg_name = "dp_crypto_clk_src",
.ops = &clk_ops_rcg_mnd,
+ .flags = CLKFLAG_NO_RATE_CACHE,
VDD_DIG_FMAX_MAP3(LOWER, 101250, LOW, 168750,
NOMINAL, 337500),
CLK_INIT(dp_crypto_clk_src.c),
@@ -1237,6 +1272,7 @@ static struct branch_clk mmss_camss_cci_clk = {
.c = {
.dbg_name = "mmss_camss_cci_clk",
.parent = &cci_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_cci_clk.c),
},
@@ -1260,6 +1296,7 @@ static struct branch_clk mmss_camss_cpp_clk = {
.c = {
.dbg_name = "mmss_camss_cpp_clk",
.parent = &cpp_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_cpp_clk.c),
},
@@ -1317,6 +1354,7 @@ static struct branch_clk mmss_camss_csi0_clk = {
.c = {
.dbg_name = "mmss_camss_csi0_clk",
.parent = &csi0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi0_clk.c),
},
@@ -1376,6 +1414,7 @@ static struct branch_clk mmss_camss_csi1_clk = {
.c = {
.dbg_name = "mmss_camss_csi1_clk",
.parent = &csi1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi1_clk.c),
},
@@ -1435,6 +1474,7 @@ static struct branch_clk mmss_camss_csi2_clk = {
.c = {
.dbg_name = "mmss_camss_csi2_clk",
.parent = &csi2_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi2_clk.c),
},
@@ -1494,6 +1534,7 @@ static struct branch_clk mmss_camss_csi3_clk = {
.c = {
.dbg_name = "mmss_camss_csi3_clk",
.parent = &csi3_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi3_clk.c),
},
@@ -1555,6 +1596,7 @@ static struct branch_clk mmss_camss_csiphy0_clk = {
.c = {
.dbg_name = "mmss_camss_csiphy0_clk",
.parent = &csiphy_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csiphy0_clk.c),
},
@@ -1568,6 +1610,7 @@ static struct branch_clk mmss_camss_csiphy1_clk = {
.c = {
.dbg_name = "mmss_camss_csiphy1_clk",
.parent = &csiphy_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csiphy1_clk.c),
},
@@ -1581,6 +1624,7 @@ static struct branch_clk mmss_camss_csiphy2_clk = {
.c = {
.dbg_name = "mmss_camss_csiphy2_clk",
.parent = &csiphy_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csiphy2_clk.c),
},
@@ -1604,6 +1648,7 @@ static struct branch_clk mmss_fd_core_clk = {
.c = {
.dbg_name = "mmss_fd_core_clk",
.parent = &fd_core_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_fd_core_clk.c),
},
@@ -1628,6 +1673,7 @@ static struct branch_clk mmss_camss_gp0_clk = {
.c = {
.dbg_name = "mmss_camss_gp0_clk",
.parent = &camss_gp0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_gp0_clk.c),
},
@@ -1640,6 +1686,7 @@ static struct branch_clk mmss_camss_gp1_clk = {
.c = {
.dbg_name = "mmss_camss_gp1_clk",
.parent = &camss_gp1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_gp1_clk.c),
},
@@ -1663,6 +1710,7 @@ static struct branch_clk mmss_camss_jpeg0_clk = {
.c = {
.dbg_name = "mmss_camss_jpeg0_clk",
.parent = &jpeg0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_jpeg0_clk.c),
},
@@ -1701,6 +1749,7 @@ static struct branch_clk mmss_camss_mclk0_clk = {
.c = {
.dbg_name = "mmss_camss_mclk0_clk",
.parent = &mclk0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_mclk0_clk.c),
},
@@ -1713,6 +1762,7 @@ static struct branch_clk mmss_camss_mclk1_clk = {
.c = {
.dbg_name = "mmss_camss_mclk1_clk",
.parent = &mclk1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_mclk1_clk.c),
},
@@ -1725,6 +1775,7 @@ static struct branch_clk mmss_camss_mclk2_clk = {
.c = {
.dbg_name = "mmss_camss_mclk2_clk",
.parent = &mclk2_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_mclk2_clk.c),
},
@@ -1737,6 +1788,7 @@ static struct branch_clk mmss_camss_mclk3_clk = {
.c = {
.dbg_name = "mmss_camss_mclk3_clk",
.parent = &mclk3_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_mclk3_clk.c),
},
@@ -1760,6 +1812,7 @@ static struct branch_clk mmss_camss_csi0phytimer_clk = {
.c = {
.dbg_name = "mmss_camss_csi0phytimer_clk",
.parent = &csi0phytimer_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi0phytimer_clk.c),
},
@@ -1772,6 +1825,7 @@ static struct branch_clk mmss_camss_csi1phytimer_clk = {
.c = {
.dbg_name = "mmss_camss_csi1phytimer_clk",
.parent = &csi1phytimer_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi1phytimer_clk.c),
},
@@ -1784,6 +1838,7 @@ static struct branch_clk mmss_camss_csi2phytimer_clk = {
.c = {
.dbg_name = "mmss_camss_csi2phytimer_clk",
.parent = &csi2phytimer_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_csi2phytimer_clk.c),
},
@@ -1818,6 +1873,7 @@ static struct branch_clk mmss_camss_vfe0_clk = {
.c = {
.dbg_name = "mmss_camss_vfe0_clk",
.parent = &vfe0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_vfe0_clk.c),
},
@@ -1853,6 +1909,7 @@ static struct branch_clk mmss_camss_vfe1_clk = {
.c = {
.dbg_name = "mmss_camss_vfe1_clk",
.parent = &vfe1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_camss_vfe1_clk.c),
},
@@ -1921,6 +1978,7 @@ static struct branch_clk mmss_mdss_byte0_clk = {
.c = {
.dbg_name = "mmss_mdss_byte0_clk",
.parent = &byte0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_byte0_clk.c),
},
@@ -1956,6 +2014,7 @@ static struct branch_clk mmss_mdss_byte0_intf_clk = {
.c = {
.dbg_name = "mmss_mdss_byte0_intf_clk",
.parent = &mmss_mdss_byte0_intf_div_clk.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_byte0_intf_clk.c),
},
@@ -1968,6 +2027,7 @@ static struct branch_clk mmss_mdss_byte1_clk = {
.c = {
.dbg_name = "mmss_mdss_byte1_clk",
.parent = &byte1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_byte1_clk.c),
},
@@ -2003,6 +2063,7 @@ static struct branch_clk mmss_mdss_byte1_intf_clk = {
.c = {
.dbg_name = "mmss_mdss_byte1_intf_clk",
.parent = &mmss_mdss_byte1_intf_div_clk.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_byte1_intf_clk.c),
},
@@ -2015,6 +2076,7 @@ static struct branch_clk mmss_mdss_dp_aux_clk = {
.c = {
.dbg_name = "mmss_mdss_dp_aux_clk",
.parent = &dp_aux_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_dp_aux_clk.c),
},
@@ -2066,6 +2128,7 @@ static struct branch_clk mmss_mdss_dp_crypto_clk = {
.c = {
.dbg_name = "mmss_mdss_dp_crypto_clk",
.parent = &dp_crypto_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_dp_crypto_clk.c),
},
@@ -2078,6 +2141,7 @@ static struct branch_clk mmss_mdss_dp_gtc_clk = {
.c = {
.dbg_name = "mmss_mdss_dp_gtc_clk",
.parent = &dp_gtc_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_dp_gtc_clk.c),
},
@@ -2090,6 +2154,7 @@ static struct branch_clk mmss_mdss_esc0_clk = {
.c = {
.dbg_name = "mmss_mdss_esc0_clk",
.parent = &esc0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_esc0_clk.c),
},
@@ -2102,6 +2167,7 @@ static struct branch_clk mmss_mdss_esc1_clk = {
.c = {
.dbg_name = "mmss_mdss_esc1_clk",
.parent = &esc1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_esc1_clk.c),
},
@@ -2114,6 +2180,7 @@ static struct branch_clk mmss_mdss_extpclk_clk = {
.c = {
.dbg_name = "mmss_mdss_extpclk_clk",
.parent = &extpclk_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_extpclk_clk.c),
},
@@ -2126,6 +2193,7 @@ static struct branch_clk mmss_mdss_hdmi_clk = {
.c = {
.dbg_name = "mmss_mdss_hdmi_clk",
.parent = &hdmi_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_hdmi_clk.c),
},
@@ -2149,6 +2217,7 @@ static struct branch_clk mmss_mdss_mdp_clk = {
.c = {
.dbg_name = "mmss_mdss_mdp_clk",
.parent = &mdp_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_mdp_clk.c),
},
@@ -2175,6 +2244,7 @@ static struct branch_clk mmss_mdss_pclk0_clk = {
.c = {
.dbg_name = "mmss_mdss_pclk0_clk",
.parent = &pclk0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_pclk0_clk.c),
},
@@ -2187,6 +2257,7 @@ static struct branch_clk mmss_mdss_pclk1_clk = {
.c = {
.dbg_name = "mmss_mdss_pclk1_clk",
.parent = &pclk1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_pclk1_clk.c),
},
@@ -2199,6 +2270,7 @@ static struct branch_clk mmss_mdss_rot_clk = {
.c = {
.dbg_name = "mmss_mdss_rot_clk",
.parent = &rot_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_rot_clk.c),
},
@@ -2211,6 +2283,7 @@ static struct branch_clk mmss_mdss_vsync_clk = {
.c = {
.dbg_name = "mmss_mdss_vsync_clk",
.parent = &vsync_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mdss_vsync_clk.c),
},
@@ -2225,6 +2298,7 @@ static struct branch_clk mmss_mnoc_ahb_clk = {
.c = {
.dbg_name = "mmss_mnoc_ahb_clk",
.parent = &ahb_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mnoc_ahb_clk.c),
},
@@ -2260,6 +2334,7 @@ static struct branch_clk mmss_mnoc_maxi_clk = {
.c = {
.dbg_name = "mmss_mnoc_maxi_clk",
.parent = &maxi_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_mnoc_maxi_clk.c),
},
@@ -2272,6 +2347,7 @@ static struct branch_clk mmss_video_subcore0_clk = {
.c = {
.dbg_name = "mmss_video_subcore0_clk",
.parent = &video_subcore0_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_video_subcore0_clk.c),
},
@@ -2284,6 +2360,7 @@ static struct branch_clk mmss_video_subcore1_clk = {
.c = {
.dbg_name = "mmss_video_subcore1_clk",
.parent = &video_subcore1_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_video_subcore1_clk.c),
},
@@ -2318,6 +2395,7 @@ static struct branch_clk mmss_video_core_clk = {
.c = {
.dbg_name = "mmss_video_core_clk",
.parent = &video_core_clk_src.c,
+ .flags = CLKFLAG_NO_RATE_CACHE,
.ops = &clk_ops_branch,
CLK_INIT(mmss_video_core_clk.c),
},
@@ -2822,6 +2900,9 @@ int msm_mmsscc_cobalt_probe(struct platform_device *pdev)
ext_dp_phy_pll_vco.clk_id = "dp_vco_div";
ext_dp_phy_pll_vco.c.flags = CLKFLAG_NO_RATE_CACHE;
+ mmss_camss_jpeg0_vote_clk.c.flags = CLKFLAG_NO_RATE_CACHE;
+ mmss_camss_jpeg0_dma_vote_clk.c.flags = CLKFLAG_NO_RATE_CACHE;
+
is_vq = of_device_is_compatible(pdev->dev.of_node,
"qcom,mmsscc-hamster");
if (is_vq)
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 085b9acfb9d5..f685e7fe3a4d 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -117,6 +117,11 @@ static int wait_for_pll_latch_ack(struct clk_alpha_pll *pll, u32 mask)
return wait_for_pll(pll, mask, 0, "latch_ack");
}
+static int wait_for_pll_update(struct clk_alpha_pll *pll, u32 mask)
+{
+ return wait_for_pll(pll, mask, 1, "update");
+}
+
/* alpha pll with hwfsm support */
#define PLL_OFFLINE_REQ BIT(7)
@@ -562,12 +567,48 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
return clamp(rate, min_freq, max_freq);
}
+static void clk_alpha_pll_list_registers(struct seq_file *f, struct clk_hw *hw)
+{
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ int size, i, val;
+
+ static struct clk_register_data data[] = {
+ {"PLL_MODE", 0x0},
+ {"PLL_L_VAL", 0x4},
+ {"PLL_ALPHA_VAL", 0x8},
+ {"PLL_ALPHA_VAL_U", 0xC},
+ {"PLL_USER_CTL", 0x10},
+ {"PLL_CONFIG_CTL", 0x18},
+ };
+
+ static struct clk_register_data data1[] = {
+ {"APSS_PLL_VOTE", 0x0},
+ };
+
+ size = ARRAY_SIZE(data);
+
+ for (i = 0; i < size; i++) {
+ regmap_read(pll->clkr.regmap, pll->offset + data[i].offset,
+ &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
+ }
+
+ regmap_read(pll->clkr.regmap, pll->offset + data[0].offset, &val);
+
+ if (val & PLL_FSM_ENA) {
+ regmap_read(pll->clkr.regmap, pll->clkr.enable_reg +
+ data1[0].offset, &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data1[0].name, val);
+ }
+}
+
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
.recalc_rate = clk_alpha_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
.set_rate = clk_alpha_pll_set_rate,
+ .list_registers = clk_alpha_pll_list_registers,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
@@ -577,6 +618,7 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = {
.recalc_rate = clk_alpha_pll_recalc_rate,
.round_rate = clk_alpha_pll_round_rate,
.set_rate = clk_alpha_pll_set_rate,
+ .list_registers = clk_alpha_pll_list_registers,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
@@ -633,3 +675,177 @@ const struct clk_ops clk_alpha_pll_postdiv_ops = {
.set_rate = clk_alpha_pll_postdiv_set_rate,
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);
+
+static int clk_alpha_pll_slew_update(struct clk_alpha_pll *pll)
+{
+ int ret = 0;
+ u32 val;
+
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_MODE,
+ PLL_UPDATE, PLL_UPDATE);
+ regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &val);
+
+ ret = wait_for_pll_update(pll, PLL_UPDATE);
+ if (ret)
+ return ret;
+ /*
+ * HPG mandates a wait of at least 570ns before polling the LOCK
+ * detect bit. Have a delay of 1us just to be safe.
+ */
+ mb();
+ udelay(1);
+
+ ret = wait_for_pll_enable(pll, PLL_LOCK_DET);
+
+ return ret;
+}
+
+static int clk_alpha_pll_slew_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ unsigned long freq_hz;
+ const struct pll_vco *curr_vco, *vco;
+ u32 l;
+ u64 a;
+
+ freq_hz = alpha_pll_round_rate(rate, parent_rate, &l, &a);
+ if (freq_hz != rate) {
+ pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ curr_vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+ if (!curr_vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ vco = alpha_pll_find_vco(pll, freq_hz);
+ if (!vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Dynamic pll update will not support switching frequencies across
+ * vco ranges. In those cases fall back to normal alpha set rate.
+ */
+ if (curr_vco->val != vco->val)
+ return clk_alpha_pll_set_rate(hw, rate, parent_rate);
+
+ a = a << (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_L_VAL, l);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL, a);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL_U, a >> 32);
+
+ /* Ensure that the write above goes through before proceeding. */
+ mb();
+
+ if (clk_hw_is_enabled(hw))
+ clk_alpha_pll_slew_update(pll);
+
+ return 0;
+}
+
+/*
+ * Slewing plls should be bought up at frequency which is in the middle of the
+ * desired VCO range. So after bringing up the pll at calibration freq, set it
+ * back to desired frequency(that was set by previous clk_set_rate).
+ */
+static int clk_alpha_pll_calibrate(struct clk_hw *hw)
+{
+ unsigned long calibration_freq, freq_hz;
+ struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+ const struct pll_vco *vco;
+ u64 a;
+ u32 l;
+ int rc;
+
+ vco = alpha_pll_find_vco(pll, clk_hw_get_rate(hw));
+ if (!vco) {
+ pr_err("alpha pll: not in a valid vco range\n");
+ return -EINVAL;
+ }
+
+ /*
+ * As during slewing plls vco_sel won't be allowed to change, vco table
+ * should have only one entry table, i.e. index = 0, find the
+ * calibration frequency.
+ */
+ calibration_freq = (pll->vco_table[0].min_freq +
+ pll->vco_table[0].max_freq)/2;
+
+ freq_hz = alpha_pll_round_rate(calibration_freq,
+ clk_hw_get_rate(clk_hw_get_parent(hw)), &l, &a);
+ if (freq_hz != calibration_freq) {
+ pr_err("alpha_pll: call clk_set_rate with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ /* Setup PLL for calibration frequency */
+ a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_L_VAL, l);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL, a);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL_U, a >> 32);
+
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
+ PLL_VCO_MASK << PLL_VCO_SHIFT,
+ vco->val << PLL_VCO_SHIFT);
+
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
+ PLL_ALPHA_EN, PLL_ALPHA_EN);
+
+ /* Bringup the pll at calibration frequency */
+ rc = clk_alpha_pll_enable(hw);
+ if (rc) {
+ pr_err("alpha pll calibration failed\n");
+ return rc;
+ }
+
+ /*
+ * PLL is already running at calibration frequency.
+ * So slew pll to the previously set frequency.
+ */
+ freq_hz = alpha_pll_round_rate(clk_hw_get_rate(hw),
+ clk_hw_get_rate(clk_hw_get_parent(hw)), &l, &a);
+
+ pr_debug("pll %s: setting back to required rate %lu, freq_hz %ld\n",
+ hw->init->name, clk_hw_get_rate(hw), freq_hz);
+
+ /* Setup the PLL for the new frequency */
+ a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_L_VAL, l);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL, a);
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_ALPHA_VAL_U, a >> 32);
+
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
+ PLL_ALPHA_EN, PLL_ALPHA_EN);
+
+ return clk_alpha_pll_slew_update(pll);
+}
+
+static int clk_alpha_pll_slew_enable(struct clk_hw *hw)
+{
+ int rc;
+
+ rc = clk_alpha_pll_calibrate(hw);
+ if (rc)
+ return rc;
+
+ rc = clk_alpha_pll_enable(hw);
+
+ return rc;
+}
+
+const struct clk_ops clk_alpha_pll_slew_ops = {
+ .enable = clk_alpha_pll_slew_enable,
+ .disable = clk_alpha_pll_disable,
+ .recalc_rate = clk_alpha_pll_recalc_rate,
+ .round_rate = clk_alpha_pll_round_rate,
+ .set_rate = clk_alpha_pll_slew_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_slew_ops);
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 9b1d3ee61cac..dd92bc340f8a 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -80,6 +80,7 @@ struct clk_alpha_pll_postdiv {
extern const struct clk_ops clk_alpha_pll_ops;
extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
extern const struct clk_ops clk_alpha_pll_postdiv_ops;
+extern const struct clk_ops clk_alpha_pll_slew_ops;
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct pll_config *config);
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
index 8aea1d519311..6a975052cc85 100644
--- a/drivers/clk/qcom/clk-branch.c
+++ b/drivers/clk/qcom/clk-branch.c
@@ -16,10 +16,12 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/export.h>
+#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "clk-branch.h"
+#include "clk-regmap.h"
static bool clk_branch_in_hwcg_mode(const struct clk_branch *br)
{
@@ -181,6 +183,43 @@ const struct clk_ops clk_branch_ops = {
};
EXPORT_SYMBOL_GPL(clk_branch_ops);
+static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw)
+{
+ struct clk_branch *br = to_clk_branch(hw);
+ struct clk_regmap *rclk = to_clk_regmap(hw);
+ int size, i, val;
+
+ static struct clk_register_data data[] = {
+ {"CBCR", 0x0},
+ };
+
+ static struct clk_register_data data1[] = {
+ {"APSS_VOTE", 0x0},
+ {"APSS_SLEEP_VOTE", 0x4},
+ };
+
+ size = ARRAY_SIZE(data);
+
+ for (i = 0; i < size; i++) {
+ regmap_read(br->clkr.regmap, br->halt_reg + data[i].offset,
+ &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
+ }
+
+ if ((br->halt_check & BRANCH_HALT_VOTED) &&
+ !(br->halt_check & BRANCH_VOTED)) {
+ if (rclk->enable_reg) {
+ size = ARRAY_SIZE(data1);
+ for (i = 0; i < size; i++) {
+ regmap_read(br->clkr.regmap, rclk->enable_reg +
+ data1[i].offset, &val);
+ seq_printf(f, "%20s: 0x%.8x\n",
+ data1[i].name, val);
+ }
+ }
+ }
+}
+
static int clk_branch2_enable(struct clk_hw *hw)
{
return clk_branch_toggle(hw, true, clk_branch2_check_halt);
@@ -196,6 +235,7 @@ const struct clk_ops clk_branch2_ops = {
.disable = clk_branch2_disable,
.is_enabled = clk_is_enabled_regmap,
.set_flags = clk_branch_set_flags,
+ .list_registers = clk_branch2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_branch2_ops);
@@ -228,10 +268,29 @@ static void clk_gate2_disable(struct clk_hw *hw)
clk_gate_toggle(hw, false);
}
+static void clk_gate2_list_registers(struct seq_file *f, struct clk_hw *hw)
+{
+ struct clk_gate2 *gt = to_clk_gate2(hw);
+ int size, i, val;
+
+ static struct clk_register_data data[] = {
+ {"EN_REG", 0x0},
+ };
+
+ size = ARRAY_SIZE(data);
+
+ for (i = 0; i < size; i++) {
+ regmap_read(gt->clkr.regmap, gt->clkr.enable_reg +
+ data[i].offset, &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
+ }
+}
+
const struct clk_ops clk_gate2_ops = {
.enable = clk_gate2_enable,
.disable = clk_gate2_disable,
.is_enabled = clk_is_enabled_regmap,
+ .list_registers = clk_gate2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_gate2_ops);
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
index da02ab499bff..4589a3b6cec6 100644
--- a/drivers/clk/qcom/clk-rcg.h
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -24,6 +24,7 @@ struct freq_tbl {
u16 m;
u16 n;
unsigned long src_freq;
+#define FIXED_FREQ_SRC 0
};
/**
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index 6d12ddb3e245..48ff5ea00040 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -232,9 +232,10 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw,
const struct freq_tbl *f, struct clk_rate_request *req)
{
unsigned long clk_flags, rate = req->rate;
+ struct clk_rate_request parent_req = { };
struct clk_hw *p;
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- int index;
+ int index, ret = 0;
f = qcom_find_freq(f, rate);
if (!f)
@@ -265,6 +266,21 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw,
req->best_parent_rate = rate;
req->rate = f->freq;
+ if (f->src_freq != FIXED_FREQ_SRC) {
+ rate = parent_req.rate = f->src_freq;
+ parent_req.best_parent_hw = p;
+ ret = __clk_determine_rate(p, &parent_req);
+ if (ret)
+ return ret;
+
+ ret = clk_set_rate(p->clk, parent_req.rate);
+ if (ret) {
+ pr_err("Failed set rate(%lu) on parent for non-fixed source\n",
+ parent_req.rate);
+ return ret;
+ }
+ }
+
return 0;
}
@@ -317,6 +333,53 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
return update_config(rcg);
}
+static void clk_rcg2_list_registers(struct seq_file *f, struct clk_hw *hw)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ int i = 0, size = 0, val;
+
+ static struct clk_register_data data[] = {
+ {"CMD_RCGR", 0x0},
+ {"CFG_RCGR", 0x4},
+ };
+
+ static struct clk_register_data data1[] = {
+ {"CMD_RCGR", 0x0},
+ {"CFG_RCGR", 0x4},
+ {"M_VAL", 0x8},
+ {"N_VAL", 0xC},
+ {"D_VAL", 0x10},
+ };
+
+ if (rcg->mnd_width) {
+ size = ARRAY_SIZE(data1);
+ for (i = 0; i < size; i++) {
+ regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr +
+ data1[i].offset), &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data1[i].name, val);
+ }
+ } else {
+ size = ARRAY_SIZE(data);
+ for (i = 0; i < size; i++) {
+ regmap_read(rcg->clkr.regmap, (rcg->cmd_rcgr +
+ data[i].offset), &val);
+ seq_printf(f, "%20s: 0x%.8x\n", data[i].name, val);
+ }
+ }
+}
+
+/* Return the nth supported frequency for a given clock. */
+static long clk_rcg2_list_rate(struct clk_hw *hw, unsigned n,
+ unsigned long fmax)
+{
+ struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+ if (!rcg->freq_tbl)
+ return -ENXIO;
+
+ return (rcg->freq_tbl + n)->freq;
+}
+
static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -351,6 +414,8 @@ const struct clk_ops clk_rcg2_ops = {
.determine_rate = clk_rcg2_determine_rate,
.set_rate = clk_rcg2_set_rate,
.set_rate_and_parent = clk_rcg2_set_rate_and_parent,
+ .list_rate = clk_rcg2_list_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
@@ -557,6 +622,7 @@ const struct clk_ops clk_edp_pixel_ops = {
.set_rate = clk_edp_pixel_set_rate,
.set_rate_and_parent = clk_edp_pixel_set_rate_and_parent,
.determine_rate = clk_edp_pixel_determine_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
@@ -615,6 +681,7 @@ const struct clk_ops clk_byte_ops = {
.set_rate = clk_byte_set_rate,
.set_rate_and_parent = clk_byte_set_rate_and_parent,
.determine_rate = clk_byte_determine_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_byte_ops);
@@ -685,6 +752,7 @@ const struct clk_ops clk_byte2_ops = {
.set_rate = clk_byte2_set_rate,
.set_rate_and_parent = clk_byte2_set_rate_and_parent,
.determine_rate = clk_byte2_determine_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_byte2_ops);
@@ -775,6 +843,7 @@ const struct clk_ops clk_pixel_ops = {
.set_rate = clk_pixel_set_rate,
.set_rate_and_parent = clk_pixel_set_rate_and_parent,
.determine_rate = clk_pixel_determine_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_pixel_ops);
@@ -864,6 +933,7 @@ const struct clk_ops clk_gfx3d_ops = {
.set_rate = clk_gfx3d_set_rate,
.set_rate_and_parent = clk_gfx3d_set_rate_and_parent,
.determine_rate = clk_gfx3d_determine_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_gfx3d_ops);
@@ -944,5 +1014,7 @@ const struct clk_ops clk_gfx3d_src_ops = {
.set_rate = clk_gfx3d_set_rate,
.set_rate_and_parent = clk_gfx3d_src_set_rate_and_parent,
.determine_rate = clk_gfx3d_src_determine_rate,
+ .list_rate = clk_rcg2_list_rate,
+ .list_registers = clk_rcg2_list_registers,
};
EXPORT_SYMBOL_GPL(clk_gfx3d_src_ops);
diff --git a/drivers/clk/qcom/clk-regmap.h b/drivers/clk/qcom/clk-regmap.h
index 491a63d537df..8663dea02d79 100644
--- a/drivers/clk/qcom/clk-regmap.h
+++ b/drivers/clk/qcom/clk-regmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -15,6 +15,7 @@
#define __QCOM_CLK_REGMAP_H__
#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
struct regmap;
@@ -42,4 +43,9 @@ void clk_disable_regmap(struct clk_hw *hw);
struct clk *
devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk);
+struct clk_register_data {
+ char *name;
+ u32 offset;
+};
+
#endif
diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h
index 436b6949c414..ef2861ca96dd 100644
--- a/drivers/gpu/msm/a5xx_reg.h
+++ b/drivers/gpu/msm/a5xx_reg.h
@@ -893,6 +893,11 @@
#define A5XX_GDPM_INT_MASK 0xB811
#define A5XX_GPMU_BEC_ENABLE 0xB9A0
+/* ISENSE registers */
+#define A5XX_GPU_CS_DECIMAL_ALIGN 0xC16A
+#define A5XX_GPU_CS_SENSOR_PARAM_CORE_1 0xC126
+#define A5XX_GPU_CS_SENSOR_PARAM_CORE_2 0xC127
+#define A5XX_GPU_CS_SW_OV_FUSE_EN 0xC168
#define A5XX_GPU_CS_SENSOR_GENERAL_STATUS 0xC41A
#define A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_0 0xC41D
#define A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_2 0xC41F
@@ -900,5 +905,6 @@
#define A5XX_GPU_CS_ENABLE_REG 0xC520
#define A5XX_GPU_CS_AMP_CALIBRATION_CONTROL1 0xC557
#define A5XX_GPU_CS_AMP_CALIBRATION_DONE 0xC565
+#define A5XX_GPU_CS_ENDPOINT_CALIBRATION_DONE 0xC556
#endif /* _A5XX_REG_H */
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index f652e955b07c..dc35c0080d11 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -254,7 +254,7 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev)
return ret;
ret = kgsl_allocate_user(&adreno_dev->dev, &crit_pkts_refbuf0,
- NULL, PAGE_SIZE, KGSL_MEMFLAGS_SECURE);
+ PAGE_SIZE, KGSL_MEMFLAGS_SECURE);
if (ret)
return ret;
@@ -431,6 +431,43 @@ static int _poll_gdsc_status(struct adreno_device *adreno_dev,
return 0;
}
+static void a5xx_restore_isense_regs(struct adreno_device *adreno_dev)
+{
+ struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
+ unsigned int reg, i, ramp = GPMU_ISENSE_SAVE;
+ static unsigned int isense_regs[6] = {0xFFFF}, isense_reg_addr[] = {
+ A5XX_GPU_CS_DECIMAL_ALIGN,
+ A5XX_GPU_CS_SENSOR_PARAM_CORE_1,
+ A5XX_GPU_CS_SENSOR_PARAM_CORE_2,
+ A5XX_GPU_CS_SW_OV_FUSE_EN,
+ A5XX_GPU_CS_ENDPOINT_CALIBRATION_DONE,
+ A5XX_GPMU_TEMP_SENSOR_CONFIG};
+
+ if (!adreno_is_a540(adreno_dev))
+ return;
+
+ /* read signature */
+ kgsl_regread(device, ramp++, &reg);
+
+ if (reg == 0xBABEFACE) {
+ /* store memory locations in buffer */
+ for (i = 0; i < ARRAY_SIZE(isense_regs); i++)
+ kgsl_regread(device, ramp + i, isense_regs + i);
+
+ /* clear signature */
+ kgsl_regwrite(device, GPMU_ISENSE_SAVE, 0x0);
+ }
+
+ /* if we never stored memory locations - do nothing */
+ if (isense_regs[0] == 0xFFFF)
+ return;
+
+ /* restore registers from memory */
+ for (i = 0; i < ARRAY_SIZE(isense_reg_addr); i++)
+ kgsl_regwrite(device, isense_reg_addr[i], isense_regs[i]);
+
+}
+
/*
* a5xx_regulator_enable() - Enable any necessary HW regulators
* @adreno_dev: The adreno device pointer
@@ -480,6 +517,7 @@ static int a5xx_regulator_enable(struct adreno_device *adreno_dev)
kgsl_regrmw(device, A5XX_GPMU_GPMU_SP_CLOCK_CONTROL,
CNTL_IP_CLK_ENABLE, 1);
+ a5xx_restore_isense_regs(adreno_dev);
return 0;
}
diff --git a/drivers/gpu/msm/adreno_a5xx.h b/drivers/gpu/msm/adreno_a5xx.h
index e424e7a9f228..08fd16a83f30 100644
--- a/drivers/gpu/msm/adreno_a5xx.h
+++ b/drivers/gpu/msm/adreno_a5xx.h
@@ -228,6 +228,7 @@ void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
#define LM_SEQUENCE_ID 1
#define MAX_SEQUENCE_ID 3
+#define GPMU_ISENSE_SAVE (A5XX_GPMU_DATA_RAM_BASE + 200/4)
/* LM defaults */
#define LM_DEFAULT_LIMIT 6000
#define A530_DEFAULT_LEAKAGE 0x004E001A
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 554eb2dffae4..699d99651f2c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -176,9 +176,10 @@ int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr,
return 0;
}
-static void kgsl_memfree_purge(pid_t ptname, uint64_t gpuaddr,
- uint64_t size)
+static void kgsl_memfree_purge(struct kgsl_pagetable *pagetable,
+ uint64_t gpuaddr, uint64_t size)
{
+ pid_t ptname = pagetable ? pagetable->name : 0;
int i;
if (memfree.list == NULL)
@@ -342,60 +343,24 @@ kgsl_mem_entry_destroy(struct kref *kref)
}
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
-/**
- * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
- * assign it with a gpu address space before insertion
- * @process: the process that owns the memory
- * @entry: the memory entry
- *
- * @returns - 0 on succcess else error code
- *
- * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address.
- * The assignment of gpu address and insertion into list needs to
- * happen with the memory lock held to avoid race conditions between
- * gpu address being selected and some other thread looking through the
- * rb list in search of memory based on gpuaddr
- * This function should be called with processes memory spinlock held
- */
-static int
-kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process,
- struct kgsl_mem_entry *entry)
+/* Allocate a IOVA for memory objects that don't use SVM */
+static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device,
+ struct kgsl_process_private *process,
+ struct kgsl_mem_entry *entry)
{
- struct kgsl_pagetable *pagetable = process->pagetable;
+ struct kgsl_pagetable *pagetable;
/*
- * If cpu=gpu map is used then caller needs to set the
- * gpu address
+ * If SVM is enabled for this object then the address needs to be
+ * assigned elsewhere
*/
- if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
- if (!entry->memdesc.gpuaddr)
- return 0;
- } else if (entry->memdesc.gpuaddr) {
- WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
- return -EINVAL;
- }
- if (kgsl_memdesc_is_secured(&entry->memdesc))
- pagetable = pagetable->mmu->securepagetable;
-
- return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
-}
+ if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
+ return 0;
-/**
- * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked
- * process - Pointer to process private to which memory belongs
- * entry - Memory entry to untrack
- *
- * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be
- * called with processes spin lock held
- */
-static void
-kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process,
- struct kgsl_mem_entry *entry)
-{
- struct kgsl_pagetable *pagetable = entry->memdesc.pagetable;
+ pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ?
+ device->mmu.securepagetable : process->pagetable;
- if (entry->memdesc.gpuaddr)
- kgsl_mmu_put_gpuaddr(pagetable, &entry->memdesc);
+ return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
}
/* Commit the entry to the process so it can be accessed by other operations */
@@ -409,33 +374,25 @@ static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry)
spin_unlock(&entry->priv->mem_lock);
}
-/**
- * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process
- * @entry: the memory entry
- * @process: the owner process
- *
- * Attach a newly created mem_entry to its owner process so that
- * it can be found later. The mem_entry will be added to mem_idr and have
- * its 'id' field assigned.
- *
- * @returns - 0 on success or error code on failure.
+/*
+ * Attach the memory object to a process by (possibly) getting a GPU address and
+ * (possibly) mapping it
*/
-int
-kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
- struct kgsl_device_private *dev_priv)
+static int kgsl_mem_entry_attach_process(struct kgsl_device *device,
+ struct kgsl_process_private *process,
+ struct kgsl_mem_entry *entry)
{
- int id;
- int ret;
- struct kgsl_process_private *process = dev_priv->process_priv;
- struct kgsl_pagetable *pagetable = NULL;
+ int id, ret;
ret = kgsl_process_private_get(process);
if (!ret)
return -EBADF;
- ret = kgsl_mem_entry_track_gpuaddr(process, entry);
- if (ret)
- goto err_put_proc_priv;
+ ret = kgsl_mem_entry_track_gpuaddr(device, process, entry);
+ if (ret) {
+ kgsl_process_private_put(process);
+ return ret;
+ }
idr_preload(GFP_KERNEL);
spin_lock(&process->mem_lock);
@@ -445,47 +402,44 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
idr_preload_end();
if (id < 0) {
- ret = id;
- kgsl_mem_entry_untrack_gpuaddr(process, entry);
- goto err_put_proc_priv;
+ if (!kgsl_memdesc_use_cpu_map(&entry->memdesc))
+ kgsl_mmu_put_gpuaddr(&entry->memdesc);
+ kgsl_process_private_put(process);
+ return id;
}
entry->id = id;
entry->priv = process;
- /* map the memory after unlocking if gpuaddr has been assigned */
+ /*
+ * Map the memory if a GPU address is already assigned, either through
+ * kgsl_mem_entry_track_gpuaddr() or via some other SVM process
+ */
if (entry->memdesc.gpuaddr) {
- pagetable = process->pagetable;
- if (kgsl_memdesc_is_secured(&entry->memdesc))
- pagetable = pagetable->mmu->securepagetable;
-
- entry->memdesc.pagetable = pagetable;
-
if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT)
- ret = kgsl_mmu_sparse_dummy_map(pagetable,
- &entry->memdesc, 0, entry->memdesc.size);
+ ret = kgsl_mmu_sparse_dummy_map(
+ entry->memdesc.pagetable,
+ &entry->memdesc, 0,
+ entry->memdesc.size);
else if (entry->memdesc.gpuaddr)
- ret = kgsl_mmu_map(pagetable, &entry->memdesc);
+ ret = kgsl_mmu_map(entry->memdesc.pagetable,
+ &entry->memdesc);
+
if (ret)
kgsl_mem_entry_detach_process(entry);
}
- kgsl_memfree_purge(pagetable ? pagetable->name : 0,
- entry->memdesc.gpuaddr, entry->memdesc.size);
-
- return ret;
+ kgsl_memfree_purge(entry->memdesc.pagetable, entry->memdesc.gpuaddr,
+ entry->memdesc.size);
-err_put_proc_priv:
- kgsl_process_private_put(process);
return ret;
}
/* Detach a memory entry from a process and unmap it from the MMU */
-
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
{
unsigned int type;
- int ret;
+
if (entry == NULL)
return;
@@ -502,14 +456,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
entry->priv->stats[type].cur -= entry->memdesc.size;
spin_unlock(&entry->priv->mem_lock);
- ret = kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
- /*
- * Do not free the gpuaddr/size if unmap fails. Because if we try
- * to map this range in future, the iommu driver will throw
- * a BUG_ON() because it feels we are overwriting a mapping.
- */
- if (ret == 0)
- kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry);
+ kgsl_mmu_put_gpuaddr(&entry->memdesc);
kgsl_process_private_put(entry->priv);
@@ -2139,10 +2086,21 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,
entry->memdesc.pagetable = pagetable;
entry->memdesc.size = (uint64_t) size;
entry->memdesc.useraddr = hostptr;
- if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
- entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr;
entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR;
+ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
+ int ret;
+
+ /* Register the address in the database */
+ ret = kgsl_mmu_set_svm_region(pagetable,
+ (uint64_t) entry->memdesc.useraddr, (uint64_t) size);
+
+ if (ret)
+ return ret;
+
+ entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr;
+ }
+
return memdesc_sg_virt(&entry->memdesc, NULL);
}
@@ -2392,7 +2350,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
param->flags = entry->memdesc.flags;
- ret = kgsl_mem_entry_attach_process(entry, dev_priv);
+ ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry);
if (ret)
goto unmap;
@@ -2696,7 +2654,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
/* echo back flags */
param->flags = (unsigned int) entry->memdesc.flags;
- result = kgsl_mem_entry_attach_process(entry, dev_priv);
+ result = kgsl_mem_entry_attach_process(dev_priv->device, private,
+ entry);
if (result)
goto error_attach;
@@ -3089,11 +3048,11 @@ static struct kgsl_mem_entry *gpumem_alloc_entry(
entry->memdesc.priv |= KGSL_MEMDESC_SECURE;
ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc,
- private->pagetable, size, flags);
+ size, flags);
if (ret != 0)
goto err;
- ret = kgsl_mem_entry_attach_process(entry, dev_priv);
+ ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry);
if (ret != 0) {
kgsl_sharedmem_free(&entry->memdesc);
goto err;
@@ -3292,7 +3251,7 @@ long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
kgsl_memdesc_set_align(&entry->memdesc, ilog2(param->pagesize));
ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc,
- process->pagetable, param->size, entry->memdesc.flags);
+ param->size, entry->memdesc.flags);
if (ret)
goto err_remove_idr;
@@ -3359,6 +3318,7 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
+ struct kgsl_process_private *private = dev_priv->process_priv;
struct kgsl_sparse_virt_alloc *param = data;
struct kgsl_mem_entry *entry;
int ret;
@@ -3379,7 +3339,7 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
spin_lock_init(&entry->bind_lock);
entry->bind_tree = RB_ROOT;
- ret = kgsl_mem_entry_attach_process(entry, dev_priv);
+ ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry);
if (ret) {
kfree(entry);
return ret;
@@ -4057,16 +4017,16 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private,
return ret;
entry->memdesc.gpuaddr = (uint64_t) addr;
+ entry->memdesc.pagetable = private->pagetable;
ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
if (ret) {
- kgsl_mmu_put_gpuaddr(private->pagetable,
- &entry->memdesc);
+ kgsl_mmu_put_gpuaddr(&entry->memdesc);
return ret;
}
- kgsl_memfree_purge(private->pagetable ? private->pagetable->name : 0,
- entry->memdesc.gpuaddr, entry->memdesc.size);
+ kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr,
+ entry->memdesc.size);
return addr;
}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 9f35a3197a4c..bc681057250d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1403,17 +1403,16 @@ static int _setstate_alloc(struct kgsl_device *device,
{
int ret;
- ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, NULL,
- PAGE_SIZE);
- if (ret)
- return ret;
+ ret = kgsl_sharedmem_alloc_contig(device, &iommu->setstate, PAGE_SIZE);
- /* Mark the setstate memory as read only */
- iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY;
+ if (!ret) {
+ /* Mark the setstate memory as read only */
+ iommu->setstate.flags |= KGSL_MEMFLAGS_GPUREADONLY;
- kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE);
+ kgsl_sharedmem_set(device, &iommu->setstate, 0, 0, PAGE_SIZE);
+ }
- return 0;
+ return ret;
}
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
@@ -1663,7 +1662,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
if (!kgsl_secure_guard_page_memdesc.sgt) {
if (kgsl_allocate_user(KGSL_MMU_DEVICE(pt->mmu),
- &kgsl_secure_guard_page_memdesc, pt,
+ &kgsl_secure_guard_page_memdesc,
sgp_size, KGSL_MEMFLAGS_SECURE)) {
KGSL_CORE_ERR(
"Secure guard page alloc failed\n");
@@ -2364,23 +2363,27 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
}
ret = _insert_gpuaddr(pagetable, addr, size);
- if (ret == 0)
+ if (ret == 0) {
memdesc->gpuaddr = addr;
+ memdesc->pagetable = pagetable;
+ }
out:
spin_unlock(&pagetable->lock);
return ret;
}
-static void kgsl_iommu_put_gpuaddr(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc)
+static void kgsl_iommu_put_gpuaddr(struct kgsl_memdesc *memdesc)
{
- spin_lock(&pagetable->lock);
+ if (memdesc->pagetable == NULL)
+ return;
+
+ spin_lock(&memdesc->pagetable->lock);
- if (_remove_gpuaddr(pagetable, memdesc->gpuaddr))
+ if (_remove_gpuaddr(memdesc->pagetable, memdesc->gpuaddr))
BUG();
- spin_unlock(&pagetable->lock);
+ spin_unlock(&memdesc->pagetable->lock);
}
static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable,
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index f516b7cd245a..46bb6f4656fb 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -424,17 +424,29 @@ EXPORT_SYMBOL(kgsl_mmu_map);
* @pagetable: Pagetable to release the memory from
* @memdesc: Memory descriptor containing the GPU address to free
*/
-void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc)
+void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc)
{
+ struct kgsl_pagetable *pagetable = memdesc->pagetable;
+ int unmap_fail = 0;
+
if (memdesc->size == 0 || memdesc->gpuaddr == 0)
return;
- if (PT_OP_VALID(pagetable, put_gpuaddr))
- pagetable->pt_ops->put_gpuaddr(pagetable, memdesc);
+ if (!kgsl_memdesc_is_global(memdesc))
+ unmap_fail = kgsl_mmu_unmap(pagetable, memdesc);
+
+ /*
+ * Do not free the gpuaddr/size if unmap fails. Because if we
+ * try to map this range in future, the iommu driver will throw
+ * a BUG_ON() because it feels we are overwriting a mapping.
+ */
+ if (PT_OP_VALID(pagetable, put_gpuaddr) && (unmap_fail == 0))
+ pagetable->pt_ops->put_gpuaddr(memdesc);
if (!kgsl_memdesc_is_global(memdesc))
memdesc->gpuaddr = 0;
+
+ memdesc->pagetable = NULL;
}
EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr);
@@ -630,7 +642,12 @@ static int nommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl);
- return memdesc->gpuaddr != 0 ? 0 : -ENOMEM;
+ if (memdesc->gpuaddr) {
+ memdesc->pagetable = pagetable;
+ return 0;
+ }
+
+ return -ENOMEM;
}
static struct kgsl_mmu_pt_ops nommu_pt_ops = {
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 3e32c25b3dbe..bc448d424ccb 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -92,7 +92,7 @@ struct kgsl_mmu_pt_ops {
u64 (*get_ttbr0)(struct kgsl_pagetable *);
u32 (*get_contextidr)(struct kgsl_pagetable *);
int (*get_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *);
- void (*put_gpuaddr)(struct kgsl_pagetable *, struct kgsl_memdesc *);
+ void (*put_gpuaddr)(struct kgsl_memdesc *);
uint64_t (*find_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t,
uint64_t, uint64_t);
int (*set_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t);
@@ -181,8 +181,7 @@ int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc);
-void kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable,
- struct kgsl_memdesc *memdesc);
+void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
u64 ttbr0, uint64_t addr);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 618e9e9a33a3..283b72c22db4 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -318,12 +318,11 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device,
static int kgsl_allocate_secure(struct kgsl_device *device,
struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable,
uint64_t size) {
int ret;
if (MMU_FEATURE(&device->mmu, KGSL_MMU_HYP_SECURE_ALLOC))
- ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size);
+ ret = kgsl_sharedmem_page_alloc_user(memdesc, size);
else
ret = kgsl_cma_alloc_secure(device, memdesc, size);
@@ -332,7 +331,6 @@ static int kgsl_allocate_secure(struct kgsl_device *device,
int kgsl_allocate_user(struct kgsl_device *device,
struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable,
uint64_t size, uint64_t flags)
{
int ret;
@@ -340,12 +338,11 @@ int kgsl_allocate_user(struct kgsl_device *device,
memdesc->flags = flags;
if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_NONE)
- ret = kgsl_sharedmem_alloc_contig(device, memdesc,
- pagetable, size);
+ ret = kgsl_sharedmem_alloc_contig(device, memdesc, size);
else if (flags & KGSL_MEMFLAGS_SECURE)
- ret = kgsl_allocate_secure(device, memdesc, pagetable, size);
+ ret = kgsl_allocate_secure(device, memdesc, size);
else
- ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size);
+ ret = kgsl_sharedmem_page_alloc_user(memdesc, size);
return ret;
}
@@ -637,7 +634,6 @@ static inline int get_page_size(size_t size, unsigned int align)
int
kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable,
uint64_t size)
{
int ret = 0;
@@ -671,7 +667,6 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
len_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT;
- memdesc->pagetable = pagetable;
memdesc->ops = &kgsl_page_alloc_ops;
/*
@@ -805,18 +800,8 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc)
if (memdesc == NULL || memdesc->size == 0)
return;
- if (memdesc->gpuaddr) {
- int ret = 0;
-
- ret = kgsl_mmu_unmap(memdesc->pagetable, memdesc);
- /*
- * Do not free the gpuaddr/size if unmap fails. Because if we
- * try to map this range in future, the iommu driver will throw
- * a BUG_ON() because it feels we are overwriting a mapping.
- */
- if (ret == 0)
- kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc);
- }
+ /* Make sure the memory object has been unmapped */
+ kgsl_mmu_put_gpuaddr(memdesc);
if (memdesc->ops && memdesc->ops->free)
memdesc->ops->free(memdesc);
@@ -996,8 +981,7 @@ void kgsl_get_memory_usage(char *name, size_t name_size, uint64_t memflags)
EXPORT_SYMBOL(kgsl_get_memory_usage);
int kgsl_sharedmem_alloc_contig(struct kgsl_device *device,
- struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable, uint64_t size)
+ struct kgsl_memdesc *memdesc, uint64_t size)
{
int result = 0;
@@ -1006,7 +990,6 @@ int kgsl_sharedmem_alloc_contig(struct kgsl_device *device,
return -EINVAL;
memdesc->size = size;
- memdesc->pagetable = pagetable;
memdesc->ops = &kgsl_cma_ops;
memdesc->dev = device->dev->parent;
@@ -1097,7 +1080,6 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device,
{
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
int result = 0;
- struct kgsl_pagetable *pagetable = device->mmu.securepagetable;
size_t aligned;
/* Align size to 1M boundaries */
@@ -1117,7 +1099,6 @@ static int kgsl_cma_alloc_secure(struct kgsl_device *device,
memdesc->priv &= ~KGSL_MEMDESC_GUARD_PAGE;
memdesc->size = aligned;
- memdesc->pagetable = pagetable;
memdesc->ops = &kgsl_cma_ops;
memdesc->dev = iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE].dev;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 9e6817c76df8..03f278ead20f 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -26,7 +26,7 @@ struct kgsl_process_private;
int kgsl_sharedmem_alloc_contig(struct kgsl_device *device,
struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable, uint64_t size);
+ uint64_t size);
void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc);
@@ -66,13 +66,11 @@ void kgsl_sharedmem_uninit_sysfs(void);
int kgsl_allocate_user(struct kgsl_device *device,
struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable,
uint64_t size, uint64_t flags);
void kgsl_get_memory_usage(char *str, size_t len, uint64_t memflags);
int kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc,
- struct kgsl_pagetable *pagetable,
uint64_t size);
#define MEMFLAGS(_flags, _mask, _shift) \
@@ -287,11 +285,10 @@ static inline int kgsl_allocate_global(struct kgsl_device *device,
memdesc->priv = priv;
if ((memdesc->priv & KGSL_MEMDESC_CONTIG) != 0)
- ret = kgsl_sharedmem_alloc_contig(device, memdesc, NULL,
+ ret = kgsl_sharedmem_alloc_contig(device, memdesc,
(size_t) size);
else {
- ret = kgsl_sharedmem_page_alloc_user(memdesc, NULL,
- (size_t) size);
+ ret = kgsl_sharedmem_page_alloc_user(memdesc, (size_t) size);
if (ret == 0)
kgsl_memdesc_map(memdesc);
}
diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c
index e08de7a808eb..0e8fda8b9080 100644
--- a/drivers/iio/adc/qcom-rradc.c
+++ b/drivers/iio/adc/qcom-rradc.c
@@ -20,12 +20,18 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/delay.h>
#include <linux/qpnp/qpnp-revid.h>
#define FG_ADC_RR_EN_CTL 0x46
#define FG_ADC_RR_SKIN_TEMP_LSB 0x50
#define FG_ADC_RR_SKIN_TEMP_MSB 0x51
#define FG_ADC_RR_RR_ADC_CTL 0x52
+#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK 0x8
+#define FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL BIT(3)
+#define FG_ADC_RR_ADC_LOG 0x53
+#define FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK 0xFE
+#define FG_ADC_RR_ADC_LOG_CLR_CTRL BIT(0)
#define FG_ADC_RR_FAKE_BATT_LOW_LSB 0x58
#define FG_ADC_RR_FAKE_BATT_LOW_MSB 0x59
@@ -68,6 +74,8 @@
#define FG_ADC_RR_USB_IN_V_CTRL 0x90
#define FG_ADC_RR_USB_IN_V_TRIGGER 0x91
+#define FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK 0x80
+#define FG_ADC_RR_USB_IN_V_EVERY_CYCLE BIT(7)
#define FG_ADC_RR_USB_IN_V_STS 0x92
#define FG_ADC_RR_USB_IN_V_LSB 0x94
#define FG_ADC_RR_USB_IN_V_MSB 0x95
@@ -175,6 +183,9 @@
#define FG_RR_ADC_MAX_CONTINUOUS_BUFFER_LEN 16
#define FG_RR_ADC_STS_CHANNEL_READING_MASK 0x3
+#define FG_RR_CONV_CONTINUOUS_TIME_MIN 80000
+#define FG_RR_CONV_CONTINUOUS_TIME_MAX 81000
+
/*
* The channel number is not a physical index in hardware,
* rather it's a list of supported channels and an index to
@@ -230,6 +241,21 @@ struct rradc_chan_prop {
u16 adc_code, int *result);
};
+static int rradc_masked_write(struct rradc_chip *rr_adc, u16 offset, u8 mask,
+ u8 val)
+{
+ int rc;
+
+ rc = regmap_update_bits(rr_adc->regmap, rr_adc->base + offset,
+ mask, val);
+ if (rc) {
+ pr_err("spmi write failed: addr=%03X, rc=%d\n", offset, rc);
+ return rc;
+ }
+
+ return rc;
+}
+
static int rradc_read(struct rradc_chip *rr_adc, u16 offset, u8 *data, int len)
{
int rc = 0, retry_cnt = 0, i = 0;
@@ -547,7 +573,7 @@ static const struct rradc_channels rradc_chans[] = {
static int rradc_do_conversion(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u16 *data)
{
- int rc = 0, bytes_to_read = 0;
+ int rc = 0, bytes_to_read = 0, retry = 0;
u8 buf[6];
u16 offset = 0, batt_id_5 = 0, batt_id_15 = 0, batt_id_150 = 0;
u16 status = 0;
@@ -558,7 +584,8 @@ static int rradc_do_conversion(struct rradc_chip *chip,
(prop->channel != RR_ADC_CHG_HOT_TEMP) &&
(prop->channel != RR_ADC_CHG_TOO_HOT_TEMP) &&
(prop->channel != RR_ADC_SKIN_HOT_TEMP) &&
- (prop->channel != RR_ADC_SKIN_TOO_HOT_TEMP)) {
+ (prop->channel != RR_ADC_SKIN_TOO_HOT_TEMP) &&
+ (prop->channel != RR_ADC_USBIN_V)) {
/* BATT_ID STS bit does not get set initially */
status = rradc_chans[prop->channel].sts;
rc = rradc_read(chip, status, buf, 1);
@@ -576,6 +603,85 @@ static int rradc_do_conversion(struct rradc_chip *chip,
}
}
+ if (prop->channel == RR_ADC_USBIN_V) {
+ /* Force conversion every cycle */
+ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
+ FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK,
+ FG_ADC_RR_USB_IN_V_EVERY_CYCLE);
+ if (rc < 0) {
+ pr_err("Force every cycle update failed:%d\n", rc);
+ goto fail;
+ }
+
+ /* Clear channel log */
+ rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
+ FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK,
+ FG_ADC_RR_ADC_LOG_CLR_CTRL);
+ if (rc < 0) {
+ pr_err("log ctrl update to clear failed:%d\n", rc);
+ goto fail;
+ }
+
+ rc = rradc_masked_write(chip, FG_ADC_RR_ADC_LOG,
+ FG_ADC_RR_ADC_LOG_CLR_CTRL_MASK, 0);
+ if (rc < 0) {
+ pr_err("log ctrl update to not clear failed:%d\n", rc);
+ goto fail;
+ }
+
+ /* Switch to continuous mode */
+ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
+ FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK,
+ FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL);
+ if (rc < 0) {
+ pr_err("Update to continuous mode failed:%d\n", rc);
+ goto fail;
+ }
+
+ status = rradc_chans[prop->channel].sts;
+ rc = rradc_read(chip, status, buf, 1);
+ if (rc < 0) {
+ pr_err("status read failed:%d\n", rc);
+ goto fail;
+ }
+
+ buf[0] &= FG_RR_ADC_STS_CHANNEL_READING_MASK;
+ while ((buf[0] != FG_RR_ADC_STS_CHANNEL_READING_MASK) &&
+ (retry < 2)) {
+ pr_debug("%s is not ready; nothing to read\n",
+ rradc_chans[prop->channel].datasheet_name);
+ usleep_range(FG_RR_CONV_CONTINUOUS_TIME_MIN,
+ FG_RR_CONV_CONTINUOUS_TIME_MAX);
+ retry++;
+ rc = rradc_read(chip, status, buf, 1);
+ if (rc < 0) {
+ pr_err("status read failed:%d\n", rc);
+ goto fail;
+ }
+ }
+
+ /* Switch to non continuous mode */
+ rc = rradc_masked_write(chip, FG_ADC_RR_RR_ADC_CTL,
+ FG_ADC_RR_ADC_CTL_CONTINUOUS_SEL_MASK, 0);
+ if (rc < 0) {
+ pr_err("Update to continuous mode failed:%d\n", rc);
+ goto fail;
+ }
+
+ /* Restore usb_in trigger */
+ rc = rradc_masked_write(chip, FG_ADC_RR_USB_IN_V_TRIGGER,
+ FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, 0);
+ if (rc < 0) {
+ pr_err("Restore every cycle update failed:%d\n", rc);
+ goto fail;
+ }
+
+ if (retry >= 2) {
+ rc = -ENODATA;
+ goto fail;
+ }
+ }
+
offset = rradc_chans[prop->channel].lsb;
if (prop->channel == RR_ADC_BATT_ID)
bytes_to_read = 6;
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index ea3d0eed47e1..674ca6161af9 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -10,6 +10,8 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "flashv2: %s: " fmt, __func__
+
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -27,6 +29,8 @@
#include <linux/regulator/consumer.h>
#include <linux/leds-qpnp-flash.h>
#include <linux/leds-qpnp-flash-v2.h>
+#include <linux/qpnp/qpnp-revid.h>
+#include <linux/log2.h>
#include "leds.h"
#define FLASH_LED_REG_LED_STATUS1(base) (base + 0x08)
@@ -43,9 +47,12 @@
#define FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(base) (base + 0x50)
#define FLASH_LED_REG_WARMUP_DELAY(base) (base + 0x51)
#define FLASH_LED_REG_ISC_DELAY(base) (base + 0x52)
+#define FLASH_LED_REG_THERMAL_RMP_DN_RATE(base) (base + 0x55)
#define FLASH_LED_REG_THERMAL_THRSH1(base) (base + 0x56)
#define FLASH_LED_REG_THERMAL_THRSH2(base) (base + 0x57)
#define FLASH_LED_REG_THERMAL_THRSH3(base) (base + 0x58)
+#define FLASH_LED_REG_THERMAL_HYSTERESIS(base) (base + 0x59)
+#define FLASH_LED_REG_THERMAL_DEBOUNCE(base) (base + 0x5A)
#define FLASH_LED_REG_VPH_DROOP_THRESHOLD(base) (base + 0x61)
#define FLASH_LED_REG_VPH_DROOP_DEBOUNCE(base) (base + 0x62)
#define FLASH_LED_REG_ILED_GRT_THRSH(base) (base + 0x67)
@@ -58,13 +65,10 @@
#define FLASH_LED_REG_LMH_LEVEL(base) (base + 0x70)
#define FLASH_LED_REG_CURRENT_DERATE_EN(base) (base + 0x76)
-#define FLASH_LED_HDRM_MODE_PRGM_MASK GENMASK(7, 0)
#define FLASH_LED_HDRM_VOL_MASK GENMASK(7, 4)
#define FLASH_LED_CURRENT_MASK GENMASK(6, 0)
#define FLASH_LED_ENABLE_MASK GENMASK(2, 0)
#define FLASH_HW_STROBE_MASK GENMASK(2, 0)
-#define FLASH_LED_SAFETY_TMR_MASK GENMASK(7, 0)
-#define FLASH_LED_INT_RT_STS_MASK GENMASK(7, 0)
#define FLASH_LED_ISC_WARMUP_DELAY_MASK GENMASK(1, 0)
#define FLASH_LED_CURRENT_DERATE_EN_MASK GENMASK(2, 0)
#define FLASH_LED_VPH_DROOP_DEBOUNCE_MASK GENMASK(1, 0)
@@ -74,13 +78,19 @@
#define FLASH_LED_LMH_LEVEL_MASK GENMASK(1, 0)
#define FLASH_LED_VPH_DROOP_HYSTERESIS_MASK GENMASK(5, 4)
#define FLASH_LED_VPH_DROOP_THRESHOLD_MASK GENMASK(2, 0)
+#define FLASH_LED_THERMAL_HYSTERESIS_MASK GENMASK(1, 0)
+#define FLASH_LED_THERMAL_DEBOUNCE_MASK GENMASK(1, 0)
#define FLASH_LED_THERMAL_THRSH_MASK GENMASK(2, 0)
-#define FLASH_LED_THERMAL_OTST_MASK GENMASK(2, 0)
#define FLASH_LED_MOD_CTRL_MASK BIT(7)
#define FLASH_LED_HW_SW_STROBE_SEL_BIT BIT(2)
#define FLASH_LED_VPH_DROOP_FAULT_MASK BIT(4)
#define FLASH_LED_LMH_MITIGATION_EN_MASK BIT(0)
#define FLASH_LED_CHGR_MITIGATION_EN_MASK BIT(4)
+#define THERMAL_OTST1_RAMP_CTRL_MASK BIT(7)
+#define THERMAL_OTST1_RAMP_CTRL_SHIFT 7
+#define THERMAL_DERATE_SLOW_SHIFT 4
+#define THERMAL_DERATE_SLOW_MASK GENMASK(6, 4)
+#define THERMAL_DERATE_FAST_MASK GENMASK(2, 0)
#define VPH_DROOP_DEBOUNCE_US_TO_VAL(val_us) (val_us / 8)
#define VPH_DROOP_HYST_MV_TO_VAL(val_mv) (val_mv / 25)
@@ -89,17 +99,24 @@
#define MITIGATION_THRSH_MA_TO_VAL(val_ma) (val_ma / 100)
#define CURRENT_MA_TO_REG_VAL(curr_ma, ires_ua) ((curr_ma * 1000) / ires_ua - 1)
#define SAFETY_TMR_TO_REG_VAL(duration_ms) ((duration_ms / 10) - 1)
+#define THERMAL_HYST_TEMP_TO_VAL(val, divisor) (val / divisor)
#define FLASH_LED_ISC_WARMUP_DELAY_SHIFT 6
#define FLASH_LED_WARMUP_DELAY_DEFAULT 2
#define FLASH_LED_ISC_DELAY_DEFAULT 3
#define FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT 2
+#define FLASH_LED_VPH_DROOP_HYST_SHIFT 4
#define FLASH_LED_VPH_DROOP_HYST_DEFAULT 2
#define FLASH_LED_VPH_DROOP_THRESH_DEFAULT 5
-#define FLASH_LED_VPH_DROOP_DEBOUNCE_MAX 3
-#define FLASH_LED_VPH_DROOP_HYST_MAX 3
+#define FLASH_LED_DEBOUNCE_MAX 3
+#define FLASH_LED_HYSTERESIS_MAX 3
#define FLASH_LED_VPH_DROOP_THRESH_MAX 7
+#define THERMAL_DERATE_SLOW_MAX 314592
+#define THERMAL_DERATE_FAST_MAX 512
+#define THERMAL_DEBOUNCE_TIME_MAX 64
+#define THERMAL_DERATE_HYSTERESIS_MAX 3
#define FLASH_LED_THERMAL_THRSH_MIN 3
+#define FLASH_LED_THERMAL_THRSH_MAX 7
#define FLASH_LED_THERMAL_OTST_LEVELS 3
#define FLASH_LED_VLED_MAX_DEFAULT_UV 3500000
#define FLASH_LED_IBATT_OCP_THRESH_DEFAULT_UA 4500000
@@ -191,32 +208,41 @@ struct flash_switch_data {
* Flash LED configuration read from device tree
*/
struct flash_led_platform_data {
- int *thermal_derate_current;
- int all_ramp_up_done_irq;
- int all_ramp_down_done_irq;
- int led_fault_irq;
- int ibatt_ocp_threshold_ua;
- int vled_max_uv;
- int rpara_uohm;
- int lmh_rbatt_threshold_uohm;
- int lmh_ocv_threshold_uv;
- u32 led1n2_iclamp_low_ma;
- u32 led1n2_iclamp_mid_ma;
- u32 led3_iclamp_low_ma;
- u32 led3_iclamp_mid_ma;
- u8 isc_delay;
- u8 warmup_delay;
- u8 current_derate_en_cfg;
- u8 vph_droop_threshold;
- u8 vph_droop_hysteresis;
- u8 vph_droop_debounce;
- u8 lmh_mitigation_sel;
- u8 chgr_mitigation_sel;
- u8 lmh_level;
- u8 iled_thrsh_val;
- u8 hw_strobe_option;
- bool hdrm_auto_mode_en;
- bool thermal_derate_en;
+ struct pmic_revid_data *pmic_rev_id;
+ int *thermal_derate_current;
+ int all_ramp_up_done_irq;
+ int all_ramp_down_done_irq;
+ int led_fault_irq;
+ int ibatt_ocp_threshold_ua;
+ int vled_max_uv;
+ int rpara_uohm;
+ int lmh_rbatt_threshold_uohm;
+ int lmh_ocv_threshold_uv;
+ int thermal_derate_slow;
+ int thermal_derate_fast;
+ int thermal_hysteresis;
+ int thermal_debounce;
+ int thermal_thrsh1;
+ int thermal_thrsh2;
+ int thermal_thrsh3;
+ u32 led1n2_iclamp_low_ma;
+ u32 led1n2_iclamp_mid_ma;
+ u32 led3_iclamp_low_ma;
+ u32 led3_iclamp_mid_ma;
+ u8 isc_delay;
+ u8 warmup_delay;
+ u8 current_derate_en_cfg;
+ u8 vph_droop_threshold;
+ u8 vph_droop_hysteresis;
+ u8 vph_droop_debounce;
+ u8 lmh_mitigation_sel;
+ u8 chgr_mitigation_sel;
+ u8 lmh_level;
+ u8 iled_thrsh_val;
+ u8 hw_strobe_option;
+ bool hdrm_auto_mode_en;
+ bool thermal_derate_en;
+ bool otst_ramp_bkup_en;
};
/*
@@ -239,22 +265,54 @@ struct qpnp_flash_led {
bool trigger_chgr;
};
-static int
-qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
+static int thermal_derate_slow_table[] = {
+ 128, 256, 512, 1024, 2048, 4096, 8192, 314592,
+};
+
+static int thermal_derate_fast_table[] = {
+ 32, 64, 96, 128, 256, 384, 512,
+};
+
+static int otst1_threshold_table[] = {
+ 85, 79, 73, 67, 109, 103, 97, 91,
+};
+
+static int otst2_threshold_table[] = {
+ 110, 104, 98, 92, 134, 128, 122, 116,
+};
+
+static int otst3_threshold_table[] = {
+ 125, 119, 113, 107, 149, 143, 137, 131,
+};
+
+static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
{
int rc;
uint val;
rc = regmap_read(led->regmap, addr, &val);
- if (rc < 0)
- dev_err(&led->pdev->dev, "Unable to read from 0x%04X rc = %d\n",
- addr, rc);
- else
- dev_dbg(&led->pdev->dev, "Read 0x%02X from addr 0x%04X\n",
- val, addr);
+ if (rc < 0) {
+ pr_err("Unable to read from 0x%04X rc = %d\n", addr, rc);
+ return rc;
+ }
+ pr_debug("Read 0x%02X from addr 0x%04X\n", val, addr);
*data = (u8)val;
- return rc;
+ return 0;
+}
+
+static int qpnp_flash_led_write(struct qpnp_flash_led *led, u16 addr, u8 data)
+{
+ int rc;
+
+ rc = regmap_write(led->regmap, addr, data);
+ if (rc < 0) {
+ pr_err("Unable to write to 0x%04X rc = %d\n", addr, rc);
+ return rc;
+ }
+
+ pr_debug("Wrote 0x%02X to addr 0x%04X\n", data, addr);
+ return 0;
}
static int
@@ -279,11 +337,10 @@ qpnp_flash_led_masked_write(struct qpnp_flash_led *led, u16 addr, u8 mask,
rc = regmap_update_bits(led->regmap, addr, mask, val);
if (rc < 0)
- dev_err(&led->pdev->dev, "Unable to update bits from 0x%04X, rc = %d\n",
- addr, rc);
+ pr_err("Unable to update bits from 0x%04X, rc = %d\n", addr,
+ rc);
else
- dev_dbg(&led->pdev->dev, "Wrote 0x%02X to addr 0x%04X\n",
- val, addr);
+ pr_debug("Wrote 0x%02X to addr 0x%04X\n", val, addr);
return rc;
}
@@ -297,13 +354,12 @@ led_brightness qpnp_flash_led_brightness_get(struct led_classdev *led_cdev)
static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
{
int rc, i, addr_offset;
- u8 val = 0;
+ u8 val = 0, mask;
for (i = 0; i < led->num_fnodes; i++) {
addr_offset = led->fnode[i].id;
- rc = qpnp_flash_led_masked_write(led,
+ rc = qpnp_flash_led_write(led,
FLASH_LED_REG_HDRM_PRGM(led->base + addr_offset),
- FLASH_LED_HDRM_MODE_PRGM_MASK,
led->fnode[i].hdrm_val);
if (rc < 0)
return rc;
@@ -311,9 +367,9 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
val |= 0x1 << led->fnode[i].id;
}
- rc = qpnp_flash_led_masked_write(led,
+ rc = qpnp_flash_led_write(led,
FLASH_LED_REG_HDRM_AUTO_MODE_CTRL(led->base),
- FLASH_LED_HDRM_MODE_PRGM_MASK, val);
+ val);
if (rc < 0)
return rc;
@@ -338,6 +394,70 @@ static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
if (rc < 0)
return rc;
+ val = (led->pdata->otst_ramp_bkup_en << THERMAL_OTST1_RAMP_CTRL_SHIFT);
+ mask = THERMAL_OTST1_RAMP_CTRL_MASK;
+ if (led->pdata->thermal_derate_slow >= 0) {
+ val |= (led->pdata->thermal_derate_slow <<
+ THERMAL_DERATE_SLOW_SHIFT);
+ mask |= THERMAL_DERATE_SLOW_MASK;
+ }
+
+ if (led->pdata->thermal_derate_fast >= 0) {
+ val |= led->pdata->thermal_derate_fast;
+ mask |= THERMAL_DERATE_FAST_MASK;
+ }
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_RMP_DN_RATE(led->base),
+ mask, val);
+ if (rc < 0)
+ return rc;
+
+ if (led->pdata->thermal_debounce >= 0) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_DEBOUNCE(led->base),
+ FLASH_LED_THERMAL_DEBOUNCE_MASK,
+ led->pdata->thermal_debounce);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->thermal_hysteresis >= 0) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_HYSTERESIS(led->base),
+ FLASH_LED_THERMAL_HYSTERESIS_MASK,
+ led->pdata->thermal_hysteresis);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->thermal_thrsh1 >= 0) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_THRSH1(led->base),
+ FLASH_LED_THERMAL_THRSH_MASK,
+ led->pdata->thermal_thrsh1);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->thermal_thrsh2 >= 0) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_THRSH2(led->base),
+ FLASH_LED_THERMAL_THRSH_MASK,
+ led->pdata->thermal_thrsh2);
+ if (rc < 0)
+ return rc;
+ }
+
+ if (led->pdata->thermal_thrsh3 >= 0) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_THERMAL_THRSH3(led->base),
+ FLASH_LED_THERMAL_THRSH_MASK,
+ led->pdata->thermal_thrsh3);
+ if (rc < 0)
+ return rc;
+ }
+
rc = qpnp_flash_led_masked_write(led,
FLASH_LED_REG_VPH_DROOP_DEBOUNCE(led->base),
FLASH_LED_VPH_DROOP_DEBOUNCE_MASK,
@@ -456,8 +576,7 @@ static int qpnp_flash_led_hw_strobe_enable(struct flash_node_data *fnode,
on ? fnode->hw_strobe_state_active :
fnode->hw_strobe_state_suspend);
if (rc < 0) {
- dev_err(&fnode->pdev->dev,
- "failed to change hw strobe pin state\n");
+ pr_err("failed to change hw strobe pin state\n");
return rc;
}
}
@@ -482,7 +601,7 @@ static int qpnp_flash_led_regulator_enable(struct qpnp_flash_led *led,
rc = regulator_disable(snode->vreg);
if (rc < 0) {
- dev_err(&led->pdev->dev, "regulator_%s failed, rc=%d\n",
+ pr_err("regulator_%s failed, rc=%d\n",
on ? "enable" : "disable", rc);
return rc;
}
@@ -498,14 +617,13 @@ static int get_property_from_fg(struct qpnp_flash_led *led,
union power_supply_propval pval = {0, };
if (!led->bms_psy) {
- dev_err(&led->pdev->dev, "no bms psy found\n");
+ pr_err("no bms psy found\n");
return -EINVAL;
}
rc = power_supply_get_property(led->bms_psy, prop, &pval);
if (rc) {
- dev_err(&led->pdev->dev,
- "bms psy doesn't support reading prop %d rc = %d\n",
+ pr_err("bms psy doesn't support reading prop %d rc = %d\n",
prop, rc);
return rc;
}
@@ -567,8 +685,7 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
rc = get_property_from_fg(led, POWER_SUPPLY_PROP_RESISTANCE,
&rbatt_uohm);
if (rc < 0) {
- dev_err(&led->pdev->dev, "bms psy does not support resistance, rc=%d\n",
- rc);
+ pr_err("bms psy does not support resistance, rc=%d\n", rc);
return rc;
}
@@ -578,16 +695,14 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
rc = get_property_from_fg(led, POWER_SUPPLY_PROP_VOLTAGE_OCV, &ocv_uv);
if (rc < 0) {
- dev_err(&led->pdev->dev, "bms psy does not support OCV, rc=%d\n",
- rc);
+ pr_err("bms psy does not support OCV, rc=%d\n", rc);
return rc;
}
rc = get_property_from_fg(led, POWER_SUPPLY_PROP_CURRENT_NOW,
&ibat_now);
if (rc < 0) {
- dev_err(&led->pdev->dev, "bms psy does not support current, rc=%d\n",
- rc);
+ pr_err("bms psy does not support current, rc=%d\n", rc);
return rc;
}
@@ -606,8 +721,7 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
FLASH_LED_LMH_MITIGATION_EN_MASK,
FLASH_LED_LMH_MITIGATION_ENABLE);
if (rc < 0) {
- dev_err(&led->pdev->dev, "trigger lmh mitigation failed, rc=%d\n",
- rc);
+ pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
return rc;
}
@@ -652,9 +766,8 @@ static int qpnp_flash_led_calc_max_current(struct qpnp_flash_led *led)
* before collapsing the battery. (available power/ flash input voltage)
*/
avail_flash_ua = div64_s64(avail_flash_power_fw, vin_flash_uv * MCONV);
- dev_dbg(&led->pdev->dev, "avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
- avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm,
- led->trigger_lmh);
+ pr_debug("avail_iflash=%lld, ocv=%d, ibat=%d, rbatt=%d, trigger_lmh=%d\n",
+ avail_flash_ua, ocv_uv, ibat_now, rbatt_uohm, led->trigger_lmh);
return min(FLASH_LED_MAX_TOTAL_CURRENT_MA,
(int)(div64_s64(avail_flash_ua, MCONV)));
}
@@ -796,8 +909,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
FLASH_LED_LMH_MITIGATION_EN_MASK,
FLASH_LED_LMH_MITIGATION_DISABLE);
if (rc < 0) {
- dev_err(&led->pdev->dev, "disable lmh mitigation failed, rc=%d\n",
- rc);
+ pr_err("disable lmh mitigation failed, rc=%d\n", rc);
return rc;
}
}
@@ -808,8 +920,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
FLASH_LED_CHGR_MITIGATION_EN_MASK,
FLASH_LED_CHGR_MITIGATION_DISABLE);
if (rc < 0) {
- dev_err(&led->pdev->dev, "disable chgr mitigation failed, rc=%d\n",
- rc);
+ pr_err("disable chgr mitigation failed, rc=%d\n", rc);
return rc;
}
}
@@ -841,8 +952,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
rc = pinctrl_select_state(led->fnode[i].pinctrl,
led->fnode[i].gpio_state_suspend);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "failed to disable GPIO, rc=%d\n", rc);
+ pr_err("failed to disable GPIO, rc=%d\n", rc);
return rc;
}
}
@@ -851,8 +961,7 @@ static int qpnp_flash_led_switch_disable(struct flash_switch_data *snode)
rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
led->pdata->hw_strobe_option, false);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "Unable to disable hw strobe, rc=%d\n",
+ pr_err("Unable to disable hw strobe, rc=%d\n",
rc);
return rc;
}
@@ -870,8 +979,8 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
u8 val, mask;
if (snode->enabled == on) {
- dev_dbg(&led->pdev->dev, "Switch node is already %s!\n",
- on ? "enabled" : "disabled");
+ pr_debug("Switch node is already %s!\n",
+ on ? "enabled" : "disabled");
return 0;
}
@@ -921,9 +1030,9 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
if (rc < 0)
return rc;
- rc = qpnp_flash_led_masked_write(led,
+ rc = qpnp_flash_led_write(led,
FLASH_LED_REG_SAFETY_TMR(led->base + addr_offset),
- FLASH_LED_SAFETY_TMR_MASK, led->fnode[i].duration);
+ led->fnode[i].duration);
if (rc < 0)
return rc;
@@ -933,8 +1042,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
rc = pinctrl_select_state(led->fnode[i].pinctrl,
led->fnode[i].gpio_state_active);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "failed to enable GPIO\n");
+ pr_err("failed to enable GPIO rc=%d\n", rc);
return rc;
}
}
@@ -943,8 +1051,8 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
rc = qpnp_flash_led_hw_strobe_enable(&led->fnode[i],
led->pdata->hw_strobe_option, true);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "Unable to enable hw strobe\n");
+ pr_err("Unable to enable hw strobe rc=%d\n",
+ rc);
return rc;
}
}
@@ -965,8 +1073,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
FLASH_LED_LMH_MITIGATION_EN_MASK,
FLASH_LED_LMH_MITIGATION_ENABLE);
if (rc < 0) {
- dev_err(&led->pdev->dev, "trigger lmh mitigation failed, rc=%d\n",
- rc);
+ pr_err("trigger lmh mitigation failed, rc=%d\n", rc);
return rc;
}
}
@@ -977,8 +1084,7 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on)
FLASH_LED_CHGR_MITIGATION_EN_MASK,
FLASH_LED_CHGR_MITIGATION_ENABLE);
if (rc < 0) {
- dev_err(&led->pdev->dev, "trigger chgr mitigation failed, rc=%d\n",
- rc);
+ pr_err("trigger chgr mitigation failed, rc=%d\n", rc);
return rc;
}
}
@@ -1010,15 +1116,14 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
led = dev_get_drvdata(&snode->pdev->dev);
if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
- dev_err(&led->pdev->dev, "Invalid options %d\n", options);
+ pr_err("Invalid options %d\n", options);
return -EINVAL;
}
if (options & ENABLE_REGULATOR) {
rc = qpnp_flash_led_regulator_enable(led, snode, true);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "enable regulator failed, rc=%d\n", rc);
+ pr_err("enable regulator failed, rc=%d\n", rc);
return rc;
}
}
@@ -1026,8 +1131,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
if (options & DISABLE_REGULATOR) {
rc = qpnp_flash_led_regulator_enable(led, snode, false);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "disable regulator failed, rc=%d\n", rc);
+ pr_err("disable regulator failed, rc=%d\n", rc);
return rc;
}
}
@@ -1035,8 +1139,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
if (options & QUERY_MAX_CURRENT) {
rc = qpnp_flash_led_get_max_avail_current(led);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "query max current failed, rc=%d\n", rc);
+ pr_err("query max current failed, rc=%d\n", rc);
return rc;
}
*max_current = rc;
@@ -1076,8 +1179,7 @@ static void qpnp_flash_led_brightness_set(struct led_classdev *led_cdev,
if (snode) {
rc = qpnp_flash_led_switch_set(snode, value > 0);
if (rc < 0)
- dev_err(&led->pdev->dev,
- "Failed to set flash LED switch\n");
+ pr_err("Failed to set flash LED switch rc=%d\n", rc);
} else if (fnode) {
qpnp_flash_led_node_set(fnode, value);
}
@@ -1099,8 +1201,7 @@ static ssize_t qpnp_flash_led_max_current_show(struct device *dev,
rc = qpnp_flash_led_get_max_avail_current(led);
if (rc < 0)
- dev_err(&led->pdev->dev, "query max current failed, rc=%d\n",
- rc);
+ pr_err("query max current failed, rc=%d\n", rc);
return snprintf(buf, PAGE_SIZE, "%d\n", rc);
}
@@ -1124,7 +1225,7 @@ static int flash_led_psy_notifier_call(struct notifier_block *nb,
if (!strcmp(psy->desc->name, "bms")) {
led->bms_psy = power_supply_get_by_name("bms");
if (!led->bms_psy)
- dev_err(&led->pdev->dev, "Failed to get bms power_supply\n");
+ pr_err("Failed to get bms power_supply\n");
else
power_supply_unreg_notifier(&led->nb);
}
@@ -1154,13 +1255,12 @@ static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
int rc;
u8 irq_status, led_status1, led_status2;
- dev_dbg(&led->pdev->dev, "irq received, irq=%d\n", irq);
+ pr_debug("irq received, irq=%d\n", irq);
rc = qpnp_flash_led_read(led,
FLASH_LED_REG_INT_RT_STS(led->base), &irq_status);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Failed to read interrupt status reg, rc=%d\n",
- rc);
+ pr_err("Failed to read interrupt status reg, rc=%d\n", rc);
goto exit;
}
@@ -1179,29 +1279,27 @@ static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
rc = qpnp_flash_led_read(led,
FLASH_LED_REG_LED_STATUS1(led->base), &led_status1);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Failed to read led_status1 reg, rc=%d\n",
- rc);
+ pr_err("Failed to read led_status1 reg, rc=%d\n", rc);
goto exit;
}
rc = qpnp_flash_led_read(led,
FLASH_LED_REG_LED_STATUS2(led->base), &led_status2);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Failed to read led_status2 reg, rc=%d\n",
- rc);
+ pr_err("Failed to read led_status2 reg, rc=%d\n", rc);
goto exit;
}
if (led_status1)
- dev_emerg(&led->pdev->dev, "led short/open fault detected! led_status1=%x\n",
- led_status1);
+ pr_emerg("led short/open fault detected! led_status1=%x\n",
+ led_status1);
if (led_status2 & FLASH_LED_VPH_DROOP_FAULT_MASK)
- dev_emerg(&led->pdev->dev, "led vph_droop fault detected!\n");
+ pr_emerg("led vph_droop fault detected!\n");
}
- dev_dbg(&led->pdev->dev, "irq handled, irq_type=%x, irq_status=%x\n",
- irq_type, irq_status);
+ pr_debug("irq handled, irq_type=%x, irq_status=%x\n", irq_type,
+ irq_status);
exit:
return IRQ_HANDLED;
@@ -1231,7 +1329,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
rc = of_property_read_string(node, "qcom,led-name", &fnode->cdev.name);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Unable to read flash LED names\n");
+ pr_err("Unable to read flash LED names\n");
return rc;
}
@@ -1242,11 +1340,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
} else if (!strcmp(temp_string, "torch")) {
fnode->type = FLASH_LED_TYPE_TORCH;
} else {
- dev_err(&led->pdev->dev, "Wrong flash LED type\n");
+ pr_err("Wrong flash LED type\n");
return rc;
}
} else {
- dev_err(&led->pdev->dev, "Unable to read flash LED label\n");
+ pr_err("Unable to read flash LED label\n");
return rc;
}
@@ -1254,14 +1352,14 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
if (!rc) {
fnode->id = (u8)val;
} else {
- dev_err(&led->pdev->dev, "Unable to read flash LED ID\n");
+ pr_err("Unable to read flash LED ID\n");
return rc;
}
rc = of_property_read_string(node, "qcom,default-led-trigger",
&fnode->cdev.default_trigger);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Unable to read trigger name\n");
+ pr_err("Unable to read trigger name\n");
return rc;
}
@@ -1273,7 +1371,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->ires = FLASH_LED_IRES_BASE -
(val - FLASH_LED_IRES_MIN_UA) / FLASH_LED_IRES_DIVISOR;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read current resolution\n");
+ pr_err("Unable to read current resolution rc=%d\n", rc);
return rc;
}
@@ -1284,8 +1382,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->max_current = val;
fnode->cdev.max_brightness = val;
} else {
- dev_err(&led->pdev->dev,
- "Unable to read max current, rc=%d\n", rc);
+ pr_err("Unable to read max current, rc=%d\n", rc);
return rc;
}
@@ -1293,8 +1390,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
if (!rc) {
if (val < FLASH_LED_MIN_CURRENT_MA ||
val > fnode->max_current)
- dev_warn(&led->pdev->dev,
- "Invalid operational current specified, capping it\n");
+ pr_warn("Invalid operational current specified, capping it\n");
if (val < FLASH_LED_MIN_CURRENT_MA)
val = FLASH_LED_MIN_CURRENT_MA;
if (val > fnode->max_current)
@@ -1302,8 +1398,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->current_ma = val;
fnode->cdev.brightness = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read operational current, rc=%d\n", rc);
+ pr_err("Unable to read operational current, rc=%d\n", rc);
return rc;
}
@@ -1314,13 +1409,11 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
FLASH_LED_SAFETY_TMR_ENABLE);
} else if (rc == -EINVAL) {
if (fnode->type == FLASH_LED_TYPE_FLASH) {
- dev_err(&led->pdev->dev,
- "Timer duration is required for flash LED\n");
+ pr_err("Timer duration is required for flash LED\n");
return rc;
}
} else {
- dev_err(&led->pdev->dev,
- "Unable to read timer duration\n");
+ pr_err("Unable to read timer duration\n");
return rc;
}
@@ -1332,7 +1425,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->hdrm_val = (val << FLASH_LED_HDRM_VOL_SHIFT) &
FLASH_LED_HDRM_VOL_MASK;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read headroom voltage\n");
+ pr_err("Unable to read headroom voltage\n");
return rc;
}
@@ -1343,8 +1436,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
} else if (rc == -EINVAL) {
fnode->hdrm_val |= FLASH_LED_HDRM_VOL_HI_LO_WIN_DEFAULT_MV;
} else {
- dev_err(&led->pdev->dev,
- "Unable to read hdrm hi-lo window voltage\n");
+ pr_err("Unable to read hdrm hi-lo window voltage\n");
return rc;
}
@@ -1362,8 +1454,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->hw_strobe_gpio = of_get_named_gpio(node,
"qcom,hw-strobe-gpio", 0);
if (fnode->hw_strobe_gpio < 0) {
- dev_err(&led->pdev->dev,
- "Invalid gpio specified\n");
+ pr_err("Invalid gpio specified\n");
return fnode->hw_strobe_gpio;
}
gpio_direction_output(fnode->hw_strobe_gpio, 0);
@@ -1373,8 +1464,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
pinctrl_lookup_state(fnode->pinctrl,
"strobe_enable");
if (IS_ERR_OR_NULL(fnode->hw_strobe_state_active)) {
- dev_err(&led->pdev->dev,
- "No active pin for hardware strobe, rc=%ld\n",
+ pr_err("No active pin for hardware strobe, rc=%ld\n",
PTR_ERR(fnode->hw_strobe_state_active));
fnode->hw_strobe_state_active = NULL;
}
@@ -1383,8 +1473,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
pinctrl_lookup_state(fnode->pinctrl,
"strobe_disable");
if (IS_ERR_OR_NULL(fnode->hw_strobe_state_suspend)) {
- dev_err(&led->pdev->dev,
- "No suspend pin for hardware strobe, rc=%ld\n",
+ pr_err("No suspend pin for hardware strobe, rc=%ld\n",
PTR_ERR(fnode->hw_strobe_state_suspend)
);
fnode->hw_strobe_state_suspend = NULL;
@@ -1394,8 +1483,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
rc = led_classdev_register(&led->pdev->dev, &fnode->cdev);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Unable to register led node %d\n",
- fnode->id);
+ pr_err("Unable to register led node %d\n", fnode->id);
return rc;
}
@@ -1403,14 +1491,13 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->pinctrl = devm_pinctrl_get(fnode->cdev.dev);
if (IS_ERR_OR_NULL(fnode->pinctrl)) {
- dev_dbg(&led->pdev->dev, "No pinctrl defined\n");
+ pr_debug("No pinctrl defined\n");
fnode->pinctrl = NULL;
} else {
fnode->gpio_state_active =
pinctrl_lookup_state(fnode->pinctrl, "led_enable");
if (IS_ERR_OR_NULL(fnode->gpio_state_active)) {
- dev_err(&led->pdev->dev,
- "Cannot lookup LED active state\n");
+ pr_err("Cannot lookup LED active state\n");
devm_pinctrl_put(fnode->pinctrl);
fnode->pinctrl = NULL;
return PTR_ERR(fnode->gpio_state_active);
@@ -1419,8 +1506,7 @@ static int qpnp_flash_led_parse_each_led_dt(struct qpnp_flash_led *led,
fnode->gpio_state_suspend =
pinctrl_lookup_state(fnode->pinctrl, "led_disable");
if (IS_ERR_OR_NULL(fnode->gpio_state_suspend)) {
- dev_err(&led->pdev->dev,
- "Cannot lookup LED disable state\n");
+ pr_err("Cannot lookup LED disable state\n");
devm_pinctrl_put(fnode->pinctrl);
fnode->pinctrl = NULL;
return PTR_ERR(fnode->gpio_state_suspend);
@@ -1439,8 +1525,7 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
rc = of_property_read_string(node, "qcom,led-name", &snode->cdev.name);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "Failed to read switch node name, rc=%d\n", rc);
+ pr_err("Failed to read switch node name, rc=%d\n", rc);
return rc;
}
@@ -1453,19 +1538,18 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
rc = of_property_read_string(node, "qcom,default-led-trigger",
&snode->cdev.default_trigger);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "Unable to read trigger name, rc=%d\n", rc);
+ pr_err("Unable to read trigger name, rc=%d\n", rc);
return rc;
}
rc = of_property_read_u32(node, "qcom,led-mask", &snode->led_mask);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Unable to read led mask rc=%d\n", rc);
+ pr_err("Unable to read led mask rc=%d\n", rc);
return rc;
}
if (snode->led_mask < 1 || snode->led_mask > 7) {
- dev_err(&led->pdev->dev, "Invalid value for led-mask\n");
+ pr_err("Invalid value for led-mask\n");
return -EINVAL;
}
@@ -1476,8 +1560,7 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
if (IS_ERR_OR_NULL(snode->vreg)) {
rc = PTR_ERR(snode->vreg);
if (rc != -EPROBE_DEFER)
- dev_err(&led->pdev->dev, "Failed to get regulator, rc=%d\n",
- rc);
+ pr_err("Failed to get regulator, rc=%d\n", rc);
snode->vreg = NULL;
return rc;
}
@@ -1488,8 +1571,7 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
snode->cdev.brightness_get = qpnp_flash_led_brightness_get;
rc = led_classdev_register(&led->pdev->dev, &snode->cdev);
if (rc < 0) {
- dev_err(&led->pdev->dev,
- "Unable to register led switch node\n");
+ pr_err("Unable to register led switch node\n");
return rc;
}
@@ -1497,13 +1579,53 @@ static int qpnp_flash_led_parse_and_register_switch(struct qpnp_flash_led *led,
return 0;
}
+static int get_code_from_table(int *table, int len, int value)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (value == table[i])
+ break;
+ }
+
+ if (i == len) {
+ pr_err("Couldn't find %d from table\n", value);
+ return -ENODATA;
+ }
+
+ return i;
+}
+
static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
struct device_node *node)
{
+ struct device_node *revid_node;
int rc;
u32 val;
bool short_circuit_det, open_circuit_det, vph_droop_det;
+ revid_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
+ if (!revid_node) {
+ pr_err("Missing qcom,pmic-revid property - driver failed\n");
+ return -EINVAL;
+ }
+
+ led->pdata->pmic_rev_id = get_revid_data(revid_node);
+ if (IS_ERR_OR_NULL(led->pdata->pmic_rev_id)) {
+ pr_err("Unable to get pmic_revid rc=%ld\n",
+ PTR_ERR(led->pdata->pmic_rev_id));
+ /*
+ * the revid peripheral must be registered, any failure
+ * here only indicates that the rev-id module has not
+ * probed yet.
+ */
+ return -EPROBE_DEFER;
+ }
+
+ pr_debug("PMIC subtype %d Digital major %d\n",
+ led->pdata->pmic_rev_id->pmic_subtype,
+ led->pdata->pmic_rev_id->rev4);
+
led->pdata->hdrm_auto_mode_en = of_property_read_bool(node,
"qcom,hdrm-auto-mode");
@@ -1513,8 +1635,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
led->pdata->isc_delay =
val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read ISC delay, rc=%d\n", rc);
+ pr_err("Unable to read ISC delay, rc=%d\n", rc);
return rc;
}
@@ -1524,8 +1645,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
led->pdata->warmup_delay =
val >> FLASH_LED_ISC_WARMUP_DELAY_SHIFT;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read WARMUP delay, rc=%d\n", rc);
+ pr_err("Unable to read WARMUP delay, rc=%d\n", rc);
return rc;
}
@@ -1552,26 +1672,128 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
led->pdata->thermal_derate_current,
FLASH_LED_THERMAL_OTST_LEVELS);
if (rc < 0) {
- dev_err(&led->pdev->dev, "Unable to read thermal current limits, rc=%d\n",
- rc);
+ pr_err("Unable to read thermal current limits, rc=%d\n",
+ rc);
return rc;
}
}
+ led->pdata->otst_ramp_bkup_en =
+ !of_property_read_bool(node, "qcom,otst-ramp-back-up-dis");
+
+ led->pdata->thermal_derate_slow = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-derate-slow", &val);
+ if (!rc) {
+ if (val < 0 || val > THERMAL_DERATE_SLOW_MAX) {
+ pr_err("Invalid thermal_derate_slow %d\n", val);
+ return -EINVAL;
+ }
+
+ led->pdata->thermal_derate_slow =
+ get_code_from_table(thermal_derate_slow_table,
+ ARRAY_SIZE(thermal_derate_slow_table), val);
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal derate slow, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_derate_fast = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-derate-fast", &val);
+ if (!rc) {
+ if (val < 0 || val > THERMAL_DERATE_FAST_MAX) {
+ pr_err("Invalid thermal_derate_fast %d\n", val);
+ return -EINVAL;
+ }
+
+ led->pdata->thermal_derate_fast =
+ get_code_from_table(thermal_derate_fast_table,
+ ARRAY_SIZE(thermal_derate_fast_table), val);
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal derate fast, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_debounce = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-debounce", &val);
+ if (!rc) {
+ if (val < 0 || val > THERMAL_DEBOUNCE_TIME_MAX) {
+ pr_err("Invalid thermal_debounce %d\n", val);
+ return -EINVAL;
+ }
+
+ if (val >= 0 && val < 16)
+ led->pdata->thermal_debounce = 0;
+ else
+ led->pdata->thermal_debounce = ilog2(val) - 3;
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal debounce, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_hysteresis = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-hysteresis", &val);
+ if (!rc) {
+ if (led->pdata->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE)
+ val = THERMAL_HYST_TEMP_TO_VAL(val, 20);
+ else
+ val = THERMAL_HYST_TEMP_TO_VAL(val, 15);
+
+ if (val < 0 || val > THERMAL_DERATE_HYSTERESIS_MAX) {
+ pr_err("Invalid thermal_derate_hysteresis %d\n", val);
+ return -EINVAL;
+ }
+
+ led->pdata->thermal_hysteresis = val;
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal hysteresis, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_thrsh1 = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-thrsh1", &val);
+ if (!rc) {
+ led->pdata->thermal_thrsh1 =
+ get_code_from_table(otst1_threshold_table,
+ ARRAY_SIZE(otst1_threshold_table), val);
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal thrsh1, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_thrsh2 = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-thrsh2", &val);
+ if (!rc) {
+ led->pdata->thermal_thrsh2 =
+ get_code_from_table(otst2_threshold_table,
+ ARRAY_SIZE(otst2_threshold_table), val);
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal thrsh2, rc=%d\n", rc);
+ return rc;
+ }
+
+ led->pdata->thermal_thrsh3 = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,thermal-thrsh3", &val);
+ if (!rc) {
+ led->pdata->thermal_thrsh3 =
+ get_code_from_table(otst3_threshold_table,
+ ARRAY_SIZE(otst3_threshold_table), val);
+ } else if (rc != -EINVAL) {
+ pr_err("Unable to read thermal thrsh3, rc=%d\n", rc);
+ return rc;
+ }
+
led->pdata->vph_droop_debounce = FLASH_LED_VPH_DROOP_DEBOUNCE_DEFAULT;
rc = of_property_read_u32(node, "qcom,vph-droop-debounce-us", &val);
if (!rc) {
led->pdata->vph_droop_debounce =
VPH_DROOP_DEBOUNCE_US_TO_VAL(val);
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read VPH droop debounce, rc=%d\n", rc);
+ pr_err("Unable to read VPH droop debounce, rc=%d\n", rc);
return rc;
}
- if (led->pdata->vph_droop_debounce > FLASH_LED_VPH_DROOP_DEBOUNCE_MAX) {
- dev_err(&led->pdev->dev,
- "Invalid VPH droop debounce specified");
+ if (led->pdata->vph_droop_debounce > FLASH_LED_DEBOUNCE_MAX) {
+ pr_err("Invalid VPH droop debounce specified\n");
return -EINVAL;
}
@@ -1581,14 +1803,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
led->pdata->vph_droop_threshold =
VPH_DROOP_THRESH_MV_TO_VAL(val);
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read VPH droop threshold, rc=%d\n", rc);
+ pr_err("Unable to read VPH droop threshold, rc=%d\n", rc);
return rc;
}
if (led->pdata->vph_droop_threshold > FLASH_LED_VPH_DROOP_THRESH_MAX) {
- dev_err(&led->pdev->dev,
- "Invalid VPH droop threshold specified");
+ pr_err("Invalid VPH droop threshold specified\n");
return -EINVAL;
}
@@ -1599,23 +1819,22 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
led->pdata->vph_droop_hysteresis =
VPH_DROOP_HYST_MV_TO_VAL(val);
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to read VPH droop hysteresis, rc=%d\n", rc);
+ pr_err("Unable to read VPH droop hysteresis, rc=%d\n", rc);
return rc;
}
- if (led->pdata->vph_droop_hysteresis > FLASH_LED_VPH_DROOP_HYST_MAX) {
- dev_err(&led->pdev->dev,
- "Invalid VPH droop hysteresis specified");
+ if (led->pdata->vph_droop_hysteresis > FLASH_LED_HYSTERESIS_MAX) {
+ pr_err("Invalid VPH droop hysteresis specified\n");
return -EINVAL;
}
+ led->pdata->vph_droop_hysteresis <<= FLASH_LED_VPH_DROOP_HYST_SHIFT;
+
rc = of_property_read_u32(node, "qcom,hw-strobe-option", &val);
if (!rc) {
led->pdata->hw_strobe_option = (u8)val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev,
- "Unable to parse hw strobe option, rc=%d\n", rc);
+ pr_err("Unable to parse hw strobe option, rc=%d\n", rc);
return rc;
}
@@ -1623,8 +1842,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->led1n2_iclamp_low_ma = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_low current, rc=%d\n",
- rc);
+ pr_err("Unable to read led1n2_iclamp_low current, rc=%d\n", rc);
return rc;
}
@@ -1632,8 +1850,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->led1n2_iclamp_mid_ma = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read led1n2_iclamp_mid current, rc=%d\n",
- rc);
+ pr_err("Unable to read led1n2_iclamp_mid current, rc=%d\n", rc);
return rc;
}
@@ -1641,8 +1858,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->led3_iclamp_low_ma = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read led3_iclamp_low current, rc=%d\n",
- rc);
+ pr_err("Unable to read led3_iclamp_low current, rc=%d\n", rc);
return rc;
}
@@ -1650,8 +1866,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->led3_iclamp_mid_ma = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to read led3_iclamp_mid current, rc=%d\n",
- rc);
+ pr_err("Unable to read led3_iclamp_mid current, rc=%d\n", rc);
return rc;
}
@@ -1660,8 +1875,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->vled_max_uv = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse vled_max voltage, rc=%d\n",
- rc);
+ pr_err("Unable to parse vled_max voltage, rc=%d\n", rc);
return rc;
}
@@ -1671,8 +1885,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->ibatt_ocp_threshold_ua = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse ibatt_ocp threshold, rc=%d\n",
- rc);
+ pr_err("Unable to parse ibatt_ocp threshold, rc=%d\n", rc);
return rc;
}
@@ -1681,8 +1894,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->rpara_uohm = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse rparasitic, rc=%d\n",
- rc);
+ pr_err("Unable to parse rparasitic, rc=%d\n", rc);
return rc;
}
@@ -1692,8 +1904,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->lmh_ocv_threshold_uv = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse lmh ocv threshold, rc=%d\n",
- rc);
+ pr_err("Unable to parse lmh ocv threshold, rc=%d\n", rc);
return rc;
}
@@ -1703,8 +1914,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->lmh_rbatt_threshold_uohm = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse lmh rbatt threshold, rc=%d\n",
- rc);
+ pr_err("Unable to parse lmh rbatt threshold, rc=%d\n", rc);
return rc;
}
@@ -1713,8 +1923,7 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->lmh_level = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse lmh_level, rc=%d\n",
- rc);
+ pr_err("Unable to parse lmh_level, rc=%d\n", rc);
return rc;
}
@@ -1723,13 +1932,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->lmh_mitigation_sel = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse lmh_mitigation_sel, rc=%d\n",
- rc);
+ pr_err("Unable to parse lmh_mitigation_sel, rc=%d\n", rc);
return rc;
}
if (led->pdata->lmh_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
- dev_err(&led->pdev->dev, "Invalid lmh_mitigation_sel specified\n");
+ pr_err("Invalid lmh_mitigation_sel specified\n");
return -EINVAL;
}
@@ -1738,13 +1946,12 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->chgr_mitigation_sel = val;
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse chgr_mitigation_sel, rc=%d\n",
- rc);
+ pr_err("Unable to parse chgr_mitigation_sel, rc=%d\n", rc);
return rc;
}
if (led->pdata->chgr_mitigation_sel > FLASH_LED_MITIGATION_SEL_MAX) {
- dev_err(&led->pdev->dev, "Invalid chgr_mitigation_sel specified\n");
+ pr_err("Invalid chgr_mitigation_sel specified\n");
return -EINVAL;
}
@@ -1755,30 +1962,29 @@ static int qpnp_flash_led_parse_common_dt(struct qpnp_flash_led *led,
if (!rc) {
led->pdata->iled_thrsh_val = MITIGATION_THRSH_MA_TO_VAL(val);
} else if (rc != -EINVAL) {
- dev_err(&led->pdev->dev, "Unable to parse iled_thrsh_val, rc=%d\n",
- rc);
+ pr_err("Unable to parse iled_thrsh_val, rc=%d\n", rc);
return rc;
}
if (led->pdata->iled_thrsh_val > FLASH_LED_MITIGATION_THRSH_MAX) {
- dev_err(&led->pdev->dev, "Invalid iled_thrsh_val specified\n");
+ pr_err("Invalid iled_thrsh_val specified\n");
return -EINVAL;
}
led->pdata->all_ramp_up_done_irq =
of_irq_get_byname(node, "all-ramp-up-done-irq");
if (led->pdata->all_ramp_up_done_irq < 0)
- dev_dbg(&led->pdev->dev, "all-ramp-up-done-irq not used\n");
+ pr_debug("all-ramp-up-done-irq not used\n");
led->pdata->all_ramp_down_done_irq =
of_irq_get_byname(node, "all-ramp-down-done-irq");
if (led->pdata->all_ramp_down_done_irq < 0)
- dev_dbg(&led->pdev->dev, "all-ramp-down-done-irq not used\n");
+ pr_debug("all-ramp-down-done-irq not used\n");
led->pdata->led_fault_irq =
of_irq_get_byname(node, "led-fault-irq");
if (led->pdata->led_fault_irq < 0)
- dev_dbg(&led->pdev->dev, "led-fault-irq not used\n");
+ pr_debug("led-fault-irq not used\n");
return 0;
}
@@ -1793,14 +1999,14 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
node = pdev->dev.of_node;
if (!node) {
- dev_info(&pdev->dev, "No flash LED nodes defined\n");
+ pr_err("No flash LED nodes defined\n");
return -ENODEV;
}
rc = of_property_read_u32(node, "reg", &base);
if (rc < 0) {
- dev_err(&pdev->dev, "Couldn't find reg in node %s, rc = %d\n",
- node->full_name, rc);
+ pr_err("Couldn't find reg in node %s, rc = %d\n",
+ node->full_name, rc);
return rc;
}
@@ -1811,7 +2017,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
led->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!led->regmap) {
- dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+ pr_err("Couldn't get parent's regmap\n");
return -EINVAL;
}
@@ -1824,16 +2030,14 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
rc = qpnp_flash_led_parse_common_dt(led, node);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Failed to parse common flash LED device tree\n");
+ pr_err("Failed to parse common flash LED device tree\n");
return rc;
}
for_each_available_child_of_node(node, temp) {
rc = of_property_read_string(temp, "label", &temp_string);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Failed to parse label, rc=%d\n", rc);
+ pr_err("Failed to parse label, rc=%d\n", rc);
return rc;
}
@@ -1843,14 +2047,13 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
!strcmp("torch", temp_string)) {
led->num_fnodes++;
} else {
- dev_err(&pdev->dev,
- "Invalid label for led node\n");
+ pr_err("Invalid label for led node\n");
return -EINVAL;
}
}
if (!led->num_fnodes) {
- dev_err(&pdev->dev, "No LED nodes defined\n");
+ pr_err("No LED nodes defined\n");
return -ECHILD;
}
@@ -1872,8 +2075,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
for_each_available_child_of_node(node, temp) {
rc = of_property_read_string(temp, "label", &temp_string);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Failed to parse label, rc=%d\n", rc);
+ pr_err("Failed to parse label, rc=%d\n", rc);
return rc;
}
@@ -1882,7 +2084,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
rc = qpnp_flash_led_parse_each_led_dt(led,
&led->fnode[i++], temp);
if (rc < 0) {
- dev_err(&pdev->dev, "Unable to parse flash node %d rc=%d\n",
+ pr_err("Unable to parse flash node %d rc=%d\n",
i, rc);
goto error_led_register;
}
@@ -1892,7 +2094,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
rc = qpnp_flash_led_parse_and_register_switch(led,
&led->snode[j++], temp);
if (rc < 0) {
- dev_err(&pdev->dev, "Unable to parse and register switch node, rc=%d\n",
+ pr_err("Unable to parse and register switch node, rc=%d\n",
rc);
goto error_switch_register;
}
@@ -1907,8 +2109,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
IRQF_ONESHOT,
"qpnp_flash_led_all_ramp_up_done_irq", led);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
+ pr_err("Unable to request all_ramp_up_done(%d) IRQ(err:%d)\n",
led->pdata->all_ramp_up_done_irq, rc);
goto error_switch_register;
}
@@ -1921,8 +2122,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
IRQF_ONESHOT,
"qpnp_flash_led_all_ramp_down_done_irq", led);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
+ pr_err("Unable to request all_ramp_down_done(%d) IRQ(err:%d)\n",
led->pdata->all_ramp_down_done_irq, rc);
goto error_switch_register;
}
@@ -1935,8 +2135,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
IRQF_ONESHOT,
"qpnp_flash_led_fault_irq", led);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Unable to request led_fault(%d) IRQ(err:%d)\n",
+ pr_err("Unable to request led_fault(%d) IRQ(err:%d)\n",
led->pdata->led_fault_irq, rc);
goto error_switch_register;
}
@@ -1946,16 +2145,14 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
if (!led->bms_psy) {
rc = flash_led_psy_register_notifier(led);
if (rc < 0) {
- dev_err(&pdev->dev, "Couldn't register psy notifier, rc = %d\n",
- rc);
+ pr_err("Couldn't register psy notifier, rc = %d\n", rc);
goto error_switch_register;
}
}
rc = qpnp_flash_led_init_settings(led);
if (rc < 0) {
- dev_err(&pdev->dev,
- "Failed to initialize flash LED, rc=%d\n", rc);
+ pr_err("Failed to initialize flash LED, rc=%d\n", rc);
goto unreg_notifier;
}
@@ -1964,8 +2161,7 @@ static int qpnp_flash_led_probe(struct platform_device *pdev)
rc = sysfs_create_file(&led->snode[i].cdev.dev->kobj,
&qpnp_flash_led_attrs[j].attr);
if (rc < 0) {
- dev_err(&pdev->dev, "sysfs creation failed, rc=%d\n",
- rc);
+ pr_err("sysfs creation failed, rc=%d\n", rc);
goto sysfs_fail;
}
}
diff --git a/drivers/leds/leds-qpnp-flash.c b/drivers/leds/leds-qpnp-flash.c
index 95b4c42a5adb..98dfa56add51 100644
--- a/drivers/leds/leds-qpnp-flash.c
+++ b/drivers/leds/leds-qpnp-flash.c
@@ -82,7 +82,6 @@
#define FLASH_LED_HDRM_SNS_ENABLE_MASK 0x81
#define FLASH_MASK_MODULE_CONTRL_MASK 0xE0
#define FLASH_FOLLOW_OTST2_RB_MASK 0x08
-#define FLASH_PREPARE_OPTIONS_MASK 0x08
#define FLASH_LED_TRIGGER_DEFAULT "none"
#define FLASH_LED_HEADROOM_DEFAULT_MV 500
@@ -1172,7 +1171,7 @@ int qpnp_flash_led_prepare(struct led_trigger *trig, int options,
flash_node = container_of(led_cdev, struct flash_node_data, cdev);
led = dev_get_drvdata(&flash_node->pdev->dev);
- if (!(options & FLASH_PREPARE_OPTIONS_MASK)) {
+ if (!(options & FLASH_LED_PREPARE_OPTIONS_MASK)) {
dev_err(&led->pdev->dev, "Invalid options %d\n", options);
return -EINVAL;
}
diff --git a/drivers/leds/leds-qpnp-wled.c b/drivers/leds/leds-qpnp-wled.c
index 97cfa813f4ce..79c54edefdc5 100644
--- a/drivers/leds/leds-qpnp-wled.c
+++ b/drivers/leds/leds-qpnp-wled.c
@@ -50,6 +50,7 @@
#define QPNP_WLED_VLOOP_COMP_RES_REG(b) (b + 0x55)
#define QPNP_WLED_VLOOP_COMP_GM_REG(b) (b + 0x56)
#define QPNP_WLED_PSM_CTRL_REG(b) (b + 0x5B)
+#define QPNP_WLED_LCD_AUTO_PFM_REG(b) (b + 0x5C)
#define QPNP_WLED_SC_PRO_REG(b) (b + 0x5E)
#define QPNP_WLED_SWIRE_AVDD_REG(b) (b + 0x5F)
#define QPNP_WLED_CTRL_SPARE_REG(b) (b + 0xDF)
@@ -69,17 +70,29 @@
#define QPNP_WLED_LOOP_COMP_RES_STEP_KOHM 20
#define QPNP_WLED_LOOP_COMP_RES_MIN_KOHM 20
#define QPNP_WLED_LOOP_COMP_RES_MAX_KOHM 320
-#define QPNP_WLED_VLOOP_COMP_GM_MASK 0xF0
+#define QPNP_WLED_VLOOP_COMP_GM_MASK GENMASK(3, 0)
#define QPNP_WLED_VLOOP_COMP_GM_OVERWRITE 0x80
-#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED 0x03
+#define QPNP_WLED_VLOOP_COMP_AUTO_GM_EN BIT(6)
+#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK GENMASK(5, 4)
+#define QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT 4
+#define QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994 0x03
+#define QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT 0x09
+#define QPNP_WLED_LOOP_GM_DFLT_WLED 0x09
#define QPNP_WLED_LOOP_EA_GM_MIN 0x0
#define QPNP_WLED_LOOP_EA_GM_MAX 0xF
+#define QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX 3
+#define QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH 1
#define QPNP_WLED_VREF_PSM_MASK 0xF8
#define QPNP_WLED_VREF_PSM_STEP_MV 50
#define QPNP_WLED_VREF_PSM_MIN_MV 400
#define QPNP_WLED_VREF_PSM_MAX_MV 750
#define QPNP_WLED_VREF_PSM_DFLT_AMOLED_MV 450
#define QPNP_WLED_PSM_CTRL_OVERWRITE 0x80
+#define QPNP_WLED_LCD_AUTO_PFM_DFLT_THRESH 1
+#define QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX 0xF
+#define QPNP_WLED_LCD_AUTO_PFM_EN_SHIFT 7
+#define QPNP_WLED_LCD_AUTO_PFM_EN_BIT BIT(7)
+#define QPNP_WLED_LCD_AUTO_PFM_THRESH_MASK GENMASK(3, 0)
#define QPNP_WLED_ILIM_MASK GENMASK(2, 0)
#define QPNP_WLED_ILIM_OVERWRITE BIT(7)
@@ -319,6 +332,10 @@ static struct wled_vref_setting vref_setting_pmicobalt = {
* @ cons_sync_write_delay_us - delay between two consecutive writes to SYNC
* @ strings - supported list of strings
* @ num_strings - number of strings
+ * @ loop_auto_gm_thresh - the clamping level for auto gm
+ * @ lcd_auto_pfm_thresh - the threshold for lcd auto pfm mode
+ * @ loop_auto_gm_en - select if auto gm is enabled
+ * @ lcd_auto_pfm_en - select if auto pfm is enabled in lcd mode
* @ avdd_mode_spmi - enable avdd programming via spmi
* @ en_9b_dim_res - enable or disable 9bit dimming
* @ en_phase_stag - enable or disable phase staggering
@@ -362,6 +379,10 @@ struct qpnp_wled {
u16 cons_sync_write_delay_us;
u8 strings[QPNP_WLED_MAX_STRINGS];
u8 num_strings;
+ u8 loop_auto_gm_thresh;
+ u8 lcd_auto_pfm_thresh;
+ bool loop_auto_gm_en;
+ bool lcd_auto_pfm_en;
bool avdd_mode_spmi;
bool en_9b_dim_res;
bool en_phase_stag;
@@ -987,24 +1008,6 @@ static int qpnp_wled_set_disp(struct qpnp_wled *wled, u16 base_addr)
if (rc)
return rc;
- /* Configure the LOOP COMP GM register for AMOLED */
- if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
- wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
- else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
- wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;
-
- rc = qpnp_wled_read_reg(wled, &reg,
- QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
- if (rc < 0)
- return rc;
-
- reg &= QPNP_WLED_VLOOP_COMP_GM_MASK;
- reg |= (wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE);
- rc = qpnp_wled_write_reg(wled, reg,
- QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
- if (rc)
- return rc;
-
/* Configure the CTRL TEST4 register for AMOLED */
rc = qpnp_wled_read_reg(wled, &reg,
QPNP_WLED_TEST4_REG(wled->ctrl_base));
@@ -1084,6 +1087,45 @@ static bool is_avdd_trim_adjustment_required(struct qpnp_wled *wled)
return !(reg & QPNP_WLED_AVDD_SET_BIT);
}
+static int qpnp_wled_gm_config(struct qpnp_wled *wled)
+{
+ int rc;
+ u8 mask = 0, reg = 0;
+
+ /* Configure the LOOP COMP GM register */
+ if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
+ wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
+ if (wled->loop_auto_gm_en)
+ reg |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN;
+
+ if (wled->loop_auto_gm_thresh >
+ QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX)
+ wled->loop_auto_gm_thresh =
+ QPNP_WLED_LOOP_AUTO_GM_THRESH_MAX;
+
+ reg |= wled->loop_auto_gm_thresh <<
+ QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_SHIFT;
+ mask |= QPNP_WLED_VLOOP_COMP_AUTO_GM_EN |
+ QPNP_WLED_VLOOP_COMP_AUTO_GM_THRESH_MASK;
+ }
+
+ if (wled->loop_ea_gm < QPNP_WLED_LOOP_EA_GM_MIN)
+ wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MIN;
+ else if (wled->loop_ea_gm > QPNP_WLED_LOOP_EA_GM_MAX)
+ wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_MAX;
+
+ reg |= wled->loop_ea_gm | QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
+ mask |= QPNP_WLED_VLOOP_COMP_GM_MASK |
+ QPNP_WLED_VLOOP_COMP_GM_OVERWRITE;
+
+ rc = qpnp_wled_masked_write_reg(wled, mask, &reg,
+ QPNP_WLED_VLOOP_COMP_GM_REG(wled->ctrl_base));
+ if (rc)
+ pr_err("write VLOOP_COMP_GM_REG failed, rc=%d]\n", rc);
+
+ return rc;
+}
+
static int qpnp_wled_ovp_config(struct qpnp_wled *wled)
{
int rc, i, *ovp_table;
@@ -1317,6 +1359,13 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
return rc;
}
+ /* Configure VLOOP_COMP_GM register */
+ rc = qpnp_wled_gm_config(wled);
+ if (rc < 0) {
+ pr_err("Error in configureing wled gm, rc=%d\n", rc);
+ return rc;
+ }
+
/* Configure the ILIM register */
rc = qpnp_wled_ilim_config(wled);
if (rc < 0) {
@@ -1324,6 +1373,24 @@ static int qpnp_wled_config(struct qpnp_wled *wled)
return rc;
}
+ /* Configure auto PFM mode for LCD mode only */
+ if ((wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
+ wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE)
+ && !wled->disp_type_amoled) {
+ reg = 0;
+ reg |= wled->lcd_auto_pfm_thresh;
+ reg |= wled->lcd_auto_pfm_en <<
+ QPNP_WLED_LCD_AUTO_PFM_EN_SHIFT;
+ rc = qpnp_wled_masked_write_reg(wled,
+ QPNP_WLED_LCD_AUTO_PFM_EN_BIT |
+ QPNP_WLED_LCD_AUTO_PFM_THRESH_MASK, &reg,
+ QPNP_WLED_LCD_AUTO_PFM_REG(wled->ctrl_base));
+ if (rc < 0) {
+ pr_err("Write LCD_AUTO_PFM failed, rc=%d\n", rc);
+ return rc;
+ }
+ }
+
/* Configure the Soft start Ramp delay: for AMOLED - 0,for LCD - 2 */
reg = (wled->disp_type_amoled) ? 0 : 2;
rc = qpnp_wled_write_reg(wled, reg,
@@ -1689,16 +1756,6 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
return rc;
}
- wled->loop_ea_gm = QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED;
- rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,loop-ea-gm", &temp_val);
- if (!rc) {
- wled->loop_ea_gm = temp_val;
- } else if (rc != -EINVAL) {
- dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
- return rc;
- }
-
wled->avdd_mode_spmi = of_property_read_bool(pdev->dev.of_node,
"qcom,avdd-mode-spmi");
@@ -1713,6 +1770,67 @@ static int qpnp_wled_parse_dt(struct qpnp_wled *wled)
}
}
+ if (wled->disp_type_amoled) {
+ if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
+ wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE)
+ wled->loop_ea_gm =
+ QPNP_WLED_LOOP_GM_DFLT_AMOLED_PMICOBALT;
+ else
+ wled->loop_ea_gm =
+ QPNP_WLED_LOOP_EA_GM_DFLT_AMOLED_PMI8994;
+ } else {
+ wled->loop_ea_gm = QPNP_WLED_LOOP_GM_DFLT_WLED;
+ }
+
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,loop-ea-gm", &temp_val);
+ if (!rc) {
+ wled->loop_ea_gm = temp_val;
+ } else if (rc != -EINVAL) {
+ dev_err(&pdev->dev, "Unable to read loop-ea-gm\n");
+ return rc;
+ }
+
+ if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
+ wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
+ wled->loop_auto_gm_en =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,loop-auto-gm-en");
+ wled->loop_auto_gm_thresh = QPNP_WLED_LOOP_AUTO_GM_DFLT_THRESH;
+ rc = of_property_read_u8(pdev->dev.of_node,
+ "qcom,loop-auto-gm-thresh",
+ &wled->loop_auto_gm_thresh);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pdev->dev,
+ "Unable to read loop-auto-gm-thresh\n");
+ return rc;
+ }
+ }
+
+ if (wled->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE ||
+ wled->pmic_rev_id->pmic_subtype == PM2FALCON_SUBTYPE) {
+
+ if (wled->pmic_rev_id->rev4 == PMICOBALT_V2P0_REV4)
+ wled->lcd_auto_pfm_en = false;
+ else
+ wled->lcd_auto_pfm_en = true;
+
+ wled->lcd_auto_pfm_thresh = QPNP_WLED_LCD_AUTO_PFM_DFLT_THRESH;
+ rc = of_property_read_u8(pdev->dev.of_node,
+ "qcom,lcd-auto-pfm-thresh",
+ &wled->lcd_auto_pfm_thresh);
+ if (rc && rc != -EINVAL) {
+ dev_err(&pdev->dev,
+ "Unable to read lcd-auto-pfm-thresh\n");
+ return rc;
+ }
+
+ if (wled->lcd_auto_pfm_thresh >
+ QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX)
+ wled->lcd_auto_pfm_thresh =
+ QPNP_WLED_LCD_AUTO_PFM_THRESH_MAX;
+ }
+
wled->sc_deb_cycles = QPNP_WLED_SC_DEB_CYCLES_DFLT;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,sc-deb-cycles", &temp_val);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7dc7271b05c1..457629ee4bf5 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -8125,11 +8125,12 @@ static int qseecom_check_whitelist_feature(void)
static int qseecom_probe(struct platform_device *pdev)
{
int rc;
- int ret = 0;
+ int i;
uint32_t feature = 10;
struct device *class_dev;
struct msm_bus_scale_pdata *qseecom_platform_support = NULL;
struct qseecom_command_scm_resp resp;
+ struct qseecom_ce_info_use *pce_info_use = NULL;
qseecom.qsee_bw_count = 0;
qseecom.qsee_perf_client = 0;
@@ -8171,7 +8172,7 @@ static int qseecom_probe(struct platform_device *pdev)
class_dev = device_create(driver_class, NULL, qseecom_device_no, NULL,
QSEECOM_DEV);
- if (!class_dev) {
+ if (IS_ERR(class_dev)) {
pr_err("class_device_create failed %d\n", rc);
rc = -ENOMEM;
goto exit_destroy_class;
@@ -8210,7 +8211,7 @@ static int qseecom_probe(struct platform_device *pdev)
qseecom.pdev = class_dev;
/* Create ION msm client */
qseecom.ion_clnt = msm_ion_client_create("qseecom-kernel");
- if (qseecom.ion_clnt == NULL) {
+ if (IS_ERR_OR_NULL(qseecom.ion_clnt)) {
pr_err("Ion client cannot be created\n");
rc = -ENOMEM;
goto exit_del_cdev;
@@ -8272,14 +8273,14 @@ static int qseecom_probe(struct platform_device *pdev)
pr_debug("CE operating frequency is not defined, setting to default 100MHZ\n");
qseecom.ce_opp_freq_hz = QSEE_CE_CLK_100MHZ;
}
- ret = __qseecom_init_clk(CLK_QSEE);
- if (ret)
+ rc = __qseecom_init_clk(CLK_QSEE);
+ if (rc)
goto exit_destroy_ion_client;
if ((qseecom.qsee.instance != qseecom.ce_drv.instance) &&
(qseecom.support_pfe || qseecom.support_fde)) {
- ret = __qseecom_init_clk(CLK_CE_DRV);
- if (ret) {
+ rc = __qseecom_init_clk(CLK_CE_DRV);
+ if (rc) {
__qseecom_deinit_clk(CLK_QSEE);
goto exit_destroy_ion_client;
}
@@ -8333,9 +8334,14 @@ static int qseecom_probe(struct platform_device *pdev)
} else {
pr_err("Fail to get secure app region info\n");
rc = -EINVAL;
- goto exit_destroy_ion_client;
+ goto exit_deinit_clock;
+ }
+ rc = __qseecom_enable_clk(CLK_QSEE);
+ if (rc) {
+ pr_err("CLK_QSEE enabling failed (%d)\n", rc);
+ rc = -EIO;
+ goto exit_deinit_clock;
}
- __qseecom_enable_clk(CLK_QSEE);
rc = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
cmd_buf, cmd_len,
&resp, sizeof(resp));
@@ -8344,7 +8350,7 @@ static int qseecom_probe(struct platform_device *pdev)
pr_err("send secapp reg fail %d resp.res %d\n",
rc, resp.result);
rc = -EINVAL;
- goto exit_destroy_ion_client;
+ goto exit_deinit_clock;
}
}
/*
@@ -8380,7 +8386,28 @@ static int qseecom_probe(struct platform_device *pdev)
atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_READY);
return 0;
+exit_deinit_clock:
+ __qseecom_deinit_clk(CLK_QSEE);
+ if ((qseecom.qsee.instance != qseecom.ce_drv.instance) &&
+ (qseecom.support_pfe || qseecom.support_fde))
+ __qseecom_deinit_clk(CLK_CE_DRV);
exit_destroy_ion_client:
+ if (qseecom.ce_info.fde) {
+ pce_info_use = qseecom.ce_info.fde;
+ for (i = 0; i < qseecom.ce_info.num_fde; i++) {
+ kzfree(pce_info_use->ce_pipe_entry);
+ pce_info_use++;
+ }
+ kfree(qseecom.ce_info.fde);
+ }
+ if (qseecom.ce_info.pfe) {
+ pce_info_use = qseecom.ce_info.pfe;
+ for (i = 0; i < qseecom.ce_info.num_pfe; i++) {
+ kzfree(pce_info_use->ce_pipe_entry);
+ pce_info_use++;
+ }
+ kfree(qseecom.ce_info.pfe);
+ }
ion_client_destroy(qseecom.ion_clnt);
exit_del_cdev:
cdev_del(&qseecom.cdev);
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.h b/drivers/phy/phy-qcom-ufs-qmp-v3.h
index 8b1e03eab639..d5e49c281278 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.h
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.h
@@ -225,22 +225,22 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A_3_0_0[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL1, 0xFF),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE0, 0x82),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x06),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE0, 0x08),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x36),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE0, 0x34),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x3F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0xDA),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE0, 0xCB),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE0, 0x01),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE0, 0xFF),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE0, 0x0C),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_DEC_START_MODE1, 0x98),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x06),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_CP_CTRL_MODE1, 0x08),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_RCTRL_MODE1, 0x16),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x36),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_PLL_CCTRL_MODE1, 0x34),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x3F),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00),
- UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xC1),
+ UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE1_MODE1, 0xB2),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_VCO_TUNE2_MODE1, 0x00),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP1_MODE1, 0x32),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_COM_LOCK_CMP2_MODE1, 0x0F),
diff --git a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
index 3678f952fe0f..91bbce2ce1d1 100644
--- a/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
+++ b/drivers/pinctrl/qcom/pinctrl-msmfalcon.c
@@ -748,10 +748,10 @@ static const char * const blsp_i2c5_groups[] = {
"gpio18", "gpio19",
};
static const char * const blsp_spi6_groups[] = {
- "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio49", "gpio52", "gpio22", "gpio23",
};
static const char * const blsp_uart2_groups[] = {
- "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio4", "gpio5", "gpio6", "gpio7",
};
static const char * const blsp_uim6_groups[] = {
"gpio20", "gpio21",
@@ -1495,13 +1495,14 @@ static const struct msm_pingroup msmfalcon_groups[] = {
NA, NA),
PINGROUP(3, SOUTH, blsp_spi1, blsp_uart1, blsp_i2c1, ddr_bist, NA, NA,
atest_tsens2, atest_usb1, NA),
- PINGROUP(4, NORTH, blsp_spi2, blsp_uim2, NA, phase_flag3, NA, NA, NA,
- NA, NA),
- PINGROUP(5, SOUTH, blsp_spi2, blsp_uim2, NA, phase_flag14, NA, NA, NA,
- NA, NA),
- PINGROUP(6, SOUTH, blsp_spi2, blsp_i2c2, NA, phase_flag31, NA, NA, NA,
+ PINGROUP(4, NORTH, blsp_spi2, blsp_uim2, blsp_uart2, phase_flag3, NA,
+ NA, NA, NA, NA),
+ PINGROUP(5, SOUTH, blsp_spi2, blsp_uim2, blsp_uart2, phase_flag14, NA,
+ NA, NA, NA, NA),
+ PINGROUP(6, SOUTH, blsp_spi2, blsp_i2c2, blsp_uart2, phase_flag31, NA,
+ NA, NA, NA, NA),
+ PINGROUP(7, SOUTH, blsp_spi2, blsp_i2c2, blsp_uart2, NA, NA, NA, NA,
NA, NA),
- PINGROUP(7, SOUTH, blsp_spi2, blsp_i2c2, NA, NA, NA, NA, NA, NA, NA),
PINGROUP(8, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc1,
atest_usb13, bimc_dte1, NA),
PINGROUP(9, NORTH, blsp_spi3, ddr_bist, NA, NA, NA, wlan1_adc0,
@@ -1526,13 +1527,13 @@ static const struct msm_pingroup msmfalcon_groups[] = {
NA, NA),
PINGROUP(19, CENTER, blsp_uart5, blsp_spi5, blsp_i2c5, NA, NA, NA, NA,
NA, NA),
- PINGROUP(20, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, NA, NA, NA,
+ PINGROUP(20, SOUTH, NA, NA, blsp_uim6, NA, NA, NA, NA,
NA, NA),
- PINGROUP(21, SOUTH, blsp_spi6, blsp_uart2, blsp_uim6, NA, phase_flag11,
+ PINGROUP(21, SOUTH, NA, NA, blsp_uim6, NA, phase_flag11,
qdss_cti0_b, vsense_data0, NA, NA),
- PINGROUP(22, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
+ PINGROUP(22, CENTER, blsp_spi6, NA, blsp_i2c6, NA,
phase_flag12, vsense_data1, NA, NA, NA),
- PINGROUP(23, CENTER, blsp_spi6, blsp_uart2, blsp_i2c6, NA,
+ PINGROUP(23, CENTER, blsp_spi6, NA, blsp_i2c6, NA,
phase_flag13, vsense_mode, NA, NA, NA),
PINGROUP(24, NORTH, blsp_spi7, blsp_uart6_a, sec_mi2s, sndwire_clk, NA,
NA, phase_flag17, vsense_clkout, NA),
@@ -1580,13 +1581,13 @@ static const struct msm_pingroup msmfalcon_groups[] = {
NA, NA, NA),
PINGROUP(48, SOUTH, NA, phase_flag1, qdss_gpio15, NA, NA, NA, NA, NA,
NA),
- PINGROUP(49, SOUTH, NA, phase_flag2, qdss_cti0_a, NA, NA, NA, NA, NA,
- NA),
+ PINGROUP(49, SOUTH, blsp_spi6, phase_flag2, qdss_cti0_a, NA, NA, NA,
+ NA, NA, NA),
PINGROUP(50, SOUTH, qspi_cs, NA, phase_flag9, qdss_cti0_a, NA, NA, NA,
NA, NA),
PINGROUP(51, SOUTH, qspi_data3, NA, phase_flag15, qdss_gpio8, NA, NA,
NA, NA, NA),
- PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi8_b, blsp_i2c8_b, NA,
+ PINGROUP(52, SOUTH, CCI_TIMER2, blsp_spi8_b, blsp_i2c8_b, blsp_spi6,
phase_flag16, qdss_gpio, NA, NA, NA),
PINGROUP(53, NORTH, NA, phase_flag6, qdss_cti1_a, NA, NA, NA, NA, NA,
NA),
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 4b0cd46082a3..be2946c873b3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -1723,6 +1723,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
struct ipa3_sys_context *sys;
int src_ep_idx;
int num_frags, f;
+ struct ipa_gsi_ep_config *gsi_ep;
if (unlikely(!ipa3_ctx)) {
IPAERR("IPA3 driver was not initialized\n");
@@ -1734,23 +1735,6 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
return -EINVAL;
}
- num_frags = skb_shinfo(skb)->nr_frags;
- if (num_frags) {
- /* 1 desc for tag to resolve status out-of-order issue;
- * 1 desc is needed for the linear portion of skb;
- * 1 desc may be needed for the PACKET_INIT;
- * 1 desc for each frag
- */
- desc = kzalloc(sizeof(*desc) * (num_frags + 3), GFP_ATOMIC);
- if (!desc) {
- IPAERR("failed to alloc desc array\n");
- goto fail_mem;
- }
- } else {
- memset(_desc, 0, 3 * sizeof(struct ipa3_desc));
- desc = &_desc[0];
- }
-
/*
* USB_CONS: PKT_INIT ep_idx = dst pipe
* Q6_CONS: PKT_INIT ep_idx = sender pipe
@@ -1787,6 +1771,37 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
goto fail_gen;
}
+ num_frags = skb_shinfo(skb)->nr_frags;
+ /*
+ * make sure TLV FIFO supports the needed frags.
+ * 2 descriptors are needed for IP_PACKET_INIT and TAG_STATUS.
+ * 1 descriptor needed for the linear portion of skb.
+ */
+ gsi_ep = ipa3_get_gsi_ep_info(src_ep_idx);
+ if (gsi_ep && (num_frags + 3 > gsi_ep->ipa_if_tlv)) {
+ if (skb_linearize(skb)) {
+ IPAERR("Failed to linear skb with %d frags\n",
+ num_frags);
+ goto fail_gen;
+ }
+ num_frags = 0;
+ }
+ if (num_frags) {
+ /* 1 desc for tag to resolve status out-of-order issue;
+ * 1 desc is needed for the linear portion of skb;
+ * 1 desc may be needed for the PACKET_INIT;
+ * 1 desc for each frag
+ */
+ desc = kzalloc(sizeof(*desc) * (num_frags + 3), GFP_ATOMIC);
+ if (!desc) {
+ IPAERR("failed to alloc desc array\n");
+ goto fail_gen;
+ }
+ } else {
+ memset(_desc, 0, 3 * sizeof(struct ipa3_desc));
+ desc = &_desc[0];
+ }
+
if (dst_ep_idx != -1) {
/* SW data path */
cmd.destination_pipe_index = dst_ep_idx;
@@ -1794,7 +1809,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
IPA_IMM_CMD_IP_PACKET_INIT, &cmd, true);
if (unlikely(!cmd_pyld)) {
IPAERR("failed to construct ip_packet_init imm cmd\n");
- goto fail_gen;
+ goto fail_mem;
}
/* the tag field will be populated in ipa3_send() function */
@@ -1863,7 +1878,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
if (num_frags == 0) {
if (ipa3_send(sys, 2, desc, true)) {
IPAERR("fail to send skb %p HWP\n", skb);
- goto fail_gen;
+ goto fail_mem;
}
} else {
for (f = 0; f < num_frags; f++) {
@@ -1880,7 +1895,7 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
if (ipa3_send(sys, num_frags + 2, desc, true)) {
IPAERR("fail to send skb %p num_frags %u HWP\n",
skb, num_frags);
- goto fail_gen;
+ goto fail_mem;
}
}
IPA_STATS_INC_CNT(ipa3_ctx->stats.tx_hw_pkts);
@@ -1894,10 +1909,10 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
fail_send:
ipahal_destroy_imm_cmd(cmd_pyld);
-fail_gen:
+fail_mem:
if (num_frags)
kfree(desc);
-fail_mem:
+fail_gen:
return -EFAULT;
}
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 6968ab2ab11c..8248fcee341d 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -1069,6 +1069,7 @@ static int smb2_init_hw(struct smb2 *chip)
&chip->dt.dc_icl_ua);
chg->otg_cl_ua = chip->dt.otg_cl_ua;
+ chg->dcp_icl_ua = chip->dt.usb_icl_ua;
rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
if (rc < 0) {
@@ -1101,7 +1102,7 @@ static int smb2_init_hw(struct smb2 *chip)
vote(chg->fv_votable,
DEFAULT_VOTER, true, chip->dt.fv_uv);
vote(chg->usb_icl_votable,
- DEFAULT_VOTER, true, chip->dt.usb_icl_ua);
+ DCP_VOTER, true, chip->dt.usb_icl_ua);
vote(chg->dc_icl_votable,
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
vote(chg->hvdcp_disable_votable, DEFAULT_VOTER,
@@ -1186,6 +1187,13 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ /* disable try.SINK mode */
+ rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT, 0);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
+ return rc;
+ }
+
rc = smblib_masked_write(chg, QNOVO_PT_ENABLE_CMD_REG,
QNOVO_PT_ENABLE_CMD_BIT, QNOVO_PT_ENABLE_CMD_BIT);
if (rc < 0) {
@@ -1280,6 +1288,13 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ rc = smblib_validate_initial_typec_legacy_status(chg);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't validate typec legacy status rc=%d\n",
+ rc);
+ return rc;
+ }
+
return rc;
}
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 6aae7d49271f..3403474565be 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -16,6 +16,7 @@
#include <linux/iio/consumer.h>
#include <linux/power_supply.h>
#include <linux/regulator/driver.h>
+#include <linux/qpnp/power-on.h>
#include <linux/irq.h>
#include "smb-lib.h"
#include "smb-reg.h"
@@ -2015,6 +2016,13 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc;
}
+ rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
+ rc);
+ return rc;
+ }
+
rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT);
if (rc < 0) {
@@ -2031,6 +2039,14 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc;
}
} else {
+ rc = vote(chg->usb_icl_votable, DCP_VOTER, true,
+ chg->dcp_icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
+ rc);
+ return rc;
+ }
+
rc = smblib_masked_write(chg, CMD_APSD_REG,
ICL_OVERRIDE_BIT, 0);
if (rc < 0) {
@@ -2066,13 +2082,6 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
smblib_update_usb_type(chg);
power_supply_changed(chg->usb_psy);
- rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT,
- chg->pd_active ? 0 : EN_TRYSINK_MODE_BIT);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
- return rc;
- }
-
return rc;
}
@@ -3356,3 +3365,40 @@ int smblib_deinit(struct smb_charger *chg)
return 0;
}
+
+int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg)
+{
+ int rc;
+ u8 stat;
+
+
+ if (qpnp_pon_is_warm_reset())
+ return 0;
+
+ rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
+ return rc;
+ }
+
+ if ((stat & TYPEC_LEGACY_CABLE_STATUS_BIT) == 0)
+ return 0;
+
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ TYPEC_DISABLE_CMD_BIT, TYPEC_DISABLE_CMD_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't disable typec rc=%d\n", rc);
+ return rc;
+ }
+
+ usleep_range(150000, 151000);
+
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ TYPEC_DISABLE_CMD_BIT, 0);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't enable typec rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index a0237412ee8b..b309095b04c1 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -28,6 +28,7 @@ enum print_reason {
#define DEFAULT_VOTER "DEFAULT_VOTER"
#define USER_VOTER "USER_VOTER"
#define PD_VOTER "PD_VOTER"
+#define DCP_VOTER "DCP_VOTER"
#define USB_PSY_VOTER "USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
@@ -203,6 +204,7 @@ struct smb_charger {
int *thermal_mitigation;
int otg_cl_ua;
+ int dcp_icl_ua;
int fake_capacity;
@@ -354,6 +356,8 @@ int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
int smblib_get_prop_slave_current_now(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_validate_initial_typec_legacy_status(struct smb_charger *chg);
+
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index 9dc528a6bb45..4255958de300 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -630,10 +630,12 @@ static int smb138x_init_hw(struct smb138x *chip)
vote(chg->fcc_votable,
DEFAULT_VOTER, true, chip->dt.fcc_ua);
vote(chg->usb_icl_votable,
- DEFAULT_VOTER, true, chip->dt.usb_icl_ua);
+ DCP_VOTER, true, chip->dt.usb_icl_ua);
vote(chg->dc_icl_votable,
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
+ chg->dcp_icl_ua = chip->dt.usb_icl_ua;
+
/* 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);
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 873b4615d4a9..603cbe65825b 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -412,8 +412,9 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
/**
* Returns zero for success and non-zero in case of a failure
*/
-static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
- u32 hs, u32 rate, bool update_link_startup_timer)
+static int __ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
+ u32 hs, u32 rate, bool update_link_startup_timer,
+ bool is_pre_scale_up)
{
int ret = 0;
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -460,8 +461,12 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
}
list_for_each_entry(clki, &hba->clk_list_head, list) {
- if (!strcmp(clki->name, "core_clk"))
- core_clk_rate = clk_get_rate(clki->clk);
+ if (!strcmp(clki->name, "core_clk")) {
+ if (is_pre_scale_up)
+ core_clk_rate = clki->max_freq;
+ else
+ core_clk_rate = clk_get_rate(clki->clk);
+ }
}
/* If frequency is smaller than 1MHz, set to 1MHz */
@@ -558,6 +563,13 @@ out:
return ret;
}
+static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
+ u32 hs, u32 rate, bool update_link_startup_timer)
+{
+ return __ufs_qcom_cfg_timers(hba, gear, hs, rate,
+ update_link_startup_timer, false);
+}
+
static int ufs_qcom_link_startup_pre_change(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -2160,61 +2172,49 @@ out:
static int ufs_qcom_clk_scale_up_pre_change(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct ufs_pa_layer_attr *attr = &host->dev_req_params;
+ int err = 0;
if (!ufs_qcom_cap_qunipro(host))
- return 0;
-
- return ufs_qcom_configure_lpm(hba, false);
-}
+ goto out;
-static int ufs_qcom_clk_scale_up_post_change(struct ufs_hba *hba)
-{
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ err = ufs_qcom_configure_lpm(hba, false);
+ if (err)
+ goto out;
- if (!ufs_qcom_cap_qunipro(host))
- return 0;
+ if (attr)
+ __ufs_qcom_cfg_timers(hba, attr->gear_rx, attr->pwr_rx,
+ attr->hs_rate, false, true);
/* set unipro core clock cycles to 150 and clear clock divider */
- return ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150);
+ err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba, 150);
+out:
+ return err;
}
static int ufs_qcom_clk_scale_down_pre_change(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- u32 core_clk_ctrl_reg;
- int err = 0;
if (!ufs_qcom_cap_qunipro(host))
- goto out;
-
- err = ufs_qcom_configure_lpm(hba, true);
- if (err)
- goto out;
-
- err = ufshcd_dme_get(hba,
- UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
- &core_clk_ctrl_reg);
+ return 0;
- /* make sure CORE_CLK_DIV_EN is cleared */
- if (!err &&
- (core_clk_ctrl_reg & DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT)) {
- core_clk_ctrl_reg &= ~DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT;
- err = ufshcd_dme_set(hba,
- UIC_ARG_MIB(DME_VS_CORE_CLK_CTRL),
- core_clk_ctrl_reg);
- }
-out:
- return err;
+ return ufs_qcom_configure_lpm(hba, true);
}
static int ufs_qcom_clk_scale_down_post_change(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ struct ufs_pa_layer_attr *attr = &host->dev_req_params;
int err = 0;
if (!ufs_qcom_cap_qunipro(host))
return 0;
+ if (attr)
+ ufs_qcom_cfg_timers(hba, attr->gear_rx, attr->pwr_rx,
+ attr->hs_rate, false);
+
if (ufs_qcom_cap_svs2(host))
/*
* For SVS2 set unipro core clock cycles to 37 and
@@ -2235,7 +2235,6 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
bool scale_up, enum ufs_notify_change_status status)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- struct ufs_pa_layer_attr *dev_req_params = &host->dev_req_params;
int err = 0;
switch (status) {
@@ -2246,19 +2245,9 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
err = ufs_qcom_clk_scale_down_pre_change(hba);
break;
case POST_CHANGE:
- if (scale_up)
- err = ufs_qcom_clk_scale_up_post_change(hba);
- else
+ if (!scale_up)
err = ufs_qcom_clk_scale_down_post_change(hba);
- if (err || !dev_req_params)
- goto out;
-
- ufs_qcom_cfg_timers(hba,
- dev_req_params->gear_rx,
- dev_req_params->pwr_rx,
- dev_req_params->hs_rate,
- false);
ufs_qcom_update_bus_bw_vote(host);
break;
default:
@@ -2267,7 +2256,6 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba,
break;
}
-out:
return err;
}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 862d56e78086..67e1636c25ec 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2633,6 +2633,65 @@ static inline u16 ufshcd_upiu_wlun_to_scsi_wlun(u8 upiu_wlun_id)
}
/**
+ * ufshcd_get_write_lock - synchronize between shutdown, scaling &
+ * arrival of requests
+ * @hba: ufs host
+ *
+ * Lock is predominantly held by shutdown context thus, ensuring
+ * that no requests from any other context may sneak through.
+ */
+static void ufshcd_get_write_lock(struct ufs_hba *hba)
+{
+ down_write(&hba->lock);
+ hba->issuing_task = current;
+}
+
+/**
+ * ufshcd_get_read_lock - synchronize between shutdown, scaling &
+ * arrival of requests
+ * @hba: ufs host
+ *
+ * Returns 1 if acquired, < 0 on contention
+ *
+ * After shutdown's initiated, allow requests only from shutdown
+ * context. The sync between scaling & issue is maintained
+ * as is and this restructuring syncs shutdown with these too.
+ */
+static int ufshcd_get_read_lock(struct ufs_hba *hba)
+{
+ int err = 0;
+
+ err = down_read_trylock(&hba->lock);
+ if (err > 0)
+ goto out;
+ if (hba->issuing_task == current)
+ return 0;
+ else if (!ufshcd_is_shutdown_ongoing(hba))
+ return -EAGAIN;
+ else
+ return -EPERM;
+
+out:
+ hba->issuing_task = current;
+ return err;
+}
+
+/**
+ * ufshcd_put_read_lock - synchronize between shutdown, scaling &
+ * arrival of requests
+ * @hba: ufs host
+ *
+ * Returns none
+ */
+static inline void ufshcd_put_read_lock(struct ufs_hba *hba)
+{
+ if (!ufshcd_is_shutdown_ongoing(hba)) {
+ hba->issuing_task = NULL;
+ up_read(&hba->lock);
+ }
+}
+
+/**
* ufshcd_queuecommand - main entry point for SCSI requests
* @cmd: command from SCSI Midlayer
* @done: call back function
@@ -2657,8 +2716,16 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
BUG();
}
- if (!down_read_trylock(&hba->clk_scaling_lock))
- return SCSI_MLQUEUE_HOST_BUSY;
+ err = ufshcd_get_read_lock(hba);
+ if (unlikely(err < 0)) {
+ if (err == -EPERM) {
+ set_host_byte(cmd, DID_ERROR);
+ cmd->scsi_done(cmd);
+ return 0;
+ }
+ if (err == -EAGAIN)
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -2798,7 +2865,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
out_unlock:
spin_unlock_irqrestore(hba->host->host_lock, flags);
out:
- up_read(&hba->clk_scaling_lock);
+ ufshcd_put_read_lock(hba);
return err;
}
@@ -2990,7 +3057,12 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
struct completion wait;
unsigned long flags;
- down_read(&hba->clk_scaling_lock);
+ /*
+ * May get invoked from shutdown and IOCTL contexts.
+ * In shutdown context, it comes in with lock acquired.
+ */
+ if (!ufshcd_is_shutdown_ongoing(hba))
+ down_read(&hba->lock);
/*
* Get free slot, sleep if slots are unavailable.
@@ -3023,7 +3095,8 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
out_put_tag:
ufshcd_put_dev_cmd_tag(hba, tag);
wake_up(&hba->dev_cmd.tag_wq);
- up_read(&hba->clk_scaling_lock);
+ if (!ufshcd_is_shutdown_ongoing(hba))
+ up_read(&hba->lock);
return err;
}
@@ -4132,7 +4205,13 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "enter",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
- if (ret) {
+ /*
+ * Do full reinit if enter failed or if LINERESET was detected during
+ * Hibern8 operation. After LINERESET, link moves to default PWM-G1
+ * mode hence full reinit is required to move link to HS speeds.
+ */
+ if (ret || hba->full_init_linereset) {
+ hba->full_init_linereset = false;
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_ENTER);
dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d",
__func__, ret);
@@ -4175,8 +4254,13 @@ int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
trace_ufshcd_profile_hibern8(dev_name(hba->dev), "exit",
ktime_to_us(ktime_sub(ktime_get(), start)), ret);
-
- if (ret) {
+ /*
+ * Do full reinit if exit failed or if LINERESET was detected during
+ * Hibern8 operation. After LINERESET, link moves to default PWM-G1
+ * mode hence full reinit is required to move link to HS speeds.
+ */
+ if (ret || hba->full_init_linereset) {
+ hba->full_init_linereset = false;
ufshcd_update_error_stats(hba, UFS_ERR_HIBERN8_EXIT);
dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d",
__func__, ret);
@@ -5696,10 +5780,13 @@ static void ufshcd_err_handler(struct work_struct *work)
dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x",
__func__, hba->saved_err, hba->saved_uic_err);
if (!hba->silence_err_logs) {
+ /* release lock as print host regs sleeps */
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
ufshcd_print_host_regs(hba);
ufshcd_print_host_state(hba);
ufshcd_print_pwr_info(hba);
ufshcd_print_tmrs(hba, hba->outstanding_tasks);
+ spin_lock_irqsave(hba->host->host_lock, flags);
}
}
@@ -5827,9 +5914,8 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
/* PHY layer lane error */
reg = ufshcd_readl(hba, REG_UIC_ERROR_CODE_PHY_ADAPTER_LAYER);
- /* Ignore LINERESET indication, as this is not an error */
if ((reg & UIC_PHY_ADAPTER_LAYER_ERROR) &&
- (reg & UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK)) {
+ (reg & UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK)) {
/*
* To know whether this error is fatal or not, DB timeout
* must be checked but this error is handled separately.
@@ -5837,6 +5923,20 @@ static void ufshcd_update_uic_error(struct ufs_hba *hba)
dev_dbg(hba->dev, "%s: UIC Lane error reported, reg 0x%x\n",
__func__, reg);
ufshcd_update_uic_reg_hist(&hba->ufs_stats.pa_err, reg);
+
+ /* Don't ignore LINERESET indication during hibern8 operation */
+ if (reg & UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR) {
+ struct uic_command *cmd = hba->active_uic_cmd;
+
+ if (cmd) {
+ if ((cmd->command == UIC_CMD_DME_HIBER_ENTER)
+ || (cmd->command == UIC_CMD_DME_HIBER_EXIT)) {
+ dev_err(hba->dev, "%s: LINERESET during hibern8, reg 0x%x\n",
+ __func__, reg);
+ hba->full_init_linereset = true;
+ }
+ }
+ }
}
/* PA_INIT_ERROR is fatal and needs UIC reset */
@@ -6908,11 +7008,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
if (ret)
goto out;
- /* Enable auto hibern8 if supported */
- if (ufshcd_is_auto_hibern8_supported(hba))
- ufshcd_set_auto_hibern8_timer(hba,
- hba->hibern8_on_idle.delay_ms);
-
/* Debug counters initialization */
ufshcd_clear_dbg_ufs_stats(hba);
/* set the default level for urgent bkops */
@@ -6979,6 +7074,13 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
if (ufshcd_scsi_add_wlus(hba))
goto out;
+ /* Enable auto hibern8 if supported, after full host and
+ * device initialization.
+ */
+ if (ufshcd_is_auto_hibern8_supported(hba))
+ ufshcd_set_auto_hibern8_timer(hba,
+ hba->hibern8_on_idle.delay_ms);
+
/* Initialize devfreq after UFS device is detected */
if (ufshcd_is_clkscaling_supported(hba)) {
memcpy(&hba->clk_scaling.saved_pwr_info.info,
@@ -8654,11 +8756,37 @@ static inline void ufshcd_add_sysfs_nodes(struct ufs_hba *hba)
*/
int ufshcd_shutdown(struct ufs_hba *hba)
{
- /*
- * TODO: This function should send the power down notification to
- * UFS device and then power off the UFS link. But we need to be sure
- * that there will not be any new UFS requests issued after this.
+ int ret = 0;
+
+ if (ufshcd_is_ufs_dev_poweroff(hba) && ufshcd_is_link_off(hba))
+ goto out;
+
+ pm_runtime_get_sync(hba->dev);
+ ufshcd_hold_all(hba);
+ /**
+ * (1) Acquire the lock to stop any more requests
+ * (2) Set state to shutting down
+ * (3) Suspend clock scaling
+ * (4) Wait for all issued requests to complete
*/
+ ufshcd_get_write_lock(hba);
+ ufshcd_mark_shutdown_ongoing(hba);
+ ufshcd_scsi_block_requests(hba);
+ ufshcd_suspend_clkscaling(hba);
+ ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
+ if (ret)
+ dev_err(hba->dev, "%s: waiting for DB clear: failed: %d\n",
+ __func__, ret);
+ /* Requests may have errored out above, let it be handled */
+ flush_work(&hba->eh_work);
+ /* reqs issued from contexts other than shutdown will fail from now */
+ ufshcd_scsi_unblock_requests(hba);
+ ufshcd_release_all(hba);
+ ret = ufshcd_suspend(hba, UFS_SHUTDOWN_PM);
+out:
+ if (ret)
+ dev_err(hba->dev, "%s failed, err %d\n", __func__, ret);
+ /* allow force shutdown even in case of errors */
return 0;
}
EXPORT_SYMBOL(ufshcd_shutdown);
@@ -8843,10 +8971,10 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
* clock scaling is in progress
*/
ufshcd_scsi_block_requests(hba);
- down_write(&hba->clk_scaling_lock);
+ down_write(&hba->lock);
if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
ret = -EBUSY;
- up_write(&hba->clk_scaling_lock);
+ up_write(&hba->lock);
ufshcd_scsi_unblock_requests(hba);
}
@@ -8855,7 +8983,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba)
{
- up_write(&hba->clk_scaling_lock);
+ up_write(&hba->lock);
ufshcd_scsi_unblock_requests(hba);
}
@@ -9038,6 +9166,10 @@ static void ufshcd_clk_scaling_resume_work(struct work_struct *work)
clk_scaling.resume_work);
unsigned long irq_flags;
+ /* Let's not resume scaling if shutdown is ongoing */
+ if (ufshcd_is_shutdown_ongoing(hba))
+ return;
+
spin_lock_irqsave(hba->host->host_lock, irq_flags);
if (!hba->clk_scaling.is_suspended) {
spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
@@ -9250,7 +9382,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Initialize mutex for device management commands */
mutex_init(&hba->dev_cmd.lock);
- init_rwsem(&hba->clk_scaling_lock);
+ init_rwsem(&hba->lock);
/* Initialize device management tag acquire wait queue */
init_waitqueue_head(&hba->dev_cmd.tag_wq);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c0714b7bea72..9f2b04c8ff82 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -895,15 +895,30 @@ struct ufs_hba {
enum bkops_status urgent_bkops_lvl;
bool is_urgent_bkops_lvl_checked;
- struct rw_semaphore clk_scaling_lock;
+ /* sync b/w diff contexts */
+ struct rw_semaphore lock;
+ struct task_struct *issuing_task;
+ unsigned long shutdown_in_prog;
struct reset_control *core_reset;
/* If set, don't gate device ref_clk during clock gating */
bool no_ref_clk_gating;
int scsi_block_reqs_cnt;
+
+ bool full_init_linereset;
};
+static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
+{
+ set_bit(0, &hba->shutdown_in_prog);
+}
+
+static inline bool ufshcd_is_shutdown_ongoing(struct ufs_hba *hba)
+{
+ return !!(test_bit(0, &hba->shutdown_in_prog));
+}
+
/* Returns true if clocks can be gated. Otherwise false */
static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba)
{
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index d65dad03bdd2..c0e4650a75ad 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -190,6 +190,7 @@ enum {
/* UECPA - Host UIC Error Code PHY Adapter Layer 38h */
#define UIC_PHY_ADAPTER_LAYER_ERROR UFS_BIT(31)
+#define UIC_PHY_ADAPTER_LAYER_GENERIC_ERROR UFS_BIT(4)
#define UIC_PHY_ADAPTER_LAYER_ERROR_CODE_MASK 0x1F
#define UIC_PHY_ADAPTER_LAYER_LANE_ERR_MASK 0xF
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 6215636b0f46..59d7f6423932 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1485,8 +1485,18 @@ static int icnss_hw_reset(struct icnss_priv *priv)
icnss_hw_reset_wlan_rfactrl_power_down(priv);
ret = icnss_hw_reset_rf_reset_cmd(priv);
- if (ret)
+ if (ret) {
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_FORCE_ACTIVE, 0);
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_DISCONNECT_CLR, 0);
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_WLAN_DISABLE, 1);
goto top_level_reset;
+ }
icnss_hw_reset_switch_to_cxo(priv);
@@ -1511,8 +1521,18 @@ static int icnss_hw_reset(struct icnss_priv *priv)
}
ret = icnss_hw_reset_xo_disable_cmd(priv);
- if (ret)
+ if (ret) {
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_FORCE_ACTIVE, 0);
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_DISCONNECT_CLR, 0);
+ icnss_hw_write_reg_field(priv->mpm_config_va,
+ MPM_WCSSAON_CONFIG_OFFSET,
+ MPM_WCSSAON_CONFIG_WLAN_DISABLE, 1);
goto top_level_reset;
+ }
icnss_hw_write_reg_field(priv->mpm_config_va, MPM_WCSSAON_CONFIG_OFFSET,
MPM_WCSSAON_CONFIG_FORCE_ACTIVE, 0);
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index cd3d387645fd..8f5ad7af8d0d 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -84,6 +84,7 @@ static int smem_module_inited;
static RAW_NOTIFIER_HEAD(smem_module_init_notifier_list);
static DEFINE_MUTEX(smem_module_init_notifier_lock);
static bool probe_done;
+uint32_t smem_max_items;
/* smem security feature components */
#define SMEM_TOC_IDENTIFIER 0x434f5424 /* "$TOC" */
@@ -139,6 +140,11 @@ struct smem_partition_info {
};
static struct smem_partition_info partitions[NUM_SMEM_SUBSYSTEMS];
+
+#define SMEM_COMM_PART_VERSION 0x000C
+#define SMEM_COMM_HOST 0xFFFE
+static bool use_comm_partition;
+static struct smem_partition_info comm_partition;
/* end smem security feature components */
/* Identifier for the SMEM target info struct. */
@@ -149,6 +155,7 @@ struct smem_targ_info_type {
uint32_t identifier;
uint32_t size;
phys_addr_t phys_base_addr;
+ uint32_t max_items;
};
struct restart_notifier_block {
@@ -312,7 +319,7 @@ static void *__smem_get_entry_nonsecure(unsigned id, unsigned *size,
if (!skip_init_check && !smem_initialized_check())
return ret;
- if (id >= SMEM_NUM_ITEMS)
+ if (id >= smem_max_items)
return ret;
if (use_spinlocks) {
@@ -374,7 +381,7 @@ static void *__smem_get_entry_secure(unsigned id,
if (!skip_init_check && !smem_initialized_check())
return NULL;
- if (id >= SMEM_NUM_ITEMS) {
+ if (id >= smem_max_items) {
SMEM_INFO("%s: invalid id %d\n", __func__, id);
return NULL;
}
@@ -385,12 +392,18 @@ static void *__smem_get_entry_secure(unsigned id,
return NULL;
}
- if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset)
- return __smem_get_entry_nonsecure(id, size, skip_init_check,
- use_rspinlock);
-
- partition_num = partitions[to_proc].partition_num;
- hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
+ if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) {
+ if (use_comm_partition) {
+ partition_num = comm_partition.partition_num;
+ hdr = smem_areas[0].virt_addr + comm_partition.offset;
+ } else {
+ return __smem_get_entry_nonsecure(id, size,
+ skip_init_check, use_rspinlock);
+ }
+ } else {
+ partition_num = partitions[to_proc].partition_num;
+ hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
+ }
if (unlikely(!spinlocks_initialized)) {
rc = init_smem_remote_spinlock();
if (unlikely(rc)) {
@@ -613,8 +626,19 @@ static void *alloc_item_secure(unsigned id, unsigned size_in, unsigned to_proc,
uint32_t partition_num;
void *ret = NULL;
- hdr = smem_base + partitions[to_proc].offset;
- partition_num = partitions[to_proc].partition_num;
+ if (to_proc == SMEM_COMM_HOST) {
+ hdr = smem_base + comm_partition.offset;
+ partition_num = comm_partition.partition_num;
+ size_cacheline = comm_partition.size_cacheline;
+ } else if (to_proc < NUM_SMEM_SUBSYSTEMS) {
+ hdr = smem_base + partitions[to_proc].offset;
+ partition_num = partitions[to_proc].partition_num;
+ size_cacheline = partitions[to_proc].size_cacheline;
+ } else {
+ SMEM_INFO("%s: invalid to_proc %u for id %u\n", __func__,
+ to_proc, id);
+ return NULL;
+ }
if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) {
LOG_ERR(
@@ -626,7 +650,6 @@ static void *alloc_item_secure(unsigned id, unsigned size_in, unsigned to_proc,
BUG();
}
- size_cacheline = partitions[to_proc].size_cacheline;
free_space = hdr->offset_free_cached -
hdr->offset_free_uncached;
@@ -718,7 +741,7 @@ void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
if (!smem_initialized_check())
return NULL;
- if (id >= SMEM_NUM_ITEMS) {
+ if (id >= smem_max_items) {
SMEM_INFO("%s: invalid id %u\n", __func__, id);
return NULL;
}
@@ -761,11 +784,16 @@ void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
if (id > SMEM_FIXED_ITEM_LAST) {
SMEM_INFO("%s: allocating %u size %u to_proc %u flags %u\n",
__func__, id, size_in, to_proc, flags);
- if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset)
- ret = alloc_item_nonsecure(id, a_size_in);
- else
+ if (flags & SMEM_ANY_HOST_FLAG
+ || !partitions[to_proc].offset) {
+ if (use_comm_partition)
+ ret = alloc_item_secure(id, size_in,
+ SMEM_COMM_HOST, flags);
+ else
+ ret = alloc_item_nonsecure(id, a_size_in);
+ } else {
ret = alloc_item_secure(id, size_in, to_proc, flags);
-
+ }
} else {
SMEM_INFO("%s: attempted to allocate non-dynamic item %u\n",
__func__, id);
@@ -893,14 +921,18 @@ EXPORT_SYMBOL(smem_get_free_space);
unsigned smem_get_version(unsigned idx)
{
int *version_array;
+ struct smem_shared *smem = smem_ram_base;
if (idx > 32) {
pr_err("%s: invalid idx:%d\n", __func__, idx);
return 0;
}
- version_array = __smem_find(SMEM_VERSION_INFO, SMEM_VERSION_INFO_SIZE,
- true);
+ if (use_comm_partition)
+ version_array = smem->version;
+ else
+ version_array = __smem_find(SMEM_VERSION_INFO,
+ SMEM_VERSION_INFO_SIZE, true);
if (version_array == NULL)
return 0;
@@ -948,6 +980,7 @@ bool smem_initialized_check(void)
static int is_inited;
unsigned long flags;
struct smem_shared *smem;
+ unsigned ver;
if (likely(checked)) {
if (unlikely(!is_inited))
@@ -976,8 +1009,12 @@ bool smem_initialized_check(void)
* structures. Without the extra configuration data, the SMEM driver
* cannot be properly initialized.
*/
- if (smem_get_version(MODEM_SBL_VERSION_INDEX) != SMEM_VERSION << 16) {
- pr_err("%s: SBL version not correct\n", __func__);
+ ver = smem->version[MODEM_SBL_VERSION_INDEX];
+ if (ver == SMEM_COMM_PART_VERSION << 16) {
+ use_comm_partition = true;
+ } else if (ver != SMEM_VERSION << 16) {
+ pr_err("%s: SBL version not correct 0x%x\n",
+ __func__, smem->version[7]);
goto failed;
}
@@ -1122,6 +1159,7 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
{
uint16_t remote_host;
struct smem_partition_header *hdr;
+ bool is_comm_partition = false;
if (!entry->offset) {
SMEM_INFO("Skipping smem partition %d - bad offset\n", num);
@@ -1136,31 +1174,38 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
return;
}
- if (entry->host0 == SMEM_APPS)
- remote_host = entry->host1;
- else
- remote_host = entry->host0;
+ if (entry->host0 == SMEM_COMM_HOST && entry->host1 == SMEM_COMM_HOST)
+ is_comm_partition = true;
- if (remote_host >= NUM_SMEM_SUBSYSTEMS) {
- SMEM_INFO("Skipping smem partition %d - bad remote:%d\n", num,
- remote_host);
- return;
- }
- if (partitions[remote_host].offset) {
- SMEM_INFO("Skipping smem partition %d - duplicate of %d\n", num,
- partitions[remote_host].partition_num);
- return;
- }
+ if (!is_comm_partition) {
+ if (entry->host0 == SMEM_APPS)
+ remote_host = entry->host1;
+ else
+ remote_host = entry->host0;
- hdr = smem_areas[0].virt_addr + entry->offset;
+ if (remote_host >= NUM_SMEM_SUBSYSTEMS) {
+ SMEM_INFO(
+ "Skipping smem partition %d - bad remote:%d\n",
+ num, remote_host);
+ return;
+ }
+ if (partitions[remote_host].offset) {
+ SMEM_INFO(
+ "Skipping smem partition %d - duplicate of %d\n",
+ num, partitions[remote_host].partition_num);
+ return;
+ }
- if (entry->host0 != SMEM_APPS && entry->host1 != SMEM_APPS) {
- SMEM_INFO(
- "Non-APSS Partition %d offset:%x host0:%d host1:%d\n",
- num, entry->offset, entry->host0, entry->host1);
- return;
+ if (entry->host0 != SMEM_APPS && entry->host1 != SMEM_APPS) {
+ SMEM_INFO(
+ "Non-APSS Partition %d offset:%x host0:%d host1:%d\n",
+ num, entry->offset, entry->host0, entry->host1);
+ return;
+ }
}
+ hdr = smem_areas[0].virt_addr + entry->offset;
+
if (hdr->identifier != SMEM_PART_HDR_IDENTIFIER) {
LOG_ERR("Smem partition %d hdr magic is bad\n", num);
BUG();
@@ -1177,6 +1222,14 @@ static void smem_init_security_partition(struct smem_toc_entry *entry,
LOG_ERR("Smem partition %d cached heap exceeds size\n", num);
BUG();
}
+ if (hdr->host0 == SMEM_COMM_HOST && hdr->host1 == SMEM_COMM_HOST) {
+ comm_partition.partition_num = num;
+ comm_partition.offset = entry->offset;
+ comm_partition.size_cacheline = entry->size_cacheline;
+ SMEM_INFO("Common Partition %d offset:%x\n", num,
+ entry->offset);
+ return;
+ }
if (hdr->host0 != SMEM_APPS && hdr->host1 != SMEM_APPS) {
LOG_ERR("Smem partition %d hosts don't match TOC\n", num);
BUG();
@@ -1253,6 +1306,8 @@ static int smem_init_target_info(phys_addr_t info_addr, resource_size_t size)
}
smem_ram_phys = smem_targ_info->phys_base_addr;
smem_ram_size = smem_targ_info->size;
+ if (smem_targ_info->max_items)
+ smem_max_items = smem_targ_info->max_items;
iounmap(smem_targ_info_addr);
return 0;
}
@@ -1488,7 +1543,7 @@ int __init msm_smem_init(void)
return 0;
registered = true;
-
+ smem_max_items = SMEM_NUM_ITEMS;
smem_ipc_log_ctx = ipc_log_context_create(NUM_LOG_PAGES, "smem", 0);
if (!smem_ipc_log_ctx) {
pr_err("%s: unable to create logging context\n", __func__);
diff --git a/drivers/soc/qcom/smem_debug.c b/drivers/soc/qcom/smem_debug.c
index ace89afb614c..766a1781e6b9 100644
--- a/drivers/soc/qcom/smem_debug.c
+++ b/drivers/soc/qcom/smem_debug.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smem_debug.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013,2016 The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -53,7 +53,7 @@ static void debug_read_mem(struct seq_file *s)
heap_info->free_offset,
heap_info->heap_remaining);
- for (n = 0; n < SMEM_NUM_ITEMS; n++) {
+ for (n = 0; n < smem_max_items; n++) {
if (toc[n].allocated == 0)
continue;
seq_printf(s, "%04d: offset %08x size %08x\n",
@@ -67,9 +67,8 @@ static void debug_read_smem_version(struct seq_file *s)
for (n = 0; n < 32; n++) {
version = smem_get_version(n);
- seq_printf(s, "entry %d: smem = %d proc_comm = %d\n", n,
- version >> 16,
- version & 0xffff);
+ seq_printf(s, "entry %d:%x smem = %d proc_comm = %d\n",
+ n, version, version >> 16, version & 0xffff);
}
}
diff --git a/drivers/soc/qcom/smem_private.h b/drivers/soc/qcom/smem_private.h
index 7aeca5eed8d2..ddbc29e30dfb 100644
--- a/drivers/soc/qcom/smem_private.h
+++ b/drivers/soc/qcom/smem_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013,2016 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
@@ -18,6 +18,7 @@
#define SMD_HEAP_SIZE 512
+extern uint32_t smem_max_items;
struct smem_heap_info {
unsigned initialized;
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index ced2f23addd4..002cafb08f37 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -60,6 +60,7 @@
#define MSM_LIMITS_NODE_DCVS 0x44435653
#define MSM_LIMITS_SUB_FN_GENERAL 0x47454E00
#define MSM_LIMITS_SUB_FN_CRNT 0x43524E54
+#define MSM_LIMITS_SUB_FN_REL 0x52454C00
#define MSM_LIMITS_DOMAIN_MAX 0x444D4158
#define MSM_LIMITS_DOMAIN_MIN 0x444D494E
#define MSM_LIMITS_CLUSTER_0 0x6370302D
@@ -1674,7 +1675,20 @@ static int msm_thermal_lmh_dcvs_init(struct platform_device *pdev)
*/
devm_clk_put(&pdev->dev, osm_clk);
- /* Enable the CRNT algorithm. Again, we dont care if this fails */
+ /* Enable the CRNT and Reliability algorithm. Again, we dont
+ * care if this fails
+ */
+ ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_0,
+ MSM_LIMITS_SUB_FN_REL,
+ MSM_LIMITS_ALGO_MODE_ENABLE, 1);
+ if (ret)
+ pr_err("Unable to enable REL algo for cluster0\n");
+ ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_1,
+ MSM_LIMITS_SUB_FN_REL,
+ MSM_LIMITS_ALGO_MODE_ENABLE, 1);
+ if (ret)
+ pr_err("Unable to enable REL algo for cluster1\n");
+
ret = msm_lmh_dcvs_write(MSM_LIMITS_CLUSTER_0,
MSM_LIMITS_SUB_FN_CRNT,
MSM_LIMITS_ALGO_MODE_ENABLE, 1);
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index dadd1e8dfe09..26a305f43ff6 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1441,6 +1441,9 @@ int usb_suspend(struct device *dev, pm_message_t msg)
{
struct usb_device *udev = to_usb_device(dev);
+ if (udev->bus->skip_resume && udev->state == USB_STATE_SUSPENDED)
+ return 0;
+
unbind_no_pm_drivers_interfaces(udev);
/* From now on we are sure all drivers support suspend/resume
@@ -1470,6 +1473,15 @@ int usb_resume(struct device *dev, pm_message_t msg)
struct usb_device *udev = to_usb_device(dev);
int status;
+ /*
+ * Some buses would like to keep their devices in suspend
+ * state after system resume. Their resume happen when
+ * a remote wakeup is detected or interface driver start
+ * I/O.
+ */
+ if (udev->bus->skip_resume)
+ return 0;
+
/* For all calls, take the device back to full power and
* tell the PM core in case it was autosuspended previously.
* Unbind the interfaces that will need rebinding later,
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index c025dccdd8f1..fcb9b4b822aa 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -167,6 +167,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (!hcd)
return -ENOMEM;
+ hcd_to_bus(hcd)->skip_resume = true;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hcd->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(hcd->regs)) {
@@ -221,6 +223,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
goto disable_clk;
}
+ hcd_to_bus(xhci->shared_hcd)->skip_resume = true;
+
if ((node && of_property_read_bool(node, "usb3-lpm-capable")) ||
(pdata && pdata->usb3_lpm_capable))
xhci->quirks |= XHCI_LPM_SUPPORT;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index b4d7c7d8bddf..aa2e1d9f3c70 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -913,7 +913,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
case PE_PRS_SNK_SRC_TRANSITION_TO_OFF:
val.intval = pd->requested_current = 0; /* suspend charging */
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &val);
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
pd->in_explicit_contract = false;
@@ -1039,23 +1039,23 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
return;
}
- if (handler && handler->svdm_received)
+ /* if this interrupts a previous exchange, abort queued response */
+ if (cmd_type == SVDM_CMD_TYPE_INITIATOR && pd->vdm_tx) {
+ usbpd_dbg(&pd->dev, "Discarding previously queued SVDM tx (SVID:0x%04x)\n",
+ VDM_HDR_SVID(pd->vdm_tx->data[0]));
+
+ kfree(pd->vdm_tx);
+ pd->vdm_tx = NULL;
+ }
+
+ if (handler && handler->svdm_received) {
handler->svdm_received(handler, cmd, cmd_type, vdos, num_vdos);
+ return;
+ }
+ /* Standard Discovery or unhandled messages go here */
switch (cmd_type) {
case SVDM_CMD_TYPE_INITIATOR:
- /*
- * if this interrupts a previous exchange, abort the previous
- * outgoing response
- */
- if (pd->vdm_tx) {
- usbpd_dbg(&pd->dev, "Discarding previously queued SVDM tx (SVID:0x%04x)\n",
- VDM_HDR_SVID(pd->vdm_tx->data[0]));
-
- kfree(pd->vdm_tx);
- pd->vdm_tx = NULL;
- }
-
if (svid == USBPD_SID && cmd == USBPD_SVDM_DISCOVER_IDENTITY) {
u32 tx_vdos[3] = {
ID_HDR_USB_HOST | ID_HDR_USB_DEVICE |
@@ -1074,13 +1074,14 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
break;
case SVDM_CMD_TYPE_RESP_ACK:
+ if (svid != USBPD_SID) {
+ usbpd_err(&pd->dev, "unhandled ACK for SVID:0x%x\n",
+ svid);
+ break;
+ }
+
switch (cmd) {
case USBPD_SVDM_DISCOVER_IDENTITY:
- if (svid != USBPD_SID) {
- usbpd_err(&pd->dev, "invalid VID:0x%x\n", svid);
- break;
- }
-
kfree(pd->vdm_tx_retry);
pd->vdm_tx_retry = NULL;
@@ -1091,11 +1092,6 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
break;
case USBPD_SVDM_DISCOVER_SVIDS:
- if (svid != USBPD_SID) {
- usbpd_err(&pd->dev, "invalid VID:0x%x\n", svid);
- break;
- }
-
pd->vdm_state = DISCOVERED_SVIDS;
kfree(pd->vdm_tx_retry);
@@ -1181,33 +1177,15 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg)
break;
- case USBPD_SVDM_DISCOVER_MODES:
- usbpd_info(&pd->dev, "SVID:0x%04x VDM Modes discovered\n",
- svid);
- pd->vdm_state = DISCOVERED_MODES;
- break;
-
- case USBPD_SVDM_ENTER_MODE:
- usbpd_info(&pd->dev, "SVID:0x%04x VDM Mode entered\n",
- svid);
- pd->vdm_state = MODE_ENTERED;
- kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
- break;
-
- case USBPD_SVDM_EXIT_MODE:
- usbpd_info(&pd->dev, "SVID:0x%04x VDM Mode exited\n",
- svid);
- pd->vdm_state = MODE_EXITED;
- kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE);
- break;
-
default:
+ usbpd_dbg(&pd->dev, "unhandled ACK for command:0x%x\n",
+ cmd);
break;
}
break;
case SVDM_CMD_TYPE_RESP_NAK:
- usbpd_info(&pd->dev, "VDM NAK received for SVID:0x%04x command:%d\n",
+ usbpd_info(&pd->dev, "VDM NAK received for SVID:0x%04x command:0x%x\n",
svid, cmd);
break;
@@ -1731,6 +1709,8 @@ static void usbpd_sm(struct work_struct *w)
case PE_SNK_SELECT_CAPABILITY:
if (IS_CTRL(rx_msg, MSG_ACCEPT)) {
+ usbpd_set_state(pd, PE_SNK_TRANSITION_SINK);
+
/* prepare for voltage increase/decrease */
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
@@ -1740,16 +1720,31 @@ static void usbpd_sm(struct work_struct *w)
&val);
/*
- * disable charging; technically we are allowed to
- * charge up to pSnkStdby (2.5 W) during this
- * transition, but disable it just for simplicity.
+ * if we are changing voltages, we must lower input
+ * current to pSnkStdby (2.5W). Calculate it and set
+ * PD_CURRENT_MAX accordingly.
*/
- val.intval = 0;
- power_supply_set_property(pd->usb_psy,
+ if (pd->requested_voltage != pd->current_voltage) {
+ int mv = max(pd->requested_voltage,
+ pd->current_voltage) / 1000;
+ val.intval = (2500000 / mv) * 1000;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
+ } else {
+ /* decreasing current? */
+ ret = power_supply_get_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
+ if (!ret &&
+ pd->requested_current < val.intval) {
+ val.intval =
+ pd->requested_current * 1000;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX,
+ &val);
+ }
+ }
pd->selected_pdo = pd->requested_pdo;
- usbpd_set_state(pd, PE_SNK_TRANSITION_SINK);
} else if (IS_CTRL(rx_msg, MSG_REJECT) ||
IS_CTRL(rx_msg, MSG_WAIT)) {
if (pd->in_explicit_contract)
diff --git a/drivers/usb/phy/phy-msm-qusb.c b/drivers/usb/phy/phy-msm-qusb.c
index 5456b9e8733b..839d701ec9b5 100644
--- a/drivers/usb/phy/phy-msm-qusb.c
+++ b/drivers/usb/phy/phy-msm-qusb.c
@@ -109,6 +109,7 @@ struct qusb_phy {
void __iomem *base;
void __iomem *tune2_efuse_reg;
void __iomem *ref_clk_base;
+ void __iomem *tcsr_clamp_dig_n;
struct clk *ref_clk_src;
struct clk *ref_clk;
@@ -147,6 +148,7 @@ struct qusb_phy {
int phy_pll_reset_seq_len;
int *emu_dcm_reset_seq;
int emu_dcm_reset_seq_len;
+ bool put_into_high_z_state;
};
static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
@@ -189,15 +191,14 @@ static int qusb_phy_config_vdd(struct qusb_phy *qphy, int high)
return ret;
}
-static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on,
- bool toggle_vdd)
+static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on)
{
int ret = 0;
dev_dbg(qphy->phy.dev, "%s turn %s regulators. power_enabled:%d\n",
__func__, on ? "on" : "off", qphy->power_enabled);
- if (toggle_vdd && qphy->power_enabled == on) {
+ if (qphy->power_enabled == on) {
dev_dbg(qphy->phy.dev, "PHYs' regulators are already ON.\n");
return 0;
}
@@ -205,19 +206,17 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on,
if (!on)
goto disable_vdda33;
- if (toggle_vdd) {
- ret = qusb_phy_config_vdd(qphy, true);
- if (ret) {
- dev_err(qphy->phy.dev, "Unable to config VDD:%d\n",
- ret);
- goto err_vdd;
- }
+ ret = qusb_phy_config_vdd(qphy, true);
+ if (ret) {
+ dev_err(qphy->phy.dev, "Unable to config VDD:%d\n",
+ ret);
+ goto err_vdd;
+ }
- ret = regulator_enable(qphy->vdd);
- if (ret) {
- dev_err(qphy->phy.dev, "Unable to enable VDD\n");
- goto unconfig_vdd;
- }
+ ret = regulator_enable(qphy->vdd);
+ if (ret) {
+ dev_err(qphy->phy.dev, "Unable to enable VDD\n");
+ goto unconfig_vdd;
}
ret = regulator_set_load(qphy->vdda18, QUSB2PHY_1P8_HPM_LOAD);
@@ -260,8 +259,7 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on,
goto unset_vdd33;
}
- if (toggle_vdd)
- qphy->power_enabled = true;
+ qphy->power_enabled = true;
pr_debug("%s(): QUSB PHY's regulators are turned ON.\n", __func__);
return ret;
@@ -299,21 +297,18 @@ put_vdda18_lpm:
dev_err(qphy->phy.dev, "Unable to set LPM of vdda18\n");
disable_vdd:
- if (toggle_vdd) {
- ret = regulator_disable(qphy->vdd);
- if (ret)
- dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n",
+ ret = regulator_disable(qphy->vdd);
+ if (ret)
+ dev_err(qphy->phy.dev, "Unable to disable vdd:%d\n",
ret);
unconfig_vdd:
- ret = qusb_phy_config_vdd(qphy, false);
- if (ret)
- dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n",
+ ret = qusb_phy_config_vdd(qphy, false);
+ if (ret)
+ dev_err(qphy->phy.dev, "Unable unconfig VDD:%d\n",
ret);
- }
err_vdd:
- if (toggle_vdd)
- qphy->power_enabled = false;
+ qphy->power_enabled = false;
dev_dbg(qphy->phy.dev, "QUSB PHY's regulators are turned OFF.\n");
return ret;
}
@@ -330,12 +325,53 @@ static int qusb_phy_update_dpdm(struct usb_phy *phy, int value)
case POWER_SUPPLY_DP_DM_DPF_DMF:
dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPF_DMF\n");
if (!qphy->rm_pulldown) {
- ret = qusb_phy_enable_power(qphy, true, false);
+ ret = qusb_phy_enable_power(qphy, true);
if (ret >= 0) {
qphy->rm_pulldown = true;
dev_dbg(phy->dev, "DP_DM_F: rm_pulldown:%d\n",
qphy->rm_pulldown);
}
+
+ if (qphy->put_into_high_z_state) {
+ if (qphy->tcsr_clamp_dig_n)
+ writel_relaxed(0x1,
+ qphy->tcsr_clamp_dig_n);
+
+ qusb_phy_enable_clocks(qphy, true);
+
+ dev_dbg(phy->dev, "RESET QUSB PHY\n");
+ ret = reset_control_assert(qphy->phy_reset);
+ if (ret)
+ dev_err(phy->dev, "phyassert failed\n");
+ usleep_range(100, 150);
+ ret = reset_control_deassert(qphy->phy_reset);
+ if (ret)
+ dev_err(phy->dev, "deassert failed\n");
+
+ /*
+ * Phy in non-driving mode leaves Dp and Dm
+ * lines in high-Z state. Controller power
+ * collapse is not switching phy to non-driving
+ * mode causing charger detection failure. Bring
+ * phy to non-driving mode by overriding
+ * controller output via UTMI interface.
+ */
+ writel_relaxed(TERM_SELECT | XCVR_SELECT_FS |
+ OP_MODE_NON_DRIVE,
+ qphy->base + QUSB2PHY_PORT_UTMI_CTRL1);
+ writel_relaxed(UTMI_ULPI_SEL |
+ UTMI_TEST_MUX_SEL,
+ qphy->base + QUSB2PHY_PORT_UTMI_CTRL2);
+
+ /* Disable PHY */
+ writel_relaxed(CLAMP_N_EN | FREEZIO_N |
+ POWER_DOWN,
+ qphy->base + QUSB2PHY_PORT_POWERDOWN);
+ /* Make sure that above write is completed */
+ wmb();
+
+ qusb_phy_enable_clocks(qphy, false);
+ }
}
break;
@@ -343,7 +379,13 @@ static int qusb_phy_update_dpdm(struct usb_phy *phy, int value)
case POWER_SUPPLY_DP_DM_DPR_DMR:
dev_dbg(phy->dev, "POWER_SUPPLY_DP_DM_DPR_DMR\n");
if (qphy->rm_pulldown) {
- ret = qusb_phy_enable_power(qphy, false, false);
+ if (!qphy->cable_connected) {
+ if (qphy->tcsr_clamp_dig_n)
+ writel_relaxed(0x0,
+ qphy->tcsr_clamp_dig_n);
+ dev_dbg(phy->dev, "turn off for HVDCP case\n");
+ ret = qusb_phy_enable_power(qphy, false);
+ }
if (ret >= 0) {
qphy->rm_pulldown = false;
dev_dbg(phy->dev, "DP_DM_R: rm_pulldown:%d\n",
@@ -420,7 +462,7 @@ static int qusb_phy_init(struct usb_phy *phy)
dev_dbg(phy->dev, "%s\n", __func__);
- ret = qusb_phy_enable_power(qphy, true, true);
+ ret = qusb_phy_enable_power(qphy, true);
if (ret)
return ret;
@@ -651,22 +693,23 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
/* Disable all interrupts */
writel_relaxed(0x00,
qphy->base + QUSB2PHY_PORT_INTR_CTRL);
- /*
- * Phy in non-driving mode leaves Dp and Dm lines in
- * high-Z state. Controller power collapse is not
- * switching phy to non-driving mode causing charger
- * detection failure. Bring phy to non-driving mode by
- * overriding controller output via UTMI interface.
- */
- writel_relaxed(TERM_SELECT | XCVR_SELECT_FS |
- OP_MODE_NON_DRIVE,
- qphy->base + QUSB2PHY_PORT_UTMI_CTRL1);
- writel_relaxed(UTMI_ULPI_SEL | UTMI_TEST_MUX_SEL,
- qphy->base + QUSB2PHY_PORT_UTMI_CTRL2);
+ /* Make sure that above write is completed */
+ wmb();
qusb_phy_enable_clocks(qphy, false);
- qusb_phy_enable_power(qphy, false, true);
+ if (qphy->tcsr_clamp_dig_n)
+ writel_relaxed(0x0,
+ qphy->tcsr_clamp_dig_n);
+ qusb_phy_enable_power(qphy, false);
+ /*
+ * Set put_into_high_z_state to true so next USB
+ * cable connect, DPF_DMF request performs PHY
+ * reset and put it into high-z state. For bootup
+ * with or without USB cable, it doesn't require
+ * to put QUSB PHY into high-z state.
+ */
+ qphy->put_into_high_z_state = true;
}
qphy->suspended = true;
} else {
@@ -678,7 +721,10 @@ static int qusb_phy_set_suspend(struct usb_phy *phy, int suspend)
writel_relaxed(0x00,
qphy->base + QUSB2PHY_PORT_INTR_CTRL);
} else {
- qusb_phy_enable_power(qphy, true, true);
+ qusb_phy_enable_power(qphy, true);
+ if (qphy->tcsr_clamp_dig_n)
+ writel_relaxed(0x1,
+ qphy->tcsr_clamp_dig_n);
qusb_phy_enable_clocks(qphy, true);
}
qphy->suspended = false;
@@ -849,6 +895,18 @@ static int qusb_phy_probe(struct platform_device *pdev)
}
}
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "tcsr_clamp_dig_n_1p8");
+ if (res) {
+ qphy->tcsr_clamp_dig_n = devm_ioremap_nocache(dev,
+ res->start, resource_size(res));
+ if (IS_ERR(qphy->tcsr_clamp_dig_n)) {
+ dev_err(dev, "err reading tcsr_clamp_dig_n\n");
+ qphy->tcsr_clamp_dig_n = NULL;
+ }
+ }
+
+
qphy->ref_clk_src = devm_clk_get(dev, "ref_clk_src");
if (IS_ERR(qphy->ref_clk_src))
dev_dbg(dev, "clk get failed for ref_clk_src\n");
@@ -1046,7 +1104,7 @@ static int qusb_phy_remove(struct platform_device *pdev)
qphy->clocks_enabled = false;
}
- qusb_phy_enable_power(qphy, false, true);
+ qusb_phy_enable_power(qphy, false);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 29fc4e6fd65b..b7561e49955b 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -2068,7 +2068,7 @@ static int mdss_retrieve_dp_ctrl_resources(struct platform_device *pdev,
"hdcp_physical"))
pr_warn("unable to remap dp hdcp resources\n");
- pr_debug("DP Driver base=%p size=%x\n",
+ pr_debug("DP Driver base=%pK size=%x\n",
dp_drv->base, dp_drv->base_size);
mdss_debug_register_base("dp",
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index cf7a398c13ce..8dccab8a81be 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2985,6 +2985,12 @@ static int mdss_dsi_cont_splash_config(struct mdss_panel_info *pinfo,
mdss_dsi_panel_pwm_enable(ctrl_pdata);
ctrl_pdata->ctrl_state |= (CTRL_STATE_PANEL_INIT |
CTRL_STATE_MDP_ACTIVE | CTRL_STATE_DSI_ACTIVE);
+
+ /*
+ * MDP client removes this extra vote during splash reconfigure
+ * for command mode panel from interface. DSI removes the vote
+ * during suspend-resume for video mode panel.
+ */
if (ctrl_pdata->panel_data.panel_info.type == MIPI_CMD_PANEL)
clk_handle = ctrl_pdata->mdp_clk_handle;
else
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 3536cb2d294d..3a347681f434 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -557,7 +557,8 @@ struct mdss_dsi_ctrl_pdata {
void *clk_mngr;
void *dsi_clk_handle;
void *mdp_clk_handle;
- int m_vote_cnt;
+ int m_dsi_vote_cnt;
+ int m_mdp_vote_cnt;
/* debugfs structure */
struct mdss_dsi_debugfs_info *debugfs_info;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.c b/drivers/video/fbdev/msm/mdss_dsi_clk.c
index a7d1c251fab0..755d6092ea11 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_clk.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_clk.c
@@ -795,8 +795,29 @@ error:
return rc;
}
+bool is_dsi_clk_in_ecg_state(void *client)
+{
+ struct mdss_dsi_clk_client_info *c = client;
+ struct mdss_dsi_clk_mngr *mngr;
+ bool is_ecg = false;
+
+ if (!client) {
+ pr_err("Invalid client params\n");
+ goto end;
+ }
+
+ mngr = c->mngr;
+
+ mutex_lock(&mngr->clk_mutex);
+ is_ecg = (c->core_clk_state == MDSS_DSI_CLK_EARLY_GATE);
+ mutex_unlock(&mngr->clk_mutex);
+
+end:
+ return is_ecg;
+}
+
int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk,
- enum mdss_dsi_clk_state state)
+ enum mdss_dsi_clk_state state, u32 index)
{
int rc = 0;
struct mdss_dsi_clk_client_info *c = client;
@@ -817,7 +838,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk,
c->name, mngr->name, clk, state, c->core_clk_state,
c->link_clk_state);
- MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state);
+ MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state);
/*
* Refcount handling rules:
* 1. Increment refcount whenever ON is called
@@ -883,7 +904,7 @@ int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk,
pr_debug("[%s]%s: change=%d, Core (ref=%d, state=%d), Link (ref=%d, state=%d)\n",
c->name, mngr->name, changed, c->core_refcount,
c->core_clk_state, c->link_refcount, c->link_clk_state);
- MDSS_XLOG(clk, state, c->core_clk_state, c->link_clk_state);
+ MDSS_XLOG(index, clk, state, c->core_clk_state, c->link_clk_state);
if (changed) {
rc = dsi_recheck_clk_state(mngr);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.h b/drivers/video/fbdev/msm/mdss_dsi_clk.h
index 9fe45254fe6d..0b88ddb57166 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_clk.h
+++ b/drivers/video/fbdev/msm/mdss_dsi_clk.h
@@ -197,6 +197,7 @@ int mdss_dsi_clk_deregister(void *client);
* @client: client handle.
* @clk: Type of clock requested (enum mdss_dsi_clk_type).
* @state: clock state requested.
+ * @index: controller index.
*
* This routine is used to request a new clock state for a specific clock. If
* turning ON the clocks, this guarantees that clocks will be on before
@@ -206,7 +207,7 @@ int mdss_dsi_clk_deregister(void *client);
* @return: error code.
*/
int mdss_dsi_clk_req_state(void *client, enum mdss_dsi_clk_type clk,
- enum mdss_dsi_clk_state state);
+ enum mdss_dsi_clk_state state, u32 index);
/**
* mdss_dsi_clk_set_link_rate() - set clock rate for link clocks
@@ -238,4 +239,16 @@ int mdss_dsi_clk_set_link_rate(void *client, enum mdss_dsi_link_clk_type clk,
* @return:error code.
*/
int mdss_dsi_clk_force_toggle(void *client, u32 clk);
+
+/**
+ * is_dsi_clk_in_ecg_state() - Checks the current state of clocks
+ * @client: client handle.
+ *
+ * This routine returns checks the clocks status for client and return
+ * success code based on it.
+ *
+ * @return:true: if clocks are in ECG state
+ * false: for all other cases
+ */
+bool is_dsi_clk_in_ecg_state(void *client);
#endif /* _MDSS_DSI_CLK_H_ */
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index c9168242da60..5f8b45413e32 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -2811,12 +2811,6 @@ static int dsi_event_thread(void *data)
pr_debug("%s: Handling underflow event\n",
__func__);
__dsi_fifo_error_handler(ctrl, true);
- } else {
- pr_err("%s: ctrl recovery not defined\n",
- __func__);
- MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl",
- "dsi0_phy", "dsi1_ctrl", "dsi1_phy", "vbif",
- "vbif_nrt", "dbg_bus", "vbif_dbg_bus", "panic");
}
mutex_unlock(&ctrl->mutex);
}
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 08e06c75522a..d528305af798 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -233,9 +233,11 @@ static int mdss_fb_notify_update(struct msm_fb_data_type *mfd,
}
} else if (notify == NOTIFY_UPDATE_STOP) {
mutex_lock(&mfd->update.lock);
- if (mfd->update.init_done)
+ if (mfd->update.init_done) {
+ mutex_unlock(&mfd->update.lock);
+ mutex_lock(&mfd->no_update.lock);
reinit_completion(&mfd->no_update.comp);
- else {
+ } else {
mutex_unlock(&mfd->update.lock);
pr_err("notify update stop called without init\n");
return -EINVAL;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 9ed44937efe6..6b71025229a0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -4227,9 +4227,11 @@ int mdss_mdp_ctl_start(struct mdss_mdp_ctl *ctl, bool handoff)
return 0;
}
- ret = mdss_mdp_ctl_setup(ctl);
- if (ret)
- return ret;
+ if (mdss_mdp_ctl_is_power_off(ctl)) {
+ ret = mdss_mdp_ctl_setup(ctl);
+ if (ret)
+ return ret;
+ }
sctl = mdss_mdp_get_split_ctl(ctl);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index f08af5d6edd3..a71c7254de7c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -335,6 +335,57 @@ static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
return 0;
}
+static bool __disable_rd_ptr_from_te(char __iomem *pingpong_base)
+{
+ u32 cfg;
+ bool disabled;
+
+ cfg = mdss_mdp_pingpong_read(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
+
+ disabled = BIT(20) & cfg;
+ cfg &= ~BIT(20);
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+
+ return disabled;
+}
+
+static inline void __enable_rd_ptr_from_te(char __iomem *pingpong_base)
+{
+ u32 cfg;
+
+ cfg = mdss_mdp_pingpong_read(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
+ cfg |= BIT(20);
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+}
+
+/*
+* __disable_autorefresh - disables autorefresh feature in the hw.
+*
+* To disable autorefresh, driver needs to make sure no transactions are
+* on-going; for ensuring this, driver must:
+*
+* 1. Disable listening to the external TE (this gives extra time before
+* trigger next transaction).
+* 2. Wait for any on-going transaction (wait for ping pong done interrupt).
+* 3. Disable auto-refresh.
+* 4. Re-enable listening to the external panel TE.
+*
+* So it is responsability of the caller of this function to only call to disable
+* autorefresh if no hw transaction is on-going (wait for ping pong) and if
+* the listening for the external TE is disabled in the tear check logic (this
+* to prevent any race conditions with the hw), as mentioned in the above
+* steps.
+*/
+static inline void __disable_autorefresh(char __iomem *pingpong_base)
+{
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0x0);
+}
+
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
bool locked)
{
@@ -342,7 +393,7 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
struct mdss_mdp_mixer *mixer = NULL, *mixer_right = NULL;
struct mdss_mdp_ctl *ctl = ctx->ctl;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- u32 offset = 0;
+ bool rd_ptr_disabled = false;
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
if (mixer) {
@@ -352,21 +403,32 @@ static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
*/
if (mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG) & BIT(31)) {
- offset = MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG;
+
+ /* 1. disable rd pointer from the external te */
+ rd_ptr_disabled =
+ __disable_rd_ptr_from_te(mixer->pingpong_base);
+
+ /* 2. disable autorefresh */
if (is_pingpong_split(ctl->mfd))
- writel_relaxed(0x0,
- (mdata->slave_pingpong_base + offset));
+ __disable_autorefresh(
+ mdata->slave_pingpong_base);
+
if (is_split_lm(ctl->mfd)) {
- mixer_right =
- mdss_mdp_mixer_get(ctl,
- MDSS_MDP_MIXER_MUX_RIGHT);
+ mixer_right = mdss_mdp_mixer_get(ctl,
+ MDSS_MDP_MIXER_MUX_RIGHT);
+
if (mixer_right)
- writel_relaxed(0x0,
- (mixer_right->pingpong_base + offset));
+ __disable_autorefresh(
+ mixer_right->pingpong_base);
}
- mdss_mdp_pingpong_write(mixer->pingpong_base,
- MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0x0);
+
+ __disable_autorefresh(mixer->pingpong_base);
pr_debug("%s: disabling auto refresh\n", __func__);
+
+ /* 2. re-enable rd pointer from te (if was enabled) */
+ if (rd_ptr_disabled)
+ __enable_rd_ptr_from_te(mixer->pingpong_base);
+
}
rc = mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, locked);
if (rc)
@@ -991,6 +1053,7 @@ static void mdss_mdp_cmd_readptr_done(void *arg)
vsync_time = ktime_get();
ctl->vsync_cnt++;
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));
+ trace_mdp_cmd_readptr_done(ctl->num, atomic_read(&ctx->koff_cnt));
complete_all(&ctx->rdptr_done);
/* If caller is waiting for the read pointer, notify. */
@@ -2364,7 +2427,6 @@ static void mdss_mdp_cmd_pre_programming(struct mdss_mdp_ctl *mctl)
struct mdss_mdp_cmd_ctx *ctx = mctl->intf_ctx[MASTER_CTX];
char __iomem *pp_base;
u32 autorefresh_state;
- u32 cfg;
if (!mctl->is_master)
return;
@@ -2384,11 +2446,8 @@ static void mdss_mdp_cmd_pre_programming(struct mdss_mdp_ctl *mctl)
* instruct MDP to ignore the panel TE so the next auto-refresh
* is delayed until flush bits are set.
*/
- cfg = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
- cfg &= ~BIT(20);
- mdss_mdp_pingpong_write(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ __disable_rd_ptr_from_te(pp_base);
+
ctx->ignore_external_te = true;
}
@@ -2400,7 +2459,6 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl)
{
struct mdss_mdp_cmd_ctx *ctx = mctl->intf_ctx[MASTER_CTX];
char __iomem *pp_base;
- u32 cfg;
if (!mctl->is_master)
return;
@@ -2419,11 +2477,8 @@ static void mdss_mdp_cmd_post_programming(struct mdss_mdp_ctl *mctl)
pp_base = mctl->mixer_left->pingpong_base;
/* enable MDP to listen to the TE */
- cfg = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
- cfg |= BIT(20);
- mdss_mdp_pingpong_write(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ __enable_rd_ptr_from_te(pp_base);
+
ctx->ignore_external_te = false;
}
}
@@ -2675,11 +2730,10 @@ static int mdss_mdp_disable_autorefresh(struct mdss_mdp_ctl *ctl,
mdss_mdp_cmd_wait4_autorefresh_pp(sctl);
/* disable autorefresh */
- mdss_mdp_pingpong_write(pp_base, MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+ __disable_autorefresh(pp_base);
if (is_pingpong_split(ctl->mfd))
- mdss_mdp_pingpong_write(mdata->slave_pingpong_base,
- MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+ __disable_autorefresh(mdata->slave_pingpong_base);
ctx->autorefresh_state = MDP_AUTOREFRESH_OFF;
ctx->autorefresh_frame_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 048e5fce30c6..70b36a08d5ca 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -960,7 +960,7 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0));
return -ENODEV;
}
- pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num, ctx->intf_num,
+ pr_debug("stop ctl=%d video Intf #%d base=%pK", ctl->num, ctx->intf_num,
ctx->base);
ret = mdss_mdp_video_ctx_stop(ctl, pinfo, ctx);
@@ -978,7 +978,7 @@ static int mdss_mdp_video_intfs_stop(struct mdss_mdp_ctl *ctl,
pr_err("Intf %d not in use\n", (inum + MDSS_MDP_INTF0));
return -ENODEV;
}
- pr_debug("stop ctl=%d video Intf #%d base=%p", ctl->num,
+ pr_debug("stop ctl=%d video Intf #%d base=%pK", ctl->num,
sctx->intf_num, sctx->base);
ret = mdss_mdp_video_ctx_stop(ctl, pinfo, sctx);
@@ -2021,7 +2021,7 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
(inum + MDSS_MDP_INTF0));
return -EBUSY;
}
- pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
+ pr_debug("video Intf #%d base=%pK", ctx->intf_num, ctx->base);
ctx->ref_cnt++;
} else {
pr_err("Invalid intf number: %d\n", (inum + MDSS_MDP_INTF0));
@@ -2054,7 +2054,7 @@ static int mdss_mdp_video_intfs_setup(struct mdss_mdp_ctl *ctl,
(inum + MDSS_MDP_INTF0));
return -EBUSY;
}
- pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
+ pr_debug("video Intf #%d base=%pK", ctx->intf_num, ctx->base);
ctx->ref_cnt++;
ctl->intf_ctx[SLAVE_CTX] = ctx;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 036e4e39efda..73350b3a5a6f 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -852,7 +852,7 @@ static int __validate_layer_reconfig(struct mdp_input_layer *layer,
*/
if (pipe->csc_coeff_set != layer->color_space) {
src_fmt = mdss_mdp_get_format_params(layer->buffer.format);
- if (pipe->src_fmt->is_yuv && src_fmt->is_yuv) {
+ if (pipe->src_fmt->is_yuv && src_fmt && src_fmt->is_yuv) {
status = -EPERM;
pr_err("csc change is not permitted on used pipe\n");
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 946e33033ab7..298b8743f0a6 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1533,7 +1533,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
}
break;
default:
- pr_err("invalid state of buf %p=%d\n",
+ pr_err("invalid state of buf %pK=%d\n",
buf, buf->state);
BUG();
break;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index f79212ea740d..c6bef7c22193 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -2906,7 +2906,7 @@ int mdss_mdp_pp_resume(struct msm_fb_data_type *mfd)
mfd->index);
return 0;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -3250,7 +3250,7 @@ static int pp_ad_calc_bl(struct msm_fb_data_type *mfd, int bl_in, int *bl_out,
mfd->index);
return 0;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -5754,7 +5754,7 @@ static int pp_ad_invalidate_input(struct msm_fb_data_type *mfd)
mfd->index);
return 0;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -5789,7 +5789,7 @@ int mdss_mdp_ad_config(struct msm_fb_data_type *mfd,
mfd->index);
return ret;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -5929,7 +5929,7 @@ int mdss_mdp_ad_input(struct msm_fb_data_type *mfd,
mfd->index);
return ret;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -6298,7 +6298,7 @@ static int mdss_mdp_ad_ipc_reset(struct msm_fb_data_type *mfd)
mfd->index);
return 0;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
@@ -6339,7 +6339,7 @@ static int mdss_mdp_ad_setup(struct msm_fb_data_type *mfd)
mfd->index);
return 0;
} else if (ret || !ad) {
- pr_err("Failed to get ad info: ret = %d, ad = 0x%p.\n",
+ pr_err("Failed to get ad info: ret = %d, ad = 0x%pK\n",
ret, ad);
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c
index 5bd627853c59..e51cf44c2de2 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c
@@ -367,7 +367,7 @@ int pp_dither_cache_params(struct mdp_dither_cfg_data *config,
{
int ret = 0;
if (!config || !mdss_pp_res) {
- pr_err("invalid param config %pi pp_res %pK\n",
+ pr_err("invalid param config %pK pp_res %pK\n",
config, mdss_pp_res);
return -EINVAL;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_trace.h b/drivers/video/fbdev/msm/mdss_mdp_trace.h
index 648e4fcd1cd2..b79b4c70f5dc 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_trace.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_trace.h
@@ -372,6 +372,22 @@ TRACE_EVENT(mdp_cmd_pingpong_done,
__entry->koff_cnt)
);
+TRACE_EVENT(mdp_cmd_readptr_done,
+ TP_PROTO(u32 ctl_num, int koff_cnt),
+ TP_ARGS(ctl_num, koff_cnt),
+ TP_STRUCT__entry(
+ __field(u32, ctl_num)
+ __field(int, koff_cnt)
+ ),
+ TP_fast_assign(
+ __entry->ctl_num = ctl_num;
+ __entry->koff_cnt = koff_cnt;
+ ),
+ TP_printk("ctl num:%d kickoff:%d",
+ __entry->ctl_num,
+ __entry->koff_cnt)
+);
+
TRACE_EVENT(mdp_cmd_release_bw,
TP_PROTO(u32 ctl_num),
TP_ARGS(ctl_num),
diff --git a/drivers/video/fbdev/msm/mdss_util.c b/drivers/video/fbdev/msm/mdss_util.c
index d2610ff80878..65941601cfdc 100644
--- a/drivers/video/fbdev/msm/mdss_util.c
+++ b/drivers/video/fbdev/msm/mdss_util.c
@@ -23,6 +23,7 @@ int mdss_register_irq(struct mdss_hw *hw)
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (!hw || hw->hw_ndx >= MDSS_MAX_HW_BLK)
return -EINVAL;
@@ -33,10 +34,12 @@ int mdss_register_irq(struct mdss_hw *hw)
if (!mdss_irq_handlers[hw->hw_ndx])
mdss_irq_handlers[hw->hw_ndx] = hw;
else
- pr_err("panel %d's irq at %pK is already registered\n",
- hw->hw_ndx, hw->irq_handler);
+ err = true;
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+ if (err)
+ pr_err("panel %d's irq at %pK is already registered\n",
+ hw->hw_ndx, hw->irq_handler);
return 0;
}
@@ -76,6 +79,7 @@ void mdss_disable_irq(struct mdss_hw *hw)
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -87,7 +91,7 @@ void mdss_disable_irq(struct mdss_hw *hw)
spin_lock_irqsave(&mdss_lock, irq_flags);
if (!(hw->irq_info->irq_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_mask &= ~ndx_bit;
if (hw->irq_info->irq_mask == 0) {
@@ -96,12 +100,16 @@ void mdss_disable_irq(struct mdss_hw *hw)
}
}
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
/* called from interrupt context */
void mdss_disable_irq_nosync(struct mdss_hw *hw)
{
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -113,7 +121,7 @@ void mdss_disable_irq_nosync(struct mdss_hw *hw)
spin_lock(&mdss_lock);
if (!(hw->irq_info->irq_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_mask &= ~ndx_bit;
if (hw->irq_info->irq_mask == 0) {
@@ -122,6 +130,9 @@ void mdss_disable_irq_nosync(struct mdss_hw *hw)
}
}
spin_unlock(&mdss_lock);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
@@ -176,6 +187,7 @@ void mdss_disable_irq_wake(struct mdss_hw *hw)
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -188,7 +200,7 @@ void mdss_disable_irq_wake(struct mdss_hw *hw)
spin_lock_irqsave(&mdss_lock, irq_flags);
if (!(hw->irq_info->irq_wake_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_wake_mask &= ~ndx_bit;
if (hw->irq_info->irq_wake_ena) {
@@ -197,6 +209,9 @@ void mdss_disable_irq_wake(struct mdss_hw *hw)
}
}
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
struct mdss_util_intf mdss_util = {
diff --git a/drivers/video/fbdev/msm/mhl3/si_mhl2_edid_3d.c b/drivers/video/fbdev/msm/mhl3/si_mhl2_edid_3d.c
index 20d48575f323..4c9045d6a2a7 100644
--- a/drivers/video/fbdev/msm/mhl3/si_mhl2_edid_3d.c
+++ b/drivers/video/fbdev/msm/mhl3/si_mhl2_edid_3d.c
@@ -1118,7 +1118,7 @@ static void tx_prune_dtd_list(struct edid_3d_data_t *mhl_edid_3d_data,
if ((0 != p_desc->dtd.pixel_clock_low) ||
(0 != p_desc->dtd.pixel_clock_high)) {
MHL_TX_EDID_INFO(
- "pix clock non-zero p_desc:%p", p_desc)
+ "pix clock non-zero p_desc:%pK", p_desc)
if ((0 == p_desc->dtd.horz_active_7_0) &&
(0 == p_desc->dtd.horz_active_blanking_high.
horz_active_11_8)) {
@@ -1722,9 +1722,10 @@ static void prune_svd_list(
("\n\nInvalid extension size\n\n"));
while (pb_src < pb_limit) {
MHL_TX_EDID_INFO(
- "moving data up %p(0x%02X) "
- "<- %p(0x%02X)\n",
- pb_dest, (uint16_t)*pb_dest,
+ "moving data up %pK(0x%02X) ",
+ pb_dest, (uint16_t)*pb_dest);
+ MHL_TX_EDID_INFO(
+ "<- %pK(0x%02X)\n",
pb_src, (uint16_t)*pb_src);
*pb_dest++ = *pb_src++;
}
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index b5b5a026733e..0c43a2642ede 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -2081,7 +2081,11 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle,
{
int rc = 0;
struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- int i;
+ int i, *vote_cnt;
+
+ void *m_clk_handle;
+ bool is_ecg = false;
+ int state = MDSS_DSI_CLK_OFF;
if (!ctrl) {
pr_err("%s: Invalid arg\n", __func__);
@@ -2113,6 +2117,18 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle,
}
/*
+ * it should add and remove extra votes based on voting clients to avoid
+ * removal of legitimate vote from DSI client.
+ */
+ if (mctrl && (clk_handle == ctrl->dsi_clk_handle)) {
+ m_clk_handle = mctrl->dsi_clk_handle;
+ vote_cnt = &mctrl->m_dsi_vote_cnt;
+ } else if (mctrl) {
+ m_clk_handle = mctrl->mdp_clk_handle;
+ vote_cnt = &mctrl->m_mdp_vote_cnt;
+ }
+
+ /*
* When DSI is used in split mode, the link clock for master controller
* has to be turned on first before the link clock for slave can be
* turned on. In case the current controller is a slave, an ON vote is
@@ -2124,18 +2140,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle,
__func__, ctrl->ndx, clk_type, clk_state,
__builtin_return_address(0), mctrl ? 1 : 0);
if (mctrl && (clk_type & MDSS_DSI_LINK_CLK)) {
- rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle,
- MDSS_DSI_ALL_CLKS,
- MDSS_DSI_CLK_ON);
+ if (clk_state != MDSS_DSI_CLK_ON) {
+ /* preserve clk state; do not turn off forcefully */
+ is_ecg = is_dsi_clk_in_ecg_state(m_clk_handle);
+ if (is_ecg)
+ state = MDSS_DSI_CLK_EARLY_GATE;
+ }
+
+ rc = mdss_dsi_clk_req_state(m_clk_handle,
+ MDSS_DSI_ALL_CLKS, MDSS_DSI_CLK_ON, mctrl->ndx);
if (rc) {
pr_err("%s: failed to turn on mctrl clocks, rc=%d\n",
__func__, rc);
goto error;
}
- ctrl->m_vote_cnt++;
+ (*vote_cnt)++;
}
- rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state);
+ rc = mdss_dsi_clk_req_state(clk_handle, clk_type, clk_state, ctrl->ndx);
if (rc) {
pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
goto error;
@@ -2164,24 +2186,24 @@ int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, void *clk_handle,
* for ON, since the previous ECG state must have
* removed two votes to let clocks turn off.
*
- * To satisfy the above requirement, m_vote_cnt keeps track of
+ * To satisfy the above requirement, vote_cnt keeps track of
* the number of ON votes for master requested by slave. For
- * every OFF/ECG state request, Either 2 or m_vote_cnt number of
+ * every OFF/ECG state request, Either 2 or vote_cnt number of
* votes are removed depending on which is lower.
*/
- for (i = 0; (i < ctrl->m_vote_cnt && i < 2); i++) {
- rc = mdss_dsi_clk_req_state(mctrl->dsi_clk_handle,
- MDSS_DSI_ALL_CLKS,
- MDSS_DSI_CLK_OFF);
+ for (i = 0; (i < *vote_cnt && i < 2); i++) {
+ rc = mdss_dsi_clk_req_state(m_clk_handle,
+ MDSS_DSI_ALL_CLKS, state, mctrl->ndx);
if (rc) {
pr_err("%s: failed to set mctrl clk state, rc = %d\n",
__func__, rc);
goto error;
}
}
- ctrl->m_vote_cnt -= i;
- pr_debug("%s: ctrl=%d, m_vote_cnt=%d\n", __func__, ctrl->ndx,
- ctrl->m_vote_cnt);
+ (*vote_cnt) -= i;
+ pr_debug("%s: ctrl=%d, vote_cnt=%d dsi_vote_cnt=%d mdp_vote_cnt:%d\n",
+ __func__, ctrl->ndx, *vote_cnt, mctrl->m_dsi_vote_cnt,
+ mctrl->m_mdp_vote_cnt);
}
error:
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2a5acbdc6327..fd2eb059b991 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -177,6 +177,14 @@ struct clk_rate_request {
* @set_flags: Set custom flags which deals with hardware specifics. Returns 0
* on success, -EEROR otherwise.
*
+ * @list_registers: Queries the hardware to get the current register contents.
+ * This callback is optional and required clocks could
+ * add this callback.
+ *
+ * @list_rate: Return the nth supported frequency for a given clock which is
+ * below rate_max on success and -ENXIO in case of no frequency
+ * table.
+ *
* The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
* implementations to split any work between atomic (enable) and sleepable
* (prepare) contexts. If enabling a clock requires code that might sleep,
@@ -217,6 +225,10 @@ struct clk_ops {
void (*init)(struct clk_hw *hw);
int (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
int (*set_flags)(struct clk_hw *hw, unsigned flags);
+ void (*list_registers)(struct seq_file *f,
+ struct clk_hw *hw);
+ long (*list_rate)(struct clk_hw *hw, unsigned n,
+ unsigned long rate_max);
};
/**
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 5110d4211866..ccb98b459c59 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -421,7 +421,11 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
}
#endif /* CONFIG_DEBUG_SET_MODULE_RONX */
-int sk_filter(struct sock *sk, struct sk_buff *skb);
+int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
+static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
+{
+ return sk_filter_trim_cap(sk, skb, 1);
+}
int bpf_prog_select_runtime(struct bpf_prog *fp);
void bpf_prog_free(struct bpf_prog *fp);
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index e66d388651b8..c3ffe51d8069 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -98,7 +98,7 @@ enum ipa_dp_evt_type {
};
/**
- * enum hdr_total_len_or_pad_type - type vof alue held by TOTAL_LEN_OR_PAD
+ * enum hdr_total_len_or_pad_type - type of value held by TOTAL_LEN_OR_PAD
* field in header configuration register.
* @IPA_HDR_PAD: field is used as padding length
* @IPA_HDR_TOTAL_LEN: field is used as total length
@@ -433,6 +433,55 @@ typedef void (*ipa_notify_cb)(void *priv, enum ipa_dp_evt_type evt,
unsigned long data);
/**
+ * enum ipa_wdi_meter_evt_type - type of event client callback is
+ * for AP+STA mode metering
+ * @IPA_GET_WDI_SAP_STATS: get IPA_stats betwen SAP and STA -
+ * use ipa_get_wdi_sap_stats structure
+ * @IPA_SET_WIFI_QUOTA: set quota limit on STA -
+ * use ipa_set_wifi_quota structure
+ */
+enum ipa_wdi_meter_evt_type {
+ IPA_GET_WDI_SAP_STATS,
+ IPA_SET_WIFI_QUOTA,
+};
+
+struct ipa_get_wdi_sap_stats {
+ /* indicate to reset stats after query */
+ uint8_t reset_stats;
+ /* indicate valid stats from wlan-fw */
+ uint8_t stats_valid;
+ /* Tx: SAP->STA */
+ uint64_t ipv4_tx_packets;
+ uint64_t ipv4_tx_bytes;
+ /* Rx: STA->SAP */
+ uint64_t ipv4_rx_packets;
+ uint64_t ipv4_rx_bytes;
+ uint64_t ipv6_tx_packets;
+ uint64_t ipv6_tx_bytes;
+ uint64_t ipv6_rx_packets;
+ uint64_t ipv6_rx_bytes;
+};
+
+/**
+ * struct ipa_set_wifi_quota - structure used for
+ * IPA_SET_WIFI_QUOTA.
+ *
+ * @quota_bytes: Quota (in bytes) for the STA interface.
+ * @set_quota: Indicate whether to set the quota (use 1) or
+ * unset the quota.
+ *
+ */
+struct ipa_set_wifi_quota {
+ uint64_t quota_bytes;
+ uint8_t set_quota;
+ /* indicate valid quota set from wlan-fw */
+ uint8_t set_valid;
+};
+
+typedef void (*ipa_wdi_meter_notifier_cb)(enum ipa_wdi_meter_evt_type evt,
+ void *data);
+
+/**
* struct ipa_connect_params - low-level client connect input parameters. Either
* client allocates the data and desc FIFO and specifies that in data+desc OR
* specifies sizes and pipe_mem pref and IPA does the allocation.
@@ -1001,6 +1050,7 @@ struct ipa_wdi_dl_params_smmu {
* @ul_smmu: WDI_RX configuration info when WLAN uses SMMU
* @dl_smmu: WDI_TX configuration info when WLAN uses SMMU
* @smmu_enabled: true if WLAN uses SMMU
+ * @ipa_wdi_meter_notifier_cb: Get WDI stats and quato info
*/
struct ipa_wdi_in_params {
struct ipa_sys_connect_params sys;
@@ -1011,6 +1061,9 @@ struct ipa_wdi_in_params {
struct ipa_wdi_dl_params_smmu dl_smmu;
} u;
bool smmu_enabled;
+#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
+ ipa_wdi_meter_notifier_cb wdi_notify;
+#endif
};
/**
@@ -1265,6 +1318,9 @@ int ipa_resume_wdi_pipe(u32 clnt_hdl);
int ipa_suspend_wdi_pipe(u32 clnt_hdl);
int ipa_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats);
u16 ipa_get_smem_restr_bytes(void);
+int ipa_broadcast_wdi_quota_reach_ind(uint32_t fid,
+ uint64_t num_bytes);
+
/*
* To retrieve doorbell physical address of
* wlan pipes
@@ -1845,6 +1901,12 @@ static inline int ipa_suspend_wdi_pipe(u32 clnt_hdl)
return -EPERM;
}
+static inline int ipa_broadcast_wdi_quota_reach_ind(uint32_t fid,
+ uint64_t num_bytes)
+{
+ return -EPERM;
+}
+
static inline int ipa_uc_wdi_get_dbpa(
struct ipa_wdi_db_params *out)
{
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 6848454c5447..5d0899df64ff 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -53,6 +53,8 @@ extern unsigned int sysctl_sched_spill_nr_run;
extern unsigned int sysctl_sched_spill_load_pct;
extern unsigned int sysctl_sched_upmigrate_pct;
extern unsigned int sysctl_sched_downmigrate_pct;
+extern unsigned int sysctl_sched_group_upmigrate_pct;
+extern unsigned int sysctl_sched_group_downmigrate_pct;
extern unsigned int sysctl_early_detection_duration;
extern unsigned int sysctl_sched_boost;
extern unsigned int sysctl_sched_small_wakee_task_load_pct;
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 440248ba4123..7e6e4665212f 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -395,6 +395,15 @@ struct usb_bus {
struct mon_bus *mon_bus; /* non-null when associated */
int monitored; /* non-zero when monitored */
#endif
+ unsigned skip_resume:1; /* All USB devices are brought into full
+ * power state after system resume. It
+ * is desirable for some buses to keep
+ * their devices in suspend state even
+ * after system resume. The devices
+ * are resumed later when a remote
+ * wakeup is detected or an interface
+ * driver starts I/O.
+ */
};
struct usb_dev_state;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 5ed36a59b08e..213601d620e0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1171,6 +1171,7 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp)
}
bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
+int tcp_filter(struct sock *sk, struct sk_buff *skb);
#undef STATE_TRACE
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 7778ff3947de..72bbed9ad5db 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -133,6 +133,7 @@ TRACE_EVENT(sched_task_load,
__field( u32, flags )
__field( int, best_cpu )
__field( u64, latency )
+ __field( int, grp_id )
),
TP_fast_assign(
@@ -148,12 +149,13 @@ TRACE_EVENT(sched_task_load,
__entry->latency = p->state == TASK_WAKING ?
sched_ktime_clock() -
p->ravg.mark_start : 0;
+ __entry->grp_id = p->grp ? p->grp->id : 0;
),
- TP_printk("%d (%s): demand=%u boost=%d reason=%d sync=%d need_idle=%d flags=%x best_cpu=%d latency=%llu",
+ TP_printk("%d (%s): demand=%u boost=%d reason=%d sync=%d need_idle=%d flags=%x grp=%d best_cpu=%d latency=%llu",
__entry->pid, __entry->comm, __entry->demand,
__entry->boost, __entry->reason, __entry->sync,
- __entry->need_idle, __entry->flags,
+ __entry->need_idle, __entry->flags, __entry->grp_id,
__entry->best_cpu, __entry->latency)
);
@@ -164,9 +166,12 @@ TRACE_EVENT(sched_set_preferred_cluster,
TP_ARGS(grp, total_demand),
TP_STRUCT__entry(
- __field( int, id )
- __field( u64, demand )
- __field( int, cluster_first_cpu )
+ __field( int, id )
+ __field( u64, demand )
+ __field( int, cluster_first_cpu )
+ __array( char, comm, TASK_COMM_LEN )
+ __field( pid_t, pid )
+ __field(unsigned int, task_demand )
),
TP_fast_assign(
@@ -245,19 +250,19 @@ DEFINE_EVENT(sched_cpu_load, sched_cpu_load_cgroup,
TRACE_EVENT(sched_set_boost,
- TP_PROTO(int ref_count),
+ TP_PROTO(int type),
- TP_ARGS(ref_count),
+ TP_ARGS(type),
TP_STRUCT__entry(
- __field(unsigned int, ref_count )
+ __field(int, type )
),
TP_fast_assign(
- __entry->ref_count = ref_count;
+ __entry->type = type;
),
- TP_printk("ref_count=%d", __entry->ref_count)
+ TP_printk("type %d", __entry->type)
);
#if defined(CREATE_TRACE_POINTS) && defined(CONFIG_SCHED_HMP)
diff --git a/include/uapi/media/msm_sde_rotator.h b/include/uapi/media/msm_sde_rotator.h
index 12976e3f14d7..4487edf0c854 100644
--- a/include/uapi/media/msm_sde_rotator.h
+++ b/include/uapi/media/msm_sde_rotator.h
@@ -86,10 +86,4 @@ struct msm_sde_rotator_fence {
/* SDE Rotator private control ID's */
#define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000)
-/*
- * This control Id indicates this context is associated with the
- * secure camera
- */
-#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000)
-
#endif /* __UAPI_MSM_SDE_ROTATOR_H__ */
diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
index 7d0d34c53e08..7c0382a3eace 100644
--- a/kernel/sched/Makefile
+++ b/kernel/sched/Makefile
@@ -15,7 +15,7 @@ obj-y += core.o loadavg.o clock.o cputime.o
obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
obj-y += wait.o completion.o idle.o sched_avg.o
obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
-obj-$(CONFIG_SCHED_HMP) += hmp.o
+obj-$(CONFIG_SCHED_HMP) += hmp.o boost.o
obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
obj-$(CONFIG_SCHEDSTATS) += stats.o
obj-$(CONFIG_SCHED_DEBUG) += debug.o
diff --git a/kernel/sched/boost.c b/kernel/sched/boost.c
new file mode 100644
index 000000000000..fcfda385b74a
--- /dev/null
+++ b/kernel/sched/boost.c
@@ -0,0 +1,226 @@
+/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sched.h"
+#include <linux/of.h>
+#include <linux/sched/core_ctl.h>
+#include <trace/events/sched.h>
+
+/*
+ * Scheduler boost is a mechanism to temporarily place tasks on CPUs
+ * with higher capacity than those where a task would have normally
+ * ended up with their load characteristics. Any entity enabling
+ * boost is responsible for disabling it as well.
+ */
+
+unsigned int sysctl_sched_boost;
+static enum sched_boost_policy boost_policy;
+static enum sched_boost_policy boost_policy_dt = SCHED_BOOST_NONE;
+static DEFINE_MUTEX(boost_mutex);
+static unsigned int freq_aggr_threshold_backup;
+
+static inline void boost_kick(int cpu)
+{
+ struct rq *rq = cpu_rq(cpu);
+
+ if (!test_and_set_bit(BOOST_KICK, &rq->hmp_flags))
+ smp_send_reschedule(cpu);
+}
+
+static void boost_kick_cpus(void)
+{
+ int i;
+ struct cpumask kick_mask;
+
+ if (boost_policy != SCHED_BOOST_ON_BIG)
+ return;
+
+ cpumask_andnot(&kick_mask, cpu_online_mask, cpu_isolated_mask);
+
+ for_each_cpu(i, &kick_mask) {
+ if (cpu_capacity(i) != max_capacity)
+ boost_kick(i);
+ }
+}
+
+int got_boost_kick(void)
+{
+ int cpu = smp_processor_id();
+ struct rq *rq = cpu_rq(cpu);
+
+ return test_bit(BOOST_KICK, &rq->hmp_flags);
+}
+
+void clear_boost_kick(int cpu)
+{
+ struct rq *rq = cpu_rq(cpu);
+
+ clear_bit(BOOST_KICK, &rq->hmp_flags);
+}
+
+/*
+ * Scheduler boost type and boost policy might at first seem unrelated,
+ * however, there exists a connection between them that will allow us
+ * to use them interchangeably during placement decisions. We'll explain
+ * the connection here in one possible way so that the implications are
+ * clear when looking at placement policies.
+ *
+ * When policy = SCHED_BOOST_NONE, type is either none or RESTRAINED
+ * When policy = SCHED_BOOST_ON_ALL or SCHED_BOOST_ON_BIG, type can
+ * neither be none nor RESTRAINED.
+ */
+static void set_boost_policy(int type)
+{
+ if (type == SCHED_BOOST_NONE || type == RESTRAINED_BOOST) {
+ boost_policy = SCHED_BOOST_NONE;
+ return;
+ }
+
+ if (boost_policy_dt) {
+ boost_policy = boost_policy_dt;
+ return;
+ }
+
+ if (min_possible_efficiency != max_possible_efficiency) {
+ boost_policy = SCHED_BOOST_ON_BIG;
+ return;
+ }
+
+ boost_policy = SCHED_BOOST_ON_ALL;
+}
+
+enum sched_boost_policy sched_boost_policy(void)
+{
+ return boost_policy;
+}
+
+static bool verify_boost_params(int old_val, int new_val)
+{
+ /*
+ * Boost can only be turned on or off. There is no possiblity of
+ * switching from one boost type to another or to set the same
+ * kind of boost several times.
+ */
+ return !(!!old_val == !!new_val);
+}
+
+static void _sched_set_boost(int old_val, int type)
+{
+ switch (type) {
+ case NO_BOOST:
+ if (old_val == FULL_THROTTLE_BOOST)
+ core_ctl_set_boost(false);
+ else if (old_val == CONSERVATIVE_BOOST)
+ restore_cgroup_boost_settings();
+ else
+ update_freq_aggregate_threshold(
+ freq_aggr_threshold_backup);
+ break;
+
+ case FULL_THROTTLE_BOOST:
+ core_ctl_set_boost(true);
+ boost_kick_cpus();
+ break;
+
+ case CONSERVATIVE_BOOST:
+ update_cgroup_boost_settings();
+ boost_kick_cpus();
+ break;
+
+ case RESTRAINED_BOOST:
+ freq_aggr_threshold_backup =
+ update_freq_aggregate_threshold(1);
+ break;
+
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ set_boost_policy(type);
+ sysctl_sched_boost = type;
+ trace_sched_set_boost(type);
+}
+
+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;
+
+ if (!of_property_read_string(sn, "boost-policy", &boost_policy)) {
+ if (!strcmp(boost_policy, "boost-on-big"))
+ boost_policy_dt = SCHED_BOOST_ON_BIG;
+ else if (!strcmp(boost_policy, "boost-on-all"))
+ boost_policy_dt = SCHED_BOOST_ON_ALL;
+ }
+}
+
+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))
+ _sched_set_boost(sysctl_sched_boost, type);
+ else
+ ret = -EINVAL;
+
+ mutex_unlock(&boost_mutex);
+ return ret;
+}
+
+int sched_boost_handler(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int ret;
+ unsigned int *data = (unsigned int *)table->data;
+ unsigned int old_val;
+
+ if (!sched_enable_hmp)
+ return -EINVAL;
+
+ mutex_lock(&boost_mutex);
+
+ old_val = *data;
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+ if (ret || !write)
+ goto done;
+
+ if (verify_boost_params(old_val, *data)) {
+ _sched_set_boost(old_val, *data);
+ } else {
+ *data = old_val;
+ ret = -EINVAL;
+ }
+
+done:
+ mutex_unlock(&boost_mutex);
+ return ret;
+}
+
+int sched_boost(void)
+{
+ return sysctl_sched_boost;
+}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 84563da000cf..a5d101e8a5f2 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7846,7 +7846,6 @@ void __init sched_init_smp(void)
hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE);
update_cluster_topology();
- init_sched_hmp_boost_policy();
init_hrtick();
@@ -7895,7 +7894,7 @@ void __init sched_init(void)
BUG_ON(num_possible_cpus() > BITS_PER_LONG);
- sched_hmp_parse_dt();
+ sched_boost_parse_dt();
init_clusters();
#ifdef CONFIG_FAIR_GROUP_SCHED
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 1674b1054f83..3db77aff2433 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2596,6 +2596,7 @@ static u32 __compute_runnable_contrib(u64 n)
#define SBC_FLAG_COLOC_CLUSTER 0x10000
#define SBC_FLAG_WAKER_CLUSTER 0x20000
#define SBC_FLAG_BACKUP_CLUSTER 0x40000
+#define SBC_FLAG_BOOST_CLUSTER 0x80000
struct cpu_select_env {
struct task_struct *p;
@@ -2605,7 +2606,7 @@ struct cpu_select_env {
u8 need_waker_cluster:1;
u8 sync:1;
u8 ignore_prev_cpu:1;
- enum sched_boost_type boost_type;
+ enum sched_boost_policy boost_policy;
int prev_cpu;
DECLARE_BITMAP(candidate_list, NR_CPUS);
DECLARE_BITMAP(backup_list, NR_CPUS);
@@ -2705,10 +2706,38 @@ select_least_power_cluster(struct cpu_select_env *env)
struct sched_cluster *cluster;
if (env->rtg) {
- env->task_load = scale_load_to_cpu(task_load(env->p),
- cluster_first_cpu(env->rtg->preferred_cluster));
- env->sbc_best_cluster_flag |= SBC_FLAG_COLOC_CLUSTER;
- return env->rtg->preferred_cluster;
+ int cpu = cluster_first_cpu(env->rtg->preferred_cluster);
+
+ env->task_load = scale_load_to_cpu(task_load(env->p), cpu);
+
+ if (task_load_will_fit(env->p, env->task_load,
+ cpu, env->boost_policy)) {
+ env->sbc_best_cluster_flag |= SBC_FLAG_COLOC_CLUSTER;
+
+ if (env->boost_policy == SCHED_BOOST_NONE)
+ return env->rtg->preferred_cluster;
+
+ for_each_sched_cluster(cluster) {
+ if (cluster != env->rtg->preferred_cluster) {
+ __set_bit(cluster->id,
+ env->backup_list);
+ __clear_bit(cluster->id,
+ env->candidate_list);
+ }
+ }
+
+ return env->rtg->preferred_cluster;
+ }
+
+ /*
+ * Since the task load does not fit on the preferred
+ * cluster anymore, pretend that the task does not
+ * have any preferred cluster. This allows the waking
+ * task to get the appropriate CPU it needs as per the
+ * non co-location placement policy without having to
+ * wait until the preferred cluster is updated.
+ */
+ env->rtg = NULL;
}
for_each_sched_cluster(cluster) {
@@ -2718,7 +2747,7 @@ select_least_power_cluster(struct cpu_select_env *env)
env->task_load = scale_load_to_cpu(task_load(env->p),
cpu);
if (task_load_will_fit(env->p, env->task_load, cpu,
- env->boost_type))
+ env->boost_policy))
return cluster;
__set_bit(cluster->id, env->backup_list);
@@ -2961,7 +2990,14 @@ static void find_best_cpu_in_cluster(struct sched_cluster *c,
update_spare_capacity(stats, env, i, c->capacity,
env->cpu_load);
- if (env->boost_type == SCHED_BOOST_ON_ALL ||
+ /*
+ * need_idle takes precedence over sched boost but when both
+ * are set, idlest CPU with in all the clusters is selected
+ * when boost_policy = BOOST_ON_ALL whereas idlest CPU in the
+ * big cluster is selected within boost_policy = BOOST_ON_BIG.
+ */
+ if ((!env->need_idle &&
+ env->boost_policy != SCHED_BOOST_NONE) ||
env->need_waker_cluster ||
sched_cpu_high_irqload(i) ||
spill_threshold_crossed(env, cpu_rq(i)))
@@ -3005,7 +3041,7 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats)
struct task_struct *task = env->p;
struct sched_cluster *cluster;
- if (env->boost_type != SCHED_BOOST_NONE || env->reason ||
+ if (env->boost_policy != SCHED_BOOST_NONE || env->reason ||
!task->ravg.mark_start ||
env->need_idle || !sched_short_sleep_task_threshold)
return false;
@@ -3034,7 +3070,7 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats)
cluster = cpu_rq(prev_cpu)->cluster;
if (!task_load_will_fit(task, env->task_load, prev_cpu,
- sched_boost_type())) {
+ sched_boost_policy())) {
__set_bit(cluster->id, env->backup_list);
__clear_bit(cluster->id, env->candidate_list);
@@ -3056,7 +3092,7 @@ bias_to_prev_cpu(struct cpu_select_env *env, struct cluster_cpu_stats *stats)
static inline bool
wake_to_waker_cluster(struct cpu_select_env *env)
{
- return env->boost_type == SCHED_BOOST_NONE &&
+ return env->boost_policy == SCHED_BOOST_NONE &&
!env->need_idle && !env->reason && env->sync &&
task_load(current) > sched_big_waker_task_load &&
task_load(env->p) < sched_small_wakee_task_load;
@@ -3098,7 +3134,6 @@ static int select_best_cpu(struct task_struct *p, int target, int reason,
.reason = reason,
.need_idle = wake_to_idle(p),
.need_waker_cluster = 0,
- .boost_type = sched_boost_type(),
.sync = sync,
.prev_cpu = target,
.ignore_prev_cpu = 0,
@@ -3107,6 +3142,9 @@ static int select_best_cpu(struct task_struct *p, int target, int reason,
.sbc_best_cluster_flag = 0,
};
+ env.boost_policy = task_sched_boost(p) ?
+ sched_boost_policy() : SCHED_BOOST_NONE;
+
bitmap_copy(env.candidate_list, all_cluster_ids, NR_CPUS);
bitmap_zero(env.backup_list, NR_CPUS);
@@ -3178,12 +3216,23 @@ retry:
sbc_flag |= env.sbc_best_flag;
target = stats.best_cpu;
} else {
- if (env.rtg) {
+ if (env.rtg && env.boost_policy == SCHED_BOOST_NONE) {
env.rtg = NULL;
goto retry;
}
- find_backup_cluster(&env, &stats);
+ /*
+ * With boost_policy == SCHED_BOOST_ON_BIG, we reach here with
+ * backup_list = little cluster, candidate_list = none and
+ * stats->best_capacity_cpu points the best spare capacity
+ * CPU among the CPUs in the big cluster.
+ */
+ if (env.boost_policy == SCHED_BOOST_ON_BIG &&
+ stats.best_capacity_cpu >= 0)
+ sbc_flag |= SBC_FLAG_BOOST_CLUSTER;
+ else
+ find_backup_cluster(&env, &stats);
+
if (stats.best_capacity_cpu >= 0) {
target = stats.best_capacity_cpu;
sbc_flag |= SBC_FLAG_BEST_CAP_CPU;
@@ -3193,8 +3242,8 @@ retry:
out:
sbc_flag |= env.sbc_best_cluster_flag;
rcu_read_unlock();
- trace_sched_task_load(p, sched_boost(), env.reason, env.sync,
- env.need_idle, sbc_flag, target);
+ trace_sched_task_load(p, sched_boost_policy() && task_sched_boost(p),
+ env.reason, env.sync, env.need_idle, sbc_flag, target);
return target;
}
@@ -3402,11 +3451,9 @@ static inline int migration_needed(struct task_struct *p, int cpu)
if (task_will_be_throttled(p))
return 0;
- if (sched_boost_type() == SCHED_BOOST_ON_BIG) {
- if (cpu_capacity(cpu) != max_capacity)
- return UP_MIGRATION;
- return 0;
- }
+ if (sched_boost_policy() == SCHED_BOOST_ON_BIG &&
+ cpu_capacity(cpu) != max_capacity && task_sched_boost(p))
+ return UP_MIGRATION;
if (sched_cpu_high_irqload(cpu))
return IRQLOAD_MIGRATION;
@@ -3420,7 +3467,7 @@ static inline int migration_needed(struct task_struct *p, int cpu)
return DOWN_MIGRATION;
}
- if (!grp && !task_will_fit(p, cpu)) {
+ if (!task_will_fit(p, cpu)) {
rcu_read_unlock();
return UP_MIGRATION;
}
@@ -6648,10 +6695,7 @@ enum fbq_type { regular, remote, all };
#define LBF_NEED_BREAK 0x02
#define LBF_DST_PINNED 0x04
#define LBF_SOME_PINNED 0x08
-#define LBF_SCHED_BOOST_ACTIVE_BALANCE 0x40
#define LBF_BIG_TASK_ACTIVE_BALANCE 0x80
-#define LBF_HMP_ACTIVE_BALANCE (LBF_SCHED_BOOST_ACTIVE_BALANCE | \
- LBF_BIG_TASK_ACTIVE_BALANCE)
#define LBF_IGNORE_BIG_TASKS 0x100
#define LBF_IGNORE_PREFERRED_CLUSTER_TASKS 0x200
#define LBF_MOVED_RELATED_THREAD_GROUP_TASK 0x400
@@ -6682,6 +6726,7 @@ struct lb_env {
enum fbq_type fbq_type;
struct list_head tasks;
+ enum sched_boost_policy boost_policy;
};
/*
@@ -6826,9 +6871,14 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)
/* Record that we found atleast one task that could run on dst_cpu */
env->flags &= ~LBF_ALL_PINNED;
- if (cpu_capacity(env->dst_cpu) > cpu_capacity(env->src_cpu) &&
- nr_big_tasks(env->src_rq) && !is_big_task(p))
- return 0;
+ if (cpu_capacity(env->dst_cpu) > cpu_capacity(env->src_cpu)) {
+ if (nr_big_tasks(env->src_rq) && !is_big_task(p))
+ return 0;
+
+ if (env->boost_policy == SCHED_BOOST_ON_BIG &&
+ !task_sched_boost(p))
+ return 0;
+ }
twf = task_will_fit(p, env->dst_cpu);
@@ -6951,8 +7001,7 @@ static int detach_tasks(struct lb_env *env)
if (env->imbalance <= 0)
return 0;
- if (cpu_capacity(env->dst_cpu) < cpu_capacity(env->src_cpu) &&
- !sched_boost())
+ if (cpu_capacity(env->dst_cpu) < cpu_capacity(env->src_cpu))
env->flags |= LBF_IGNORE_BIG_TASKS;
else if (!same_cluster(env->dst_cpu, env->src_cpu))
env->flags |= LBF_IGNORE_PREFERRED_CLUSTER_TASKS;
@@ -7255,8 +7304,10 @@ bail_inter_cluster_balance(struct lb_env *env, struct sd_lb_stats *sds)
int local_capacity, busiest_capacity;
int local_pwr_cost, busiest_pwr_cost;
int nr_cpus;
+ int boost = sched_boost();
- if (!sysctl_sched_restrict_cluster_spill || sched_boost())
+ if (!sysctl_sched_restrict_cluster_spill ||
+ boost == FULL_THROTTLE_BOOST || boost == CONSERVATIVE_BOOST)
return 0;
local_cpu = group_first_cpu(sds->local);
@@ -7628,11 +7679,6 @@ static bool update_sd_pick_busiest_active_balance(struct lb_env *env,
{
if (env->idle != CPU_NOT_IDLE &&
cpu_capacity(env->dst_cpu) > group_rq_capacity(sg)) {
- if (sched_boost() && !sds->busiest && sgs->sum_nr_running) {
- env->flags |= LBF_SCHED_BOOST_ACTIVE_BALANCE;
- return true;
- }
-
if (sgs->sum_nr_big_tasks >
sds->busiest_stat.sum_nr_big_tasks) {
env->flags |= LBF_BIG_TASK_ACTIVE_BALANCE;
@@ -8045,7 +8091,7 @@ static struct sched_group *find_busiest_group(struct lb_env *env)
if (!sds.busiest || busiest->sum_nr_running == 0)
goto out_balanced;
- if (env->flags & LBF_HMP_ACTIVE_BALANCE)
+ if (env->flags & LBF_BIG_TASK_ACTIVE_BALANCE)
goto force_balance;
if (bail_inter_cluster_balance(env, &sds))
@@ -8257,7 +8303,7 @@ static int need_active_balance(struct lb_env *env)
{
struct sched_domain *sd = env->sd;
- if (env->flags & LBF_HMP_ACTIVE_BALANCE)
+ if (env->flags & LBF_BIG_TASK_ACTIVE_BALANCE)
return 1;
if (env->idle == CPU_NEWLY_IDLE) {
@@ -8348,20 +8394,21 @@ static int load_balance(int this_cpu, struct rq *this_rq,
struct cpumask *cpus = this_cpu_cpumask_var_ptr(load_balance_mask);
struct lb_env env = {
- .sd = sd,
- .dst_cpu = this_cpu,
- .dst_rq = this_rq,
- .dst_grpmask = sched_group_cpus(sd->groups),
- .idle = idle,
- .loop_break = sched_nr_migrate_break,
- .cpus = cpus,
- .fbq_type = all,
- .tasks = LIST_HEAD_INIT(env.tasks),
- .imbalance = 0,
- .flags = 0,
- .loop = 0,
+ .sd = sd,
+ .dst_cpu = this_cpu,
+ .dst_rq = this_rq,
+ .dst_grpmask = sched_group_cpus(sd->groups),
+ .idle = idle,
+ .loop_break = sched_nr_migrate_break,
+ .cpus = cpus,
+ .fbq_type = all,
+ .tasks = LIST_HEAD_INIT(env.tasks),
+ .imbalance = 0,
+ .flags = 0,
+ .loop = 0,
.busiest_nr_running = 0,
.busiest_grp_capacity = 0,
+ .boost_policy = sched_boost_policy(),
};
/*
@@ -8510,7 +8557,7 @@ more_balance:
no_move:
if (!ld_moved) {
- if (!(env.flags & LBF_HMP_ACTIVE_BALANCE))
+ if (!(env.flags & LBF_BIG_TASK_ACTIVE_BALANCE))
schedstat_inc(sd, lb_failed[idle]);
/*
@@ -8520,7 +8567,7 @@ no_move:
* excessive cache_hot migrations and active balances.
*/
if (idle != CPU_NEWLY_IDLE &&
- !(env.flags & LBF_HMP_ACTIVE_BALANCE))
+ !(env.flags & LBF_BIG_TASK_ACTIVE_BALANCE))
sd->nr_balance_failed++;
if (need_active_balance(&env)) {
@@ -8797,6 +8844,7 @@ static int active_load_balance_cpu_stop(void *data)
.busiest_grp_capacity = 0,
.flags = 0,
.loop = 0,
+ .boost_policy = sched_boost_policy(),
};
bool moved = false;
@@ -9272,7 +9320,8 @@ static inline int _nohz_kick_needed_hmp(struct rq *rq, int cpu, int *type)
if (rq->nr_running < 2)
return 0;
- if (!sysctl_sched_restrict_cluster_spill || sched_boost())
+ if (!sysctl_sched_restrict_cluster_spill ||
+ sched_boost_policy() == SCHED_BOOST_ON_ALL)
return 1;
if (cpu_max_power_cost(cpu) == max_power_cost)
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 30391aae0822..968a41e0e81e 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -17,8 +17,6 @@
#include <linux/cpufreq.h>
#include <linux/list_sort.h>
#include <linux/syscore_ops.h>
-#include <linux/of.h>
-#include <linux/sched/core_ctl.h>
#include "sched.h"
@@ -231,52 +229,6 @@ fail:
return ret;
}
-/*
- * It is possible that CPUs of the same micro architecture can have slight
- * difference in the efficiency due to other factors like cache size. The
- * BOOST_ON_BIG policy may not be optimial for such systems. The required
- * boost policy can be specified via device tree to handle this.
- */
-static int __read_mostly sched_boost_policy = SCHED_BOOST_NONE;
-
-/*
- * This should be called after clusters are populated and
- * the respective efficiency values are initialized.
- */
-void init_sched_hmp_boost_policy(void)
-{
- /*
- * Initialize the boost type here if it is not passed from
- * device tree.
- */
- if (sched_boost_policy == SCHED_BOOST_NONE) {
- if (max_possible_efficiency != min_possible_efficiency)
- sched_boost_policy = SCHED_BOOST_ON_BIG;
- else
- sched_boost_policy = SCHED_BOOST_ON_ALL;
- }
-}
-
-void sched_hmp_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;
-
- if (!of_property_read_string(sn, "boost-policy", &boost_policy)) {
- if (!strcmp(boost_policy, "boost-on-big"))
- sched_boost_policy = SCHED_BOOST_ON_BIG;
- else if (!strcmp(boost_policy, "boost-on-all"))
- sched_boost_policy = SCHED_BOOST_ON_ALL;
- }
-}
-
unsigned int max_possible_efficiency = 1;
unsigned int min_possible_efficiency = UINT_MAX;
@@ -680,29 +632,6 @@ int __init set_sched_enable_hmp(char *str)
early_param("sched_enable_hmp", set_sched_enable_hmp);
-int got_boost_kick(void)
-{
- int cpu = smp_processor_id();
- struct rq *rq = cpu_rq(cpu);
-
- return test_bit(BOOST_KICK, &rq->hmp_flags);
-}
-
-inline void clear_boost_kick(int cpu)
-{
- struct rq *rq = cpu_rq(cpu);
-
- clear_bit(BOOST_KICK, &rq->hmp_flags);
-}
-
-inline void boost_kick(int cpu)
-{
- struct rq *rq = cpu_rq(cpu);
-
- if (!test_and_set_bit(BOOST_KICK, &rq->hmp_flags))
- smp_send_reschedule(cpu);
-}
-
/* Clear any HMP scheduler related requests pending from or on cpu */
void clear_hmp_request(int cpu)
{
@@ -840,6 +769,9 @@ min_max_possible_capacity = 1024; /* min(rq->max_possible_capacity) */
/* Window size (in ns) */
__read_mostly unsigned int sched_ravg_window = MIN_SCHED_RAVG_WINDOW;
+/* Maximum allowed threshold before freq aggregation must be enabled */
+#define MAX_FREQ_AGGR_THRESH 1000
+
/* Temporarily disable window-stats activity on all cpus */
unsigned int __read_mostly sched_disable_window_stats;
@@ -919,8 +851,8 @@ static const unsigned int top_tasks_bitmap_size =
* C1 busy time = 5 + 5 + 6 = 16ms
*
*/
-static __read_mostly unsigned int sched_freq_aggregate;
-__read_mostly unsigned int sysctl_sched_freq_aggregate;
+static __read_mostly unsigned int sched_freq_aggregate = 1;
+__read_mostly unsigned int sysctl_sched_freq_aggregate = 1;
unsigned int __read_mostly sysctl_sched_freq_aggregate_threshold_pct;
static unsigned int __read_mostly sched_freq_aggregate_threshold;
@@ -937,14 +869,6 @@ unsigned int max_task_load(void)
/* Use this knob to turn on or off HMP-aware task placement logic */
unsigned int __read_mostly sched_enable_hmp;
-/*
- * Scheduler boost is a mechanism to temporarily place tasks on CPUs
- * with higher capacity than those where a task would have normally
- * ended up with their load characteristics. Any entity enabling
- * boost is responsible for disabling it as well.
- */
-unsigned int sysctl_sched_boost;
-
/* A cpu can no longer accommodate more tasks if:
*
* rq->nr_running > sysctl_sched_spill_nr_run ||
@@ -996,6 +920,21 @@ unsigned int __read_mostly sched_downmigrate;
unsigned int __read_mostly sysctl_sched_downmigrate_pct = 60;
/*
+ * Task groups whose aggregate demand on a cpu is more than
+ * sched_group_upmigrate need to be up-migrated if possible.
+ */
+unsigned int __read_mostly sched_group_upmigrate;
+unsigned int __read_mostly sysctl_sched_group_upmigrate_pct = 100;
+
+/*
+ * Task groups, once up-migrated, will need to drop their aggregate
+ * demand to less than sched_group_downmigrate before they are "down"
+ * migrated.
+ */
+unsigned int __read_mostly sched_group_downmigrate;
+unsigned int __read_mostly sysctl_sched_group_downmigrate_pct = 95;
+
+/*
* The load scale factor of a CPU gets boosted when its max frequency
* is restricted due to which the tasks are migrating to higher capacity
* CPUs early. The sched_upmigrate threshold is auto-upgraded by
@@ -1017,33 +956,46 @@ sched_long_cpu_selection_threshold = 100 * NSEC_PER_MSEC;
unsigned int __read_mostly sysctl_sched_restrict_cluster_spill;
-void update_up_down_migrate(void)
+static void
+_update_up_down_migrate(unsigned int *up_migrate, unsigned int *down_migrate)
{
- unsigned int up_migrate = pct_to_real(sysctl_sched_upmigrate_pct);
- unsigned int down_migrate = pct_to_real(sysctl_sched_downmigrate_pct);
unsigned int delta;
if (up_down_migrate_scale_factor == 1024)
- goto done;
+ return;
- delta = up_migrate - down_migrate;
+ delta = *up_migrate - *down_migrate;
- up_migrate /= NSEC_PER_USEC;
- up_migrate *= up_down_migrate_scale_factor;
- up_migrate >>= 10;
- up_migrate *= NSEC_PER_USEC;
+ *up_migrate /= NSEC_PER_USEC;
+ *up_migrate *= up_down_migrate_scale_factor;
+ *up_migrate >>= 10;
+ *up_migrate *= NSEC_PER_USEC;
- up_migrate = min(up_migrate, sched_ravg_window);
+ *up_migrate = min(*up_migrate, sched_ravg_window);
- down_migrate /= NSEC_PER_USEC;
- down_migrate *= up_down_migrate_scale_factor;
- down_migrate >>= 10;
- down_migrate *= NSEC_PER_USEC;
+ *down_migrate /= NSEC_PER_USEC;
+ *down_migrate *= up_down_migrate_scale_factor;
+ *down_migrate >>= 10;
+ *down_migrate *= NSEC_PER_USEC;
- down_migrate = min(down_migrate, up_migrate - delta);
-done:
+ *down_migrate = min(*down_migrate, *up_migrate - delta);
+}
+
+static void update_up_down_migrate(void)
+{
+ unsigned int up_migrate = pct_to_real(sysctl_sched_upmigrate_pct);
+ unsigned int down_migrate = pct_to_real(sysctl_sched_downmigrate_pct);
+
+ _update_up_down_migrate(&up_migrate, &down_migrate);
sched_upmigrate = up_migrate;
sched_downmigrate = down_migrate;
+
+ up_migrate = pct_to_real(sysctl_sched_group_upmigrate_pct);
+ down_migrate = pct_to_real(sysctl_sched_group_downmigrate_pct);
+
+ _update_up_down_migrate(&up_migrate, &down_migrate);
+ sched_group_upmigrate = up_migrate;
+ sched_group_downmigrate = down_migrate;
}
void set_hmp_defaults(void)
@@ -1134,82 +1086,6 @@ u64 cpu_load_sync(int cpu, int sync)
return scale_load_to_cpu(cpu_cravg_sync(cpu, sync), cpu);
}
-static int boost_refcount;
-static DEFINE_SPINLOCK(boost_lock);
-static DEFINE_MUTEX(boost_mutex);
-
-static void boost_kick_cpus(void)
-{
- int i;
-
- for_each_online_cpu(i) {
- if (cpu_capacity(i) != max_capacity)
- boost_kick(i);
- }
-}
-
-int sched_boost(void)
-{
- return boost_refcount > 0;
-}
-
-int sched_set_boost(int enable)
-{
- unsigned long flags;
- int ret = 0;
- int old_refcount;
-
- if (!sched_enable_hmp)
- return -EINVAL;
-
- spin_lock_irqsave(&boost_lock, flags);
-
- old_refcount = boost_refcount;
-
- if (enable == 1) {
- boost_refcount++;
- } else if (!enable) {
- if (boost_refcount >= 1)
- boost_refcount--;
- else
- ret = -EINVAL;
- } else {
- ret = -EINVAL;
- }
-
- if (!old_refcount && boost_refcount)
- boost_kick_cpus();
-
- if (boost_refcount <= 1)
- core_ctl_set_boost(boost_refcount == 1);
- trace_sched_set_boost(boost_refcount);
- spin_unlock_irqrestore(&boost_lock, flags);
-
- return ret;
-}
-
-int sched_boost_handler(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp,
- loff_t *ppos)
-{
- int ret;
-
- mutex_lock(&boost_mutex);
- if (!write)
- sysctl_sched_boost = sched_boost();
-
- ret = proc_dointvec(table, write, buffer, lenp, ppos);
- if (ret || !write)
- goto done;
-
- ret = (sysctl_sched_boost <= 1) ?
- sched_set_boost(sysctl_sched_boost) : -EINVAL;
-
-done:
- mutex_unlock(&boost_mutex);
- return ret;
-}
-
/*
* Task will fit on a cpu if it's bandwidth consumption on that cpu
* will be less than sched_upmigrate. A big task that was previously
@@ -1219,60 +1095,63 @@ done:
* tasks with load close to the upmigrate threshold
*/
int task_load_will_fit(struct task_struct *p, u64 task_load, int cpu,
- enum sched_boost_type boost_type)
+ enum sched_boost_policy boost_policy)
{
- int upmigrate;
+ int upmigrate = sched_upmigrate;
if (cpu_capacity(cpu) == max_capacity)
return 1;
- if (boost_type != SCHED_BOOST_ON_BIG) {
+ if (cpu_capacity(task_cpu(p)) > cpu_capacity(cpu))
+ upmigrate = sched_downmigrate;
+
+ if (boost_policy != SCHED_BOOST_ON_BIG) {
if (task_nice(p) > SCHED_UPMIGRATE_MIN_NICE ||
upmigrate_discouraged(p))
return 1;
- upmigrate = sched_upmigrate;
- if (cpu_capacity(task_cpu(p)) > cpu_capacity(cpu))
- upmigrate = sched_downmigrate;
-
if (task_load < upmigrate)
return 1;
+ } else {
+ if (task_sched_boost(p) || task_load >= upmigrate)
+ return 0;
+
+ return 1;
}
return 0;
}
-enum sched_boost_type sched_boost_type(void)
-{
- if (sched_boost())
- return sched_boost_policy;
-
- return SCHED_BOOST_NONE;
-}
-
int task_will_fit(struct task_struct *p, int cpu)
{
u64 tload = scale_load_to_cpu(task_load(p), cpu);
- return task_load_will_fit(p, tload, cpu, sched_boost_type());
+ return task_load_will_fit(p, tload, cpu, sched_boost_policy());
}
-int group_will_fit(struct sched_cluster *cluster,
- struct related_thread_group *grp, u64 demand)
+static int
+group_will_fit(struct sched_cluster *cluster, struct related_thread_group *grp,
+ u64 demand, bool group_boost)
{
int cpu = cluster_first_cpu(cluster);
int prev_capacity = 0;
- unsigned int threshold = sched_upmigrate;
+ unsigned int threshold = sched_group_upmigrate;
u64 load;
if (cluster->capacity == max_capacity)
return 1;
+ if (group_boost)
+ return 0;
+
+ if (!demand)
+ return 1;
+
if (grp->preferred_cluster)
prev_capacity = grp->preferred_cluster->capacity;
if (cluster->capacity < prev_capacity)
- threshold = sched_downmigrate;
+ threshold = sched_group_downmigrate;
load = scale_load_to_cpu(demand, cpu);
if (load < threshold)
@@ -1495,6 +1374,23 @@ void post_big_task_count_change(const struct cpumask *cpus)
DEFINE_MUTEX(policy_mutex);
+unsigned int update_freq_aggregate_threshold(unsigned int threshold)
+{
+ unsigned int old_threshold;
+
+ mutex_lock(&policy_mutex);
+
+ old_threshold = sysctl_sched_freq_aggregate_threshold_pct;
+
+ sysctl_sched_freq_aggregate_threshold_pct = threshold;
+ sched_freq_aggregate_threshold =
+ pct_to_real(sysctl_sched_freq_aggregate_threshold_pct);
+
+ mutex_unlock(&policy_mutex);
+
+ return old_threshold;
+}
+
static inline int invalid_value_freq_input(unsigned int *data)
{
if (data == &sysctl_sched_freq_aggregate)
@@ -1578,7 +1474,9 @@ int sched_hmp_proc_update_handler(struct ctl_table *table, int write,
if (write && (old_val == *data))
goto done;
- if (sysctl_sched_downmigrate_pct > sysctl_sched_upmigrate_pct) {
+ if (sysctl_sched_downmigrate_pct > sysctl_sched_upmigrate_pct ||
+ sysctl_sched_group_downmigrate_pct >
+ sysctl_sched_group_upmigrate_pct) {
*data = old_val;
ret = -EINVAL;
goto done;
@@ -3110,37 +3008,9 @@ static void reset_all_task_stats(void)
{
struct task_struct *g, *p;
- read_lock(&tasklist_lock);
do_each_thread(g, p) {
- raw_spin_lock_irq(&p->pi_lock);
reset_task_stats(p);
- raw_spin_unlock_irq(&p->pi_lock);
} while_each_thread(g, p);
- read_unlock(&tasklist_lock);
-}
-
-static void disable_window_stats(void)
-{
- unsigned long flags;
- int i;
-
- local_irq_save(flags);
- for_each_possible_cpu(i)
- raw_spin_lock(&cpu_rq(i)->lock);
-
- sched_disable_window_stats = 1;
-
- for_each_possible_cpu(i)
- raw_spin_unlock(&cpu_rq(i)->lock);
-
- local_irq_restore(flags);
-}
-
-/* Called with all cpu's rq->lock held */
-static void enable_window_stats(void)
-{
- sched_disable_window_stats = 0;
-
}
enum reset_reason_code {
@@ -3166,17 +3036,22 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
unsigned int old = 0, new = 0;
struct related_thread_group *grp;
- read_lock(&related_thread_group_lock);
-
- disable_window_stats();
+ local_irq_save(flags);
- reset_all_task_stats();
+ read_lock(&tasklist_lock);
- local_irq_save(flags);
+ read_lock(&related_thread_group_lock);
+ /* Taking all runqueue locks prevents race with sched_exit(). */
for_each_possible_cpu(cpu)
raw_spin_lock(&cpu_rq(cpu)->lock);
+ sched_disable_window_stats = 1;
+
+ reset_all_task_stats();
+
+ read_unlock(&tasklist_lock);
+
list_for_each_entry(grp, &related_thread_groups, list) {
int j;
@@ -3196,7 +3071,7 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
sched_load_granule = sched_ravg_window / NUM_LOAD_INDICES;
}
- enable_window_stats();
+ sched_disable_window_stats = 0;
for_each_possible_cpu(cpu) {
struct rq *rq = cpu_rq(cpu);
@@ -3239,10 +3114,10 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
for_each_possible_cpu(cpu)
raw_spin_unlock(&cpu_rq(cpu)->lock);
- local_irq_restore(flags);
-
read_unlock(&related_thread_group_lock);
+ local_irq_restore(flags);
+
trace_sched_reset_all_window_stats(window_start, window_size,
sched_ktime_clock() - start_ts, reason, old, new);
}
@@ -3824,13 +3699,13 @@ static void check_for_up_down_migrate_update(const struct cpumask *cpus)
}
/* Return cluster which can offer required capacity for group */
-static struct sched_cluster *
-best_cluster(struct related_thread_group *grp, u64 total_demand)
+static struct sched_cluster *best_cluster(struct related_thread_group *grp,
+ u64 total_demand, bool group_boost)
{
struct sched_cluster *cluster = NULL;
for_each_sched_cluster(cluster) {
- if (group_will_fit(cluster, grp, total_demand))
+ if (group_will_fit(cluster, grp, total_demand, group_boost))
return cluster;
}
@@ -3841,6 +3716,9 @@ static void _set_preferred_cluster(struct related_thread_group *grp)
{
struct task_struct *p;
u64 combined_demand = 0;
+ bool boost_on_big = sched_boost_policy() == SCHED_BOOST_ON_BIG;
+ bool group_boost = false;
+ u64 wallclock;
if (!sysctl_sched_enable_colocation) {
grp->last_update = sched_ktime_clock();
@@ -3848,31 +3726,43 @@ static void _set_preferred_cluster(struct related_thread_group *grp)
return;
}
+ if (list_empty(&grp->tasks))
+ return;
+
+ wallclock = sched_ktime_clock();
+
/*
* wakeup of two or more related tasks could race with each other and
* could result in multiple calls to _set_preferred_cluster being issued
* at same time. Avoid overhead in such cases of rechecking preferred
* cluster
*/
- if (sched_ktime_clock() - grp->last_update < sched_ravg_window / 10)
+ if (wallclock - grp->last_update < sched_ravg_window / 10)
return;
- list_for_each_entry(p, &grp->tasks, grp_list)
+ list_for_each_entry(p, &grp->tasks, grp_list) {
+ if (boost_on_big && task_sched_boost(p)) {
+ group_boost = true;
+ break;
+ }
+
+ if (p->ravg.mark_start < wallclock -
+ (sched_ravg_window * sched_ravg_hist_size))
+ continue;
+
combined_demand += p->ravg.demand;
- grp->preferred_cluster = best_cluster(grp, combined_demand);
+ }
+
+ grp->preferred_cluster = best_cluster(grp,
+ combined_demand, group_boost);
grp->last_update = sched_ktime_clock();
trace_sched_set_preferred_cluster(grp, combined_demand);
}
void set_preferred_cluster(struct related_thread_group *grp)
{
- /*
- * Prevent possible deadlock with update_children(). Not updating
- * the preferred cluster once is not a big deal.
- */
- if (!raw_spin_trylock(&grp->lock))
- return;
+ raw_spin_lock(&grp->lock);
_set_preferred_cluster(grp);
raw_spin_unlock(&grp->lock);
}
@@ -3880,6 +3770,8 @@ void set_preferred_cluster(struct related_thread_group *grp)
#define ADD_TASK 0
#define REM_TASK 1
+#define DEFAULT_CGROUP_COLOC_ID 1
+
static inline void free_group_cputime(struct related_thread_group *grp)
{
free_percpu(grp->cpu_time);
@@ -4116,64 +4008,19 @@ static void free_related_thread_group(struct rcu_head *rcu)
kfree(grp);
}
-/*
- * The thread group for a task can change while we are here. However,
- * add_new_task_to_grp() will take care of any tasks that we miss here.
- * When a parent exits, and a child thread is simultaneously exiting,
- * sched_set_group_id() will synchronize those operations.
- */
-static void update_children(struct task_struct *leader,
- struct related_thread_group *grp, int event)
-{
- struct task_struct *child;
- struct rq *rq;
- unsigned long flags;
-
- if (!thread_group_leader(leader))
- return;
-
- if (event == ADD_TASK && !sysctl_sched_enable_thread_grouping)
- return;
-
- if (thread_group_empty(leader))
- return;
-
- child = next_thread(leader);
-
- do {
- rq = task_rq_lock(child, &flags);
-
- if (event == REM_TASK && child->grp && grp == child->grp) {
- transfer_busy_time(rq, grp, child, event);
- list_del_init(&child->grp_list);
- rcu_assign_pointer(child->grp, NULL);
- } else if (event == ADD_TASK && !child->grp) {
- transfer_busy_time(rq, grp, child, event);
- list_add(&child->grp_list, &grp->tasks);
- rcu_assign_pointer(child->grp, grp);
- }
-
- task_rq_unlock(rq, child, &flags);
- } while_each_thread(leader, child);
-
-}
-
static void remove_task_from_group(struct task_struct *p)
{
struct related_thread_group *grp = p->grp;
struct rq *rq;
int empty_group = 1;
- unsigned long flags;
raw_spin_lock(&grp->lock);
- rq = task_rq_lock(p, &flags);
+ rq = __task_rq_lock(p);
transfer_busy_time(rq, p->grp, p, REM_TASK);
list_del_init(&p->grp_list);
rcu_assign_pointer(p->grp, NULL);
- task_rq_unlock(rq, p, &flags);
-
- update_children(p, grp, REM_TASK);
+ __task_rq_unlock(rq);
if (!list_empty(&grp->tasks)) {
empty_group = 0;
@@ -4182,7 +4029,8 @@ static void remove_task_from_group(struct task_struct *p)
raw_spin_unlock(&grp->lock);
- if (empty_group) {
+ /* Reserved groups cannot be destroyed */
+ if (empty_group && grp->id != DEFAULT_CGROUP_COLOC_ID) {
list_del(&grp->list);
call_rcu(&grp->rcu, free_related_thread_group);
}
@@ -4192,7 +4040,6 @@ static int
add_task_to_group(struct task_struct *p, struct related_thread_group *grp)
{
struct rq *rq;
- unsigned long flags;
raw_spin_lock(&grp->lock);
@@ -4200,13 +4047,11 @@ add_task_to_group(struct task_struct *p, struct related_thread_group *grp)
* Change p->grp under rq->lock. Will prevent races with read-side
* reference of p->grp in various hot-paths
*/
- rq = task_rq_lock(p, &flags);
+ rq = __task_rq_lock(p);
transfer_busy_time(rq, grp, p, ADD_TASK);
list_add(&p->grp_list, &grp->tasks);
rcu_assign_pointer(p->grp, grp);
- task_rq_unlock(rq, p, &flags);
-
- update_children(p, grp, ADD_TASK);
+ __task_rq_unlock(rq);
_set_preferred_cluster(grp);
@@ -4219,23 +4064,33 @@ void add_new_task_to_grp(struct task_struct *new)
{
unsigned long flags;
struct related_thread_group *grp;
- struct task_struct *parent;
+ struct task_struct *leader = new->group_leader;
+ unsigned int leader_grp_id = sched_get_group_id(leader);
- if (!sysctl_sched_enable_thread_grouping)
+ if (!sysctl_sched_enable_thread_grouping &&
+ leader_grp_id != DEFAULT_CGROUP_COLOC_ID)
return;
if (thread_group_leader(new))
return;
- parent = new->group_leader;
+ if (leader_grp_id == DEFAULT_CGROUP_COLOC_ID) {
+ if (!same_schedtune(new, leader))
+ return;
+ }
write_lock_irqsave(&related_thread_group_lock, flags);
rcu_read_lock();
- grp = task_related_thread_group(parent);
+ grp = task_related_thread_group(leader);
rcu_read_unlock();
- /* Its possible that update_children() already added us to the group */
+ /*
+ * It's possible that someone already added the new task to the
+ * group. A leader's thread group is updated prior to calling
+ * this function. It's also possible that the leader has exited
+ * the group. In either case, there is nothing else to do.
+ */
if (!grp || new->grp) {
write_unlock_irqrestore(&related_thread_group_lock, flags);
return;
@@ -4250,14 +4105,55 @@ void add_new_task_to_grp(struct task_struct *new)
write_unlock_irqrestore(&related_thread_group_lock, flags);
}
+#if defined(CONFIG_SCHED_TUNE) && defined(CONFIG_CGROUP_SCHEDTUNE)
+/*
+ * We create a default colocation group at boot. There is no need to
+ * synchronize tasks between cgroups at creation time because the
+ * correct cgroup hierarchy is not available at boot. Therefore cgroup
+ * colocation is turned off by default even though the colocation group
+ * itself has been allocated. Furthermore this colocation group cannot
+ * be destroyted once it has been created. All of this has been as part
+ * of runtime optimizations.
+ *
+ * The job of synchronizing tasks to the colocation group is done when
+ * the colocation flag in the cgroup is turned on.
+ */
+static int __init create_default_coloc_group(void)
+{
+ struct related_thread_group *grp = NULL;
+ unsigned long flags;
+
+ grp = alloc_related_thread_group(DEFAULT_CGROUP_COLOC_ID);
+ if (IS_ERR(grp)) {
+ WARN_ON(1);
+ return -ENOMEM;
+ }
+
+ write_lock_irqsave(&related_thread_group_lock, flags);
+ list_add(&grp->list, &related_thread_groups);
+ write_unlock_irqrestore(&related_thread_group_lock, flags);
+
+ update_freq_aggregate_threshold(MAX_FREQ_AGGR_THRESH);
+ return 0;
+}
+late_initcall(create_default_coloc_group);
+
+int sync_cgroup_colocation(struct task_struct *p, bool insert)
+{
+ unsigned int grp_id = insert ? DEFAULT_CGROUP_COLOC_ID : 0;
+
+ return sched_set_group_id(p, grp_id);
+}
+#endif
+
int sched_set_group_id(struct task_struct *p, unsigned int group_id)
{
int rc = 0;
unsigned long flags;
struct related_thread_group *grp = NULL;
- /* Prevents tasks from exiting while we are managing groups. */
- write_lock_irqsave(&related_thread_group_lock, flags);
+ raw_spin_lock_irqsave(&p->pi_lock, flags);
+ write_lock(&related_thread_group_lock);
/* Switching from one group to another directly is not permitted */
if ((current != p && p->flags & PF_EXITING) ||
@@ -4272,6 +4168,12 @@ int sched_set_group_id(struct task_struct *p, unsigned int group_id)
grp = lookup_related_thread_group(group_id);
if (!grp) {
+ /* This is a reserved id */
+ if (group_id == DEFAULT_CGROUP_COLOC_ID) {
+ rc = -EINVAL;
+ goto done;
+ }
+
grp = alloc_related_thread_group(group_id);
if (IS_ERR(grp)) {
rc = -ENOMEM;
@@ -4281,10 +4183,10 @@ int sched_set_group_id(struct task_struct *p, unsigned int group_id)
list_add(&grp->list, &related_thread_groups);
}
- BUG_ON(!grp);
rc = add_task_to_group(p, grp);
done:
- write_unlock_irqrestore(&related_thread_group_lock, flags);
+ write_unlock(&related_thread_group_lock);
+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
return rc;
}
@@ -4529,7 +4431,7 @@ bool early_detection_notify(struct rq *rq, u64 wallclock)
struct task_struct *p;
int loop_max = 10;
- if (!sched_boost() || !rq->cfs.h_nr_running)
+ if (sched_boost_policy() == SCHED_BOOST_NONE || !rq->cfs.h_nr_running)
return 0;
rq->ed_task = NULL;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index ba4403e910d8..12a04f30ef77 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1677,8 +1677,13 @@ static int find_lowest_rq_hmp(struct task_struct *task)
int prev_cpu = task_cpu(task);
u64 cpu_load, min_load = ULLONG_MAX;
int i;
- int restrict_cluster = sched_boost() ? 0 :
- sysctl_sched_restrict_cluster_spill;
+ int restrict_cluster;
+ int boost_on_big;
+
+ boost_on_big = sched_boost() == FULL_THROTTLE_BOOST &&
+ sched_boost_policy() == SCHED_BOOST_ON_BIG;
+
+ restrict_cluster = sysctl_sched_restrict_cluster_spill;
/* Make sure the mask is initialized first */
if (unlikely(!lowest_mask))
@@ -1697,6 +1702,9 @@ static int find_lowest_rq_hmp(struct task_struct *task)
*/
for_each_sched_cluster(cluster) {
+ if (boost_on_big && cluster->capacity != max_possible_capacity)
+ continue;
+
cpumask_and(&candidate_mask, &cluster->cpus, lowest_mask);
cpumask_andnot(&candidate_mask, &candidate_mask,
cpu_isolated_mask);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 4289bf6cd642..30838bb9b442 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1061,8 +1061,6 @@ extern unsigned int max_load_scale_factor;
extern unsigned int max_possible_capacity;
extern unsigned int min_max_possible_capacity;
extern unsigned int max_power_cost;
-extern unsigned int sched_upmigrate;
-extern unsigned int sched_downmigrate;
extern unsigned int sched_init_task_load_windows;
extern unsigned int up_down_migrate_scale_factor;
extern unsigned int sysctl_sched_restrict_cluster_spill;
@@ -1106,18 +1104,23 @@ extern void sched_account_irqstart(int cpu, struct task_struct *curr,
u64 wallclock);
extern unsigned int cpu_temp(int cpu);
extern unsigned int nr_eligible_big_tasks(int cpu);
-extern void update_up_down_migrate(void);
extern int update_preferred_cluster(struct related_thread_group *grp,
struct task_struct *p, u32 old_load);
extern void set_preferred_cluster(struct related_thread_group *grp);
extern void add_new_task_to_grp(struct task_struct *new);
+extern unsigned int update_freq_aggregate_threshold(unsigned int threshold);
-enum sched_boost_type {
+enum sched_boost_policy {
SCHED_BOOST_NONE,
SCHED_BOOST_ON_BIG,
SCHED_BOOST_ON_ALL,
};
+#define NO_BOOST 0
+#define FULL_THROTTLE_BOOST 1
+#define CONSERVATIVE_BOOST 2
+#define RESTRAINED_BOOST 3
+
static inline struct sched_cluster *cpu_cluster(int cpu)
{
return cpu_rq(cpu)->cluster;
@@ -1387,14 +1390,11 @@ extern void set_hmp_defaults(void);
extern int power_delta_exceeded(unsigned int cpu_cost, unsigned int base_cost);
extern unsigned int power_cost(int cpu, u64 demand);
extern void reset_all_window_stats(u64 window_start, unsigned int window_size);
-extern void boost_kick(int cpu);
extern int sched_boost(void);
extern int task_load_will_fit(struct task_struct *p, u64 task_load, int cpu,
- enum sched_boost_type boost_type);
-extern enum sched_boost_type sched_boost_type(void);
+ enum sched_boost_policy boost_policy);
+extern enum sched_boost_policy sched_boost_policy(void);
extern int task_will_fit(struct task_struct *p, int cpu);
-extern int group_will_fit(struct sched_cluster *cluster,
- struct related_thread_group *grp, u64 demand);
extern u64 cpu_load(int cpu);
extern u64 cpu_load_sync(int cpu, int sync);
extern int preferred_cluster(struct sched_cluster *cluster,
@@ -1422,10 +1422,32 @@ extern u64 cpu_upmigrate_discourage_read_u64(struct cgroup_subsys_state *css,
struct cftype *cft);
extern int cpu_upmigrate_discourage_write_u64(struct cgroup_subsys_state *css,
struct cftype *cft, u64 upmigrate_discourage);
-extern void sched_hmp_parse_dt(void);
-extern void init_sched_hmp_boost_policy(void);
+extern void sched_boost_parse_dt(void);
extern void clear_top_tasks_bitmap(unsigned long *bitmap);
+#if defined(CONFIG_SCHED_TUNE) && defined(CONFIG_CGROUP_SCHEDTUNE)
+extern bool task_sched_boost(struct task_struct *p);
+extern int sync_cgroup_colocation(struct task_struct *p, bool insert);
+extern bool same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2);
+extern void update_cgroup_boost_settings(void);
+extern void restore_cgroup_boost_settings(void);
+
+#else
+static inline bool
+same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2)
+{
+ return true;
+}
+
+static inline bool task_sched_boost(struct task_struct *p)
+{
+ return true;
+}
+
+static inline void update_cgroup_boost_settings(void) { }
+static inline void restore_cgroup_boost_settings(void) { }
+#endif
+
#else /* CONFIG_SCHED_HMP */
struct hmp_sched_stats;
@@ -1615,8 +1637,7 @@ static inline void post_big_task_count_change(void) { }
static inline void set_hmp_defaults(void) { }
static inline void clear_reserved(int cpu) { }
-static inline void sched_hmp_parse_dt(void) {}
-static inline void init_sched_hmp_boost_policy(void) {}
+static inline void sched_boost_parse_dt(void) {}
#define trace_sched_cpu_load(...)
#define trace_sched_cpu_load_lb(...)
diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c
index 4f8182302e5e..ee2af8e0b5ce 100644
--- a/kernel/sched/tune.c
+++ b/kernel/sched/tune.c
@@ -25,6 +25,33 @@ struct schedtune {
/* Boost value for tasks on that SchedTune CGroup */
int boost;
+#ifdef CONFIG_SCHED_HMP
+ /* Toggle ability to override sched boost enabled */
+ bool sched_boost_no_override;
+
+ /*
+ * Controls whether a cgroup is eligible for sched boost or not. This
+ * can temporariliy be disabled by the kernel based on the no_override
+ * flag above.
+ */
+ bool sched_boost_enabled;
+
+ /*
+ * This tracks the default value of sched_boost_enabled and is used
+ * restore the value following any temporary changes to that flag.
+ */
+ bool sched_boost_enabled_backup;
+
+ /*
+ * Controls whether tasks of this cgroup should be colocated with each
+ * other and tasks of other cgroups that have the same flag turned on.
+ */
+ bool colocate;
+
+ /* Controls whether further updates are allowed to the colocate flag */
+ bool colocate_update_disabled;
+#endif
+
};
static inline struct schedtune *css_st(struct cgroup_subsys_state *css)
@@ -54,6 +81,13 @@ static inline struct schedtune *parent_st(struct schedtune *st)
static struct schedtune
root_schedtune = {
.boost = 0,
+#ifdef CONFIG_SCHED_HMP
+ .sched_boost_no_override = false,
+ .sched_boost_enabled = true,
+ .sched_boost_enabled_backup = true,
+ .colocate = false,
+ .colocate_update_disabled = false,
+#endif
};
/*
@@ -97,6 +131,121 @@ struct boost_groups {
/* Boost groups affecting each CPU in the system */
DEFINE_PER_CPU(struct boost_groups, cpu_boost_groups);
+#ifdef CONFIG_SCHED_HMP
+static inline void init_sched_boost(struct schedtune *st)
+{
+ st->sched_boost_no_override = false;
+ st->sched_boost_enabled = true;
+ st->sched_boost_enabled_backup = st->sched_boost_enabled;
+ st->colocate = false;
+ st->colocate_update_disabled = false;
+}
+
+bool same_schedtune(struct task_struct *tsk1, struct task_struct *tsk2)
+{
+ return task_schedtune(tsk1) == task_schedtune(tsk2);
+}
+
+void update_cgroup_boost_settings(void)
+{
+ int i;
+
+ for (i = 0; i < BOOSTGROUPS_COUNT; i++) {
+ if (!allocated_group[i])
+ break;
+
+ if (allocated_group[i]->sched_boost_no_override)
+ continue;
+
+ allocated_group[i]->sched_boost_enabled = false;
+ }
+}
+
+void restore_cgroup_boost_settings(void)
+{
+ int i;
+
+ for (i = 0; i < BOOSTGROUPS_COUNT; i++) {
+ if (!allocated_group[i])
+ break;
+
+ allocated_group[i]->sched_boost_enabled =
+ allocated_group[i]->sched_boost_enabled_backup;
+ }
+}
+
+bool task_sched_boost(struct task_struct *p)
+{
+ struct schedtune *st = task_schedtune(p);
+
+ return st->sched_boost_enabled;
+}
+
+static u64
+sched_boost_override_read(struct cgroup_subsys_state *css,
+ struct cftype *cft)
+{
+ struct schedtune *st = css_st(css);
+
+ return st->sched_boost_no_override;
+}
+
+static int sched_boost_override_write(struct cgroup_subsys_state *css,
+ struct cftype *cft, u64 override)
+{
+ struct schedtune *st = css_st(css);
+
+ st->sched_boost_no_override = !!override;
+
+ return 0;
+}
+
+static u64 sched_boost_enabled_read(struct cgroup_subsys_state *css,
+ struct cftype *cft)
+{
+ struct schedtune *st = css_st(css);
+
+ return st->sched_boost_enabled;
+}
+
+static int sched_boost_enabled_write(struct cgroup_subsys_state *css,
+ struct cftype *cft, u64 enable)
+{
+ struct schedtune *st = css_st(css);
+
+ st->sched_boost_enabled = !!enable;
+ st->sched_boost_enabled_backup = st->sched_boost_enabled;
+
+ return 0;
+}
+
+static u64 sched_colocate_read(struct cgroup_subsys_state *css,
+ struct cftype *cft)
+{
+ struct schedtune *st = css_st(css);
+
+ return st->colocate;
+}
+
+static int sched_colocate_write(struct cgroup_subsys_state *css,
+ struct cftype *cft, u64 colocate)
+{
+ struct schedtune *st = css_st(css);
+
+ if (st->colocate_update_disabled)
+ return -EPERM;
+
+ st->colocate = !!colocate;
+ st->colocate_update_disabled = true;
+ return 0;
+}
+
+#else /* CONFIG_SCHED_HMP */
+
+static inline void init_sched_boost(struct schedtune *st) { }
+
+#endif /* CONFIG_SCHED_HMP */
+
static u64
boost_read(struct cgroup_subsys_state *css, struct cftype *cft)
{
@@ -121,12 +270,45 @@ boost_write(struct cgroup_subsys_state *css, struct cftype *cft,
return 0;
}
+static void schedtune_attach(struct cgroup_taskset *tset)
+{
+ struct task_struct *task;
+ struct cgroup_subsys_state *css;
+ struct schedtune *st;
+ bool colocate;
+
+ cgroup_taskset_first(tset, &css);
+ st = css_st(css);
+
+ colocate = st->colocate;
+
+ cgroup_taskset_for_each(task, css, tset)
+ sync_cgroup_colocation(task, colocate);
+}
+
static struct cftype files[] = {
{
.name = "boost",
.read_u64 = boost_read,
.write_u64 = boost_write,
},
+#ifdef CONFIG_SCHED_HMP
+ {
+ .name = "sched_boost_no_override",
+ .read_u64 = sched_boost_override_read,
+ .write_u64 = sched_boost_override_write,
+ },
+ {
+ .name = "sched_boost_enabled",
+ .read_u64 = sched_boost_enabled_read,
+ .write_u64 = sched_boost_enabled_write,
+ },
+ {
+ .name = "colocate",
+ .read_u64 = sched_colocate_read,
+ .write_u64 = sched_colocate_write,
+ },
+#endif
{ } /* terminate */
};
@@ -189,6 +371,7 @@ schedtune_css_alloc(struct cgroup_subsys_state *parent_css)
/* Initialize per CPUs boost group support */
st->idx = idx;
+ init_sched_boost(st);
if (schedtune_boostgroup_init(st))
goto release;
@@ -222,6 +405,7 @@ struct cgroup_subsys schedtune_cgrp_subsys = {
.legacy_cftypes = files,
.early_init = 1,
.allow_attach = subsys_cgroup_allow_attach,
+ .attach = schedtune_attach,
};
#endif /* CONFIG_CGROUP_SCHEDTUNE */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 574316f1c344..b7cbd7940f7b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -124,6 +124,7 @@ static int __maybe_unused neg_one = -1;
static int zero;
static int __maybe_unused one = 1;
static int __maybe_unused two = 2;
+static int __maybe_unused three = 3;
static int __maybe_unused four = 4;
static unsigned long one_ul = 1;
static int one_hundred = 100;
@@ -377,6 +378,22 @@ static struct ctl_table kern_table[] = {
.extra2 = &one_hundred,
},
{
+ .procname = "sched_group_upmigrate",
+ .data = &sysctl_sched_group_upmigrate_pct,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = sched_hmp_proc_update_handler,
+ .extra1 = &zero,
+ },
+ {
+ .procname = "sched_group_downmigrate",
+ .data = &sysctl_sched_group_downmigrate_pct,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = sched_hmp_proc_update_handler,
+ .extra1 = &zero,
+ },
+ {
.procname = "sched_init_task_load",
.data = &sysctl_sched_init_task_load_pct,
.maxlen = sizeof(unsigned int),
@@ -487,6 +504,8 @@ static struct ctl_table kern_table[] = {
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = sched_boost_handler,
+ .extra1 = &zero,
+ .extra2 = &three,
},
#endif /* CONFIG_SCHED_HMP */
#ifdef CONFIG_SCHED_DEBUG
diff --git a/net/core/filter.c b/net/core/filter.c
index 75e9b2b2336d..eedb05468fcb 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -52,9 +52,10 @@
#include <net/dst.h>
/**
- * sk_filter - run a packet through a socket filter
+ * sk_filter_trim_cap - run a packet through a socket filter
* @sk: sock associated with &sk_buff
* @skb: buffer to filter
+ * @cap: limit on how short the eBPF program may trim the packet
*
* Run the eBPF program and then cut skb->data to correct size returned by
* the program. If pkt_len is 0 we toss packet. If skb->len is smaller
@@ -63,7 +64,7 @@
* be accepted or -EPERM if the packet should be tossed.
*
*/
-int sk_filter(struct sock *sk, struct sk_buff *skb)
+int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
{
int err;
struct sk_filter *filter;
@@ -85,13 +86,13 @@ int sk_filter(struct sock *sk, struct sk_buff *skb)
if (filter) {
unsigned int pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
- err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
+ err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
}
rcu_read_unlock();
return err;
}
-EXPORT_SYMBOL(sk_filter);
+EXPORT_SYMBOL(sk_filter_trim_cap);
static u64 __skb_get_pay_offset(u64 ctx, u64 a, u64 x, u64 r4, u64 r5)
{
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 07408b81bcd7..e3b0b55f2c92 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1529,6 +1529,21 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
}
EXPORT_SYMBOL(tcp_prequeue);
+int tcp_filter(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcphdr *th = (struct tcphdr *)skb->data;
+ unsigned int eaten = skb->len;
+ int err;
+
+ err = sk_filter_trim_cap(sk, skb, th->doff * 4);
+ if (!err) {
+ eaten -= skb->len;
+ TCP_SKB_CB(skb)->end_seq -= eaten;
+ }
+ return err;
+}
+EXPORT_SYMBOL(tcp_filter);
+
/*
* From tcp_input.c
*/
@@ -1634,8 +1649,10 @@ process:
nf_reset(skb);
- if (sk_filter(sk, skb))
+ if (tcp_filter(sk, skb))
goto discard_and_relse;
+ th = (const struct tcphdr *)skb->data;
+ iph = ip_hdr(skb);
skb->dev = NULL;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 04955a5d2350..8647afa77db4 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1199,7 +1199,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
if (skb->protocol == htons(ETH_P_IP))
return tcp_v4_do_rcv(sk, skb);
- if (sk_filter(sk, skb))
+ if (tcp_filter(sk, skb))
goto discard;
/*
@@ -1431,8 +1431,10 @@ process:
if (tcp_v6_inbound_md5_hash(sk, skb))
goto discard_and_relse;
- if (sk_filter(sk, skb))
+ if (tcp_filter(sk, skb))
goto discard_and_relse;
+ th = (const struct tcphdr *)skb->data;
+ hdr = ipv6_hdr(skb);
skb->dev = NULL;
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c
index 79c4abcfa6b4..fb31d2ea5a81 100644
--- a/net/rose/rose_in.c
+++ b/net/rose/rose_in.c
@@ -164,7 +164,8 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
rose_frames_acked(sk, nr);
if (ns == rose->vr) {
rose_start_idletimer(sk);
- if (sock_queue_rcv_skb(sk, skb) == 0) {
+ if (sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) == 0 &&
+ sock_queue_rcv_skb(sk, skb) == 0) {
rose->vr = (rose->vr + 1) % ROSE_MODULUS;
queued = 1;
} else {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 23b7c76ff2d8..89130cf4db04 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -16,7 +16,7 @@ country 00:
(57240 - 63720 @ 2160), (0)
-country AE: DFS-FCC
+country AE: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (24), AUTO-BW
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
@@ -52,13 +52,12 @@ country AN: DFS-ETSI
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
-country AR: DFS-FCC
- (2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24), AUTO-BW
- (5250 - 5330 @ 80), (24), DFS, AUTO-BW
- (5490 - 5590 @ 80), (24), DFS
- (5650 - 5730 @ 80), (24), DFS
- (5735 - 5835 @ 80), (30)
+country AR:
+ (2402 - 2482 @ 40), (36)
+ (5170 - 5330 @ 160), (23)
+ (5490 - 5590 @ 80), (36)
+ (5650 - 5730 @ 80), (36)
+ (5735 - 5835 @ 80), (36)
country AS: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -162,11 +161,10 @@ country BG: DFS-ETSI
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country BH: DFS-ETSI
+country BH:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 20), (20)
- (5250 - 5330 @ 20), (20), DFS
- (5735 - 5835 @ 20), (20)
+ (5170 - 5330 @ 20), (23)
+ (5735 - 5835 @ 20), (33)
country BL: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -219,8 +217,10 @@ country BY: DFS-ETSI
(5490 - 5710 @ 160), (30), DFS
country BZ:
- (2402 - 2482 @ 40), (30)
- (5735 - 5835 @ 80), (30)
+ (2402 - 2482 @ 40), (36)
+ (5170 - 5330 @ 160), (27)
+ (5490 - 5730 @ 160), (36)
+ (5735 - 5835 @ 80), (36)
country CA: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -259,10 +259,9 @@ country CI: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country CL: DFS-ETSI
+country CL:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5330 @ 160), (20)
(5735 - 5835 @ 80), (20)
country CN: DFS-FCC
@@ -416,9 +415,9 @@ country EE: DFS-ETSI
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
country EG: DFS-ETSI
- (2402 - 2482 @ 20), (20)
- (5170 - 5250 @ 20), (23)
- (5250 - 5330 @ 20), (23), DFS
+ (2402 - 2482 @ 40), (20)
+ (5170 - 5250 @ 40), (23)
+ (5250 - 5330 @ 40), (23), DFS
country ES: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -581,11 +580,10 @@ country HK: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country HN: DFS-FCC
+country HN:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24), AUTO-BW
- (5250 - 5330 @ 80), (24), DFS, AUTO-BW
- (5490 - 5730 @ 160), (24), DFS
+ (5170 - 5330 @ 160), (24)
+ (5490 - 5730 @ 160), (24)
(5735 - 5835 @ 80), (30)
country HR: DFS-ETSI
@@ -657,10 +655,9 @@ country IL: DFS-ETSI
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
-country IN: DFS-ETSI
+country IN:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5170 - 5330 @ 160), (23)
(5735 - 5835 @ 80), (30)
country IR:
@@ -735,7 +732,7 @@ country KH: DFS-ETSI
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
-country KN: DFS-ETSI
+country KN: DFS-FCC
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
@@ -746,8 +743,8 @@ country KR: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
(5250 - 5330 @ 80), (20), DFS, AUTO-BW
- (5490 - 5630 @ 80), (30), DFS
- (5735 - 5815 @ 80), (30)
+ (5490 - 5710 @ 80), (30), DFS
+ (5735 - 5835 @ 80), (30)
# 60 GHz band channels 1-4,
# ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99
(57000 - 66000 @ 2160), (43)
@@ -781,7 +778,7 @@ country LB: DFS-FCC
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-country LC: DFS-ETSI
+country LC: DFS-FCC
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (20), AUTO-BW
(5250 - 5330 @ 80), (30), DFS, AUTO-BW
@@ -1047,10 +1044,9 @@ country NO: DFS-ETSI
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country NP: DFS-ETSI
+country NP:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (20), AUTO-BW
- (5250 - 5330 @ 80), (20), DFS, AUTO-BW
+ (5170 - 5330 @ 160), (20)
(5735 - 5835 @ 80), (20)
country NZ: DFS-FCC
@@ -1066,11 +1062,11 @@ country OM: DFS-ETSI
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
-country PA: DFS-FCC
+country PA:
(2402 - 2472 @ 40), (30)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5735 - 5835 @ 80), (30)
+ (5170 - 5250 @ 80), (23), AUT0-BW
+ (5250 - 5330 @ 80), (30), AUTO-BW
+ (5735 - 5835 @ 80), (36)
country PE: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -1208,11 +1204,10 @@ country RS: DFS-ETSI
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country RU: DFS-ETSI
+country RU:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5730 @ 160), (30), DFS
+ (5170 - 5330 @ 160), (23)
+ (5490 - 5730 @ 160), (30)
(5735 - 5835 @ 80), (30)
country RW: DFS-FCC
@@ -1286,11 +1281,10 @@ country SK: DFS-ETSI
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country SN: DFS-FCC
+country SN:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24), AUTO-BW
- (5250 - 5330 @ 80), (24), DFS, AUTO-BW
- (5490 - 5730 @ 160), (24), DFS
+ (5170 - 5330 @ 160), (24)
+ (5490 - 5730 @ 160), (24)
(5735 - 5835 @ 80), (30)
country SR: DFS-ETSI
@@ -1347,12 +1341,11 @@ country TR: DFS-ETSI
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
-country TT: DFS-FCC
+country TT:
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24), AUTO-BW
- (5250 - 5330 @ 80), (24), DFS, AUTO-BW
- (5490 - 5730 @ 160), (24), DFS
- (5735 - 5835 @ 80), (30)
+ (5170 - 5330 @ 160), (27)
+ (5490 - 5730 @ 160), (36)
+ (5735 - 5835 @ 80), (36)
country TW: DFS-FCC
(2402 - 2472 @ 40), (30)
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c
index a1f23685beb5..debb6c5e52d5 100644
--- a/sound/soc/codecs/wcd-mbhc-v2.c
+++ b/sound/soc/codecs/wcd-mbhc-v2.c
@@ -902,6 +902,11 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
return -EINVAL;
}
+ /* If PA is enabled, dont check for cross-connection */
+ if (mbhc->mbhc_cb->hph_pa_on_status)
+ if (mbhc->mbhc_cb->hph_pa_on_status(mbhc->codec))
+ return false;
+
WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, reg1);
/*
* Check if there is any cross connection,
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 56882be12554..b0bb89c8d9c2 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -2366,19 +2366,20 @@ static int __tavil_codec_enable_swr(struct snd_soc_dapm_widget *w, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct tavil_priv *tavil;
- int ch_cnt;
+ int ch_cnt = 0;
tavil = snd_soc_codec_get_drvdata(codec);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) &&
- !tavil->swr.rx_7_count)
+ if (((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
+ (strnstr(w->name, "INT7 MIX2",
+ sizeof("RX INT7 MIX2")))))
tavil->swr.rx_7_count++;
if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
!tavil->swr.rx_8_count)
tavil->swr.rx_8_count++;
- ch_cnt = tavil->swr.rx_7_count + tavil->swr.rx_8_count;
+ ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
SWR_DEVICE_UP, NULL);
@@ -2386,21 +2387,22 @@ static int __tavil_codec_enable_swr(struct snd_soc_dapm_widget *w, int event)
SWR_SET_NUM_RX_CH, &ch_cnt);
break;
case SND_SOC_DAPM_POST_PMD:
- if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) &&
- tavil->swr.rx_7_count)
+ if ((strnstr(w->name, "INT7_", sizeof("RX INT7_"))) ||
+ (strnstr(w->name, "INT7 MIX2",
+ sizeof("RX INT7 MIX2"))))
tavil->swr.rx_7_count--;
if ((strnstr(w->name, "INT8_", sizeof("RX INT8_"))) &&
tavil->swr.rx_8_count)
tavil->swr.rx_8_count--;
- ch_cnt = tavil->swr.rx_7_count + tavil->swr.rx_8_count;
+ ch_cnt = !!(tavil->swr.rx_7_count) + tavil->swr.rx_8_count;
swrm_wcd_notify(tavil->swr.ctrl_data[0].swr_pdev,
SWR_SET_NUM_RX_CH, &ch_cnt);
break;
}
- dev_dbg(tavil->dev, "%s: current swr ch cnt: %d\n",
- __func__, tavil->swr.rx_7_count + tavil->swr.rx_8_count);
+ dev_dbg(tavil->dev, "%s: %s: current swr ch cnt: %d\n",
+ __func__, w->name, ch_cnt);
return 0;
}
@@ -3685,6 +3687,34 @@ static void tavil_tx_mute_update_callback(struct work_struct *work)
snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x10, 0x00);
}
+static int tavil_codec_enable_rx_path_clk(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ u16 sidetone_reg;
+
+ dev_dbg(codec->dev, "%s %d %d\n", __func__, event, w->shift);
+ sidetone_reg = WCD934X_CDC_RX0_RX_PATH_CFG1 + 0x14*(w->shift);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (!strcmp(w->name, "RX INT7 MIX2 INP"))
+ __tavil_codec_enable_swr(w, event);
+ tavil_codec_enable_interp_clk(codec, event, w->shift);
+ snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x10);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, sidetone_reg, 0x10, 0x00);
+ tavil_codec_enable_interp_clk(codec, event, w->shift);
+ if (!strcmp(w->name, "RX INT7 MIX2 INP"))
+ __tavil_codec_enable_swr(w, event);
+ break;
+ default:
+ break;
+ };
+ return 0;
+}
+
static int tavil_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -6630,18 +6660,24 @@ static const struct snd_soc_dapm_widget tavil_dapm_widgets[] = {
NULL, 0, tavil_codec_spk_boost_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_MUX("RX INT0 MIX2 INP", WCD934X_CDC_RX0_RX_PATH_CFG1, 4,
- 0, &rx_int0_mix2_inp_mux),
- SND_SOC_DAPM_MUX("RX INT1 MIX2 INP", WCD934X_CDC_RX1_RX_PATH_CFG1, 4,
- 0, &rx_int1_mix2_inp_mux),
- SND_SOC_DAPM_MUX("RX INT2 MIX2 INP", WCD934X_CDC_RX2_RX_PATH_CFG1, 4,
- 0, &rx_int2_mix2_inp_mux),
- SND_SOC_DAPM_MUX("RX INT3 MIX2 INP", WCD934X_CDC_RX3_RX_PATH_CFG1, 4,
- 0, &rx_int3_mix2_inp_mux),
- SND_SOC_DAPM_MUX("RX INT4 MIX2 INP", WCD934X_CDC_RX4_RX_PATH_CFG1, 4,
- 0, &rx_int4_mix2_inp_mux),
- SND_SOC_DAPM_MUX("RX INT7 MIX2 INP", WCD934X_CDC_RX7_RX_PATH_CFG1, 4,
- 0, &rx_int7_mix2_inp_mux),
+ SND_SOC_DAPM_MUX_E("RX INT0 MIX2 INP", SND_SOC_NOPM, INTERP_EAR,
+ 0, &rx_int0_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT1 MIX2 INP", SND_SOC_NOPM, INTERP_HPHL,
+ 0, &rx_int1_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT2 MIX2 INP", SND_SOC_NOPM, INTERP_HPHR,
+ 0, &rx_int2_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT3 MIX2 INP", SND_SOC_NOPM, INTERP_LO1,
+ 0, &rx_int3_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT4 MIX2 INP", SND_SOC_NOPM, INTERP_LO2,
+ 0, &rx_int4_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MUX_E("RX INT7 MIX2 INP", SND_SOC_NOPM, INTERP_SPKR1,
+ 0, &rx_int7_mix2_inp_mux, tavil_codec_enable_rx_path_clk,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
WCD_DAPM_MUX("CDC_IF TX0 MUX", WCD934X_TX0, cdc_if_tx0),
WCD_DAPM_MUX("CDC_IF TX1 MUX", WCD934X_TX1, cdc_if_tx1),
diff --git a/sound/soc/msm/msmfalcon-common.c b/sound/soc/msm/msmfalcon-common.c
index 6c96a0778b52..c82319539f39 100644
--- a/sound/soc/msm/msmfalcon-common.c
+++ b/sound/soc/msm/msmfalcon-common.c
@@ -28,6 +28,112 @@
#define DEV_NAME_STR_LEN 32
#define DEFAULT_MCLK_RATE 9600000
+struct dev_config {
+ u32 sample_rate;
+ u32 bit_format;
+ u32 channels;
+};
+
+/* TDM default config */
+static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+ { /* PRI TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+ },
+ { /* SEC TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+ },
+ { /* TERT TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+ },
+ { /* QUAT TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+ }
+};
+
+/* TDM default config */
+static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+ { /* PRI TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+ },
+ { /* SEC TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+ },
+ { /* TERT TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+ },
+ { /* QUAT TDM */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+ {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+ }
+};
+
+static struct dev_config usb_rx_cfg = {
+ .sample_rate = SAMPLING_RATE_48KHZ,
+ .bit_format = SNDRV_PCM_FORMAT_S16_LE,
+ .channels = 2,
+};
+
+static struct dev_config usb_tx_cfg = {
+ .sample_rate = SAMPLING_RATE_48KHZ,
+ .bit_format = SNDRV_PCM_FORMAT_S16_LE,
+ .channels = 1,
+};
+
enum {
PRIM_MI2S = 0,
SEC_MI2S,
@@ -68,12 +174,6 @@ struct auxpcm_conf {
u32 ref_cnt;
};
-struct dev_config {
- u32 sample_rate;
- u32 bit_format;
- u32 channels;
-};
-
struct msm_wsa881x_dev_info {
struct device_node *of_node;
u32 index;
@@ -111,12 +211,6 @@ static struct dev_config proxy_rx_cfg = {
.channels = 2,
};
-static struct dev_config btsco_cfg = {
- .sample_rate = SAMPLING_RATE_8KHZ,
- .bit_format = SNDRV_PCM_FORMAT_S16_LE,
- .channels = 1,
-};
-
/* Default configuration of MI2S channels */
static struct dev_config mi2s_rx_cfg[] = {
[PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
@@ -155,8 +249,22 @@ static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven",
"Eight"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
+ "S32_LE"};
+static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven", "Eight"};
+static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
+static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
+ "KHZ_44P1", "KHZ_48", "KHZ_96",
+ "KHZ_192", "KHZ_352P8", "KHZ_384"};
+static const char *const usb_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven",
+ "Eight"};
+static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+ "KHZ_16", "KHZ_22P05",
+ "KHZ_32", "KHZ_44P1", "KHZ_48",
+ "KHZ_96", "KHZ_192", "KHZ_384"};
-static SOC_ENUM_SINGLE_EXT_DECL(btsco_sample_rate, auxpcm_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text);
@@ -182,6 +290,18 @@ static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_sample_rate, tdm_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_sample_rate, tdm_sample_rate_text);
static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
{
@@ -242,6 +362,439 @@ static int proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
return 1;
}
+static int tdm_get_sample_rate(int value)
+{
+ int sample_rate = 0;
+
+ switch (value) {
+ case 0:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ case 7:
+ sample_rate = SAMPLING_RATE_352P8KHZ;
+ break;
+ case 8:
+ sample_rate = SAMPLING_RATE_384KHZ;
+ break;
+ default:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int tdm_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val = 0;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 6;
+ break;
+ case SAMPLING_RATE_352P8KHZ:
+ sample_rate_val = 7;
+ break;
+ case SAMPLING_RATE_384KHZ:
+ sample_rate_val = 8;
+ break;
+ default:
+ sample_rate_val = 4;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int tdm_get_port_idx(struct snd_kcontrol *kcontrol,
+ struct tdm_port *port)
+{
+ if (port) {
+ if (strnstr(kcontrol->id.name, "PRI",
+ sizeof(kcontrol->id.name))) {
+ port->mode = TDM_PRI;
+ } else if (strnstr(kcontrol->id.name, "SEC",
+ sizeof(kcontrol->id.name))) {
+ port->mode = TDM_SEC;
+ } else if (strnstr(kcontrol->id.name, "TERT",
+ sizeof(kcontrol->id.name))) {
+ port->mode = TDM_TERT;
+ } else if (strnstr(kcontrol->id.name, "QUAT",
+ sizeof(kcontrol->id.name))) {
+ port->mode = TDM_QUAT;
+ } else {
+ pr_err("%s: unsupported mode in: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ if (strnstr(kcontrol->id.name, "RX_0",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_0",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_0;
+ } else if (strnstr(kcontrol->id.name, "RX_1",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_1",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_1;
+ } else if (strnstr(kcontrol->id.name, "RX_2",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_2",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_2;
+ } else if (strnstr(kcontrol->id.name, "RX_3",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_3",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_3;
+ } else if (strnstr(kcontrol->id.name, "RX_4",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_4",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_4;
+ } else if (strnstr(kcontrol->id.name, "RX_5",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_5",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_5;
+ } else if (strnstr(kcontrol->id.name, "RX_6",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_6",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_6;
+ } else if (strnstr(kcontrol->id.name, "RX_7",
+ sizeof(kcontrol->id.name)) ||
+ strnstr(kcontrol->id.name, "TX_7",
+ sizeof(kcontrol->id.name))) {
+ port->channel = TDM_7;
+ } else {
+ pr_err("%s: unsupported channel in: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+ } else
+ return -EINVAL;
+ return 0;
+}
+
+static int tdm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+ tdm_rx_cfg[port.mode][port.channel].sample_rate);
+
+ pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_rx_cfg[port.mode][port.channel].sample_rate =
+ tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+ tdm_tx_cfg[port.mode][port.channel].sample_rate);
+
+ pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_tx_cfg[port.mode][port.channel].sample_rate =
+ tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_get_format(int value)
+{
+ int format = 0;
+
+ switch (value) {
+ case 0:
+ format = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ case 1:
+ format = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 2:
+ format = SNDRV_PCM_FORMAT_S32_LE;
+ break;
+ default:
+ format = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ return format;
+}
+
+static int tdm_get_format_val(int format)
+{
+ int value = 0;
+
+ switch (format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ value = 0;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ value = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ value = 2;
+ break;
+ default:
+ value = 0;
+ break;
+ }
+ return value;
+}
+
+static int tdm_rx_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+ tdm_rx_cfg[port.mode][port.channel].bit_format);
+
+ pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].bit_format,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_rx_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_rx_cfg[port.mode][port.channel].bit_format =
+ tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].bit_format,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_tx_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+ tdm_tx_cfg[port.mode][port.channel].bit_format);
+
+ pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].bit_format,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_tx_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_tx_cfg[port.mode][port.channel].bit_format =
+ tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].bit_format,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+
+ ucontrol->value.enumerated.item[0] =
+ tdm_rx_cfg[port.mode][port.channel].channels - 1;
+
+ pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].channels - 1,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_rx_cfg[port.mode][port.channel].channels =
+ ucontrol->value.enumerated.item[0] + 1;
+
+ pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+ tdm_rx_cfg[port.mode][port.channel].channels,
+ ucontrol->value.enumerated.item[0] + 1);
+ }
+ return ret;
+}
+
+static int tdm_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ ucontrol->value.enumerated.item[0] =
+ tdm_tx_cfg[port.mode][port.channel].channels - 1;
+
+ pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].channels - 1,
+ ucontrol->value.enumerated.item[0]);
+ }
+ return ret;
+}
+
+static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tdm_port port;
+ int ret = tdm_get_port_idx(kcontrol, &port);
+
+ if (ret) {
+ pr_err("%s: unsupported control: %s",
+ __func__, kcontrol->id.name);
+ } else {
+ tdm_tx_cfg[port.mode][port.channel].channels =
+ ucontrol->value.enumerated.item[0] + 1;
+
+ pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+ tdm_tx_cfg[port.mode][port.channel].channels,
+ ucontrol->value.enumerated.item[0] + 1);
+ }
+ return ret;
+}
+
static int aux_pcm_get_sample_rate(int value)
{
int sample_rate;
@@ -299,32 +852,6 @@ static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
return idx;
}
-static int btsco_sample_rate_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- btsco_cfg.sample_rate =
- aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
-
- pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__,
- btsco_cfg.sample_rate,
- ucontrol->value.enumerated.item[0]);
-
- return 0;
-}
-
-static int btsco_sample_rate_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.enumerated.item[0] =
- aux_pcm_get_sample_rate_val(btsco_cfg.sample_rate);
-
- pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__,
- btsco_cfg.sample_rate,
- ucontrol->value.enumerated.item[0]);
-
- return 0;
-}
-
static int aux_pcm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -632,12 +1159,331 @@ static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
return 1;
}
+static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: usb_audio_rx_ch = %d\n", __func__,
+ usb_rx_cfg.channels);
+ ucontrol->value.integer.value[0] = usb_rx_cfg.channels - 1;
+ return 0;
+}
+
+static int usb_audio_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ usb_rx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: usb_audio_rx_ch = %d\n", __func__, usb_rx_cfg.channels);
+ return 1;
+}
+
+static int usb_audio_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int sample_rate_val;
+
+ switch (usb_rx_cfg.sample_rate) {
+ case SAMPLING_RATE_384KHZ:
+ sample_rate_val = 9;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 8;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 7;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 6;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_22P05KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_11P025KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ sample_rate_val = 0;
+ break;
+ }
+
+ ucontrol->value.integer.value[0] = sample_rate_val;
+ pr_debug("%s: usb_audio_rx_sample_rate = %d\n", __func__,
+ usb_rx_cfg.sample_rate);
+ return 0;
+}
+
+static int usb_audio_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 9:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+ break;
+ case 8:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ case 7:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+ break;
+ case 2:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 1:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+ break;
+ case 0:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ default:
+ usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+
+ pr_debug("%s: control value = %ld, usb_audio_rx_sample_rate = %d\n",
+ __func__, ucontrol->value.integer.value[0],
+ usb_rx_cfg.sample_rate);
+ return 0;
+}
+
+static int usb_audio_rx_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (usb_rx_cfg.bit_format) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ ucontrol->value.integer.value[0] = 3;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+
+ pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+ __func__, usb_rx_cfg.bit_format,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int usb_audio_rx_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int rc = 0;
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 3:
+ usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+ break;
+ case 2:
+ usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+ break;
+ case 1:
+ usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 0:
+ default:
+ usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+ __func__, usb_rx_cfg.bit_format,
+ ucontrol->value.integer.value[0]);
+
+ return rc;
+}
+
+static int usb_audio_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: usb_audio_tx_ch = %d\n", __func__,
+ usb_tx_cfg.channels);
+ ucontrol->value.integer.value[0] = usb_tx_cfg.channels - 1;
+ return 0;
+}
+
+static int usb_audio_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ usb_tx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: usb_audio_tx_ch = %d\n", __func__, usb_tx_cfg.channels);
+ return 1;
+}
+
+static int usb_audio_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int sample_rate_val;
+
+ switch (usb_tx_cfg.sample_rate) {
+ case SAMPLING_RATE_384KHZ:
+ sample_rate_val = 9;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 8;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 7;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 6;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_22P05KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_11P025KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ default:
+ sample_rate_val = 6;
+ break;
+ }
+
+ ucontrol->value.integer.value[0] = sample_rate_val;
+ pr_debug("%s: usb_audio_tx_sample_rate = %d\n", __func__,
+ usb_tx_cfg.sample_rate);
+ return 0;
+}
+
+static int usb_audio_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 9:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+ break;
+ case 8:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ case 7:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+ break;
+ case 2:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 1:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+ break;
+ case 0:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ default:
+ usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+
+ pr_debug("%s: control value = %ld, usb_audio_tx_sample_rate = %d\n",
+ __func__, ucontrol->value.integer.value[0],
+ usb_tx_cfg.sample_rate);
+ return 0;
+}
+
+static int usb_audio_tx_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (usb_tx_cfg.bit_format) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ ucontrol->value.integer.value[0] = 3;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+
+ pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+ __func__, usb_tx_cfg.bit_format,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int rc = 0;
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 3:
+ usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+ break;
+ case 2:
+ usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+ break;
+ case 1:
+ usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 0:
+ default:
+ usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+ __func__, usb_tx_cfg.bit_format,
+ ucontrol->value.integer.value[0]);
+
+ return rc;
+}
+
const struct snd_kcontrol_new msm_common_snd_controls[] = {
SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
proxy_rx_ch_get, proxy_rx_ch_put),
- SOC_ENUM_EXT("BTSCO SampleRate", btsco_sample_rate,
- btsco_sample_rate_get,
- btsco_sample_rate_put),
SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
aux_pcm_rx_sample_rate_get,
aux_pcm_rx_sample_rate_put),
@@ -702,8 +1548,119 @@ const struct snd_kcontrol_new msm_common_snd_controls[] = {
msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs,
msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+ SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
+ usb_audio_rx_ch_get, usb_audio_rx_ch_put),
+ SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
+ usb_audio_tx_ch_get, usb_audio_tx_ch_put),
+ SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
+ usb_audio_rx_format_get, usb_audio_rx_format_put),
+ SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
+ usb_audio_tx_format_get, usb_audio_tx_format_put),
+ SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
+ usb_audio_rx_sample_rate_get,
+ usb_audio_rx_sample_rate_put),
+ SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate,
+ usb_audio_tx_sample_rate_get,
+ usb_audio_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+ tdm_rx_sample_rate_get,
+ tdm_rx_sample_rate_put),
+ SOC_ENUM_EXT("PRI_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+ tdm_tx_sample_rate_get,
+ tdm_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRI_TDM_RX_0 Format", tdm_rx_format,
+ tdm_rx_format_get,
+ tdm_rx_format_put),
+ SOC_ENUM_EXT("PRI_TDM_TX_0 Format", tdm_tx_format,
+ tdm_tx_format_get,
+ tdm_tx_format_put),
+ SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", tdm_rx_chs,
+ tdm_rx_ch_get,
+ tdm_rx_ch_put),
+ SOC_ENUM_EXT("PRI_TDM_TX_0 Channels", tdm_tx_chs,
+ tdm_tx_ch_get,
+ tdm_tx_ch_put),
+ SOC_ENUM_EXT("SEC_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+ tdm_rx_sample_rate_get,
+ tdm_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+ tdm_tx_sample_rate_get,
+ tdm_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_TDM_RX_0 Format", tdm_rx_format,
+ tdm_rx_format_get,
+ tdm_rx_format_put),
+ SOC_ENUM_EXT("SEC_TDM_TX_0 Format", tdm_tx_format,
+ tdm_tx_format_get,
+ tdm_tx_format_put),
+ SOC_ENUM_EXT("SEC_TDM_RX_0 Channels", tdm_rx_chs,
+ tdm_rx_ch_get,
+ tdm_rx_ch_put),
+ SOC_ENUM_EXT("SEC_TDM_TX_0 Channels", tdm_tx_chs,
+ tdm_tx_ch_get,
+ tdm_tx_ch_put),
+ SOC_ENUM_EXT("TERT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+ tdm_rx_sample_rate_get,
+ tdm_rx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+ tdm_tx_sample_rate_get,
+ tdm_tx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_TDM_RX_0 Format", tdm_rx_format,
+ tdm_rx_format_get,
+ tdm_rx_format_put),
+ SOC_ENUM_EXT("TERT_TDM_TX_0 Format", tdm_tx_format,
+ tdm_tx_format_get,
+ tdm_tx_format_put),
+ SOC_ENUM_EXT("TERT_TDM_RX_0 Channels", tdm_rx_chs,
+ tdm_rx_ch_get,
+ tdm_rx_ch_put),
+ SOC_ENUM_EXT("TERT_TDM_TX_0 Channels", tdm_tx_chs,
+ tdm_tx_ch_get,
+ tdm_tx_ch_put),
+ SOC_ENUM_EXT("QUAT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+ tdm_rx_sample_rate_get,
+ tdm_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+ tdm_tx_sample_rate_get,
+ tdm_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_TDM_RX_0 Format", tdm_rx_format,
+ tdm_rx_format_get,
+ tdm_rx_format_put),
+ SOC_ENUM_EXT("QUAT_TDM_TX_0 Format", tdm_tx_format,
+ tdm_tx_format_get,
+ tdm_tx_format_put),
+ SOC_ENUM_EXT("QUAT_TDM_RX_0 Channels", tdm_rx_chs,
+ tdm_rx_ch_get,
+ tdm_rx_ch_put),
+ SOC_ENUM_EXT("QUAT_TDM_TX_0 Channels", tdm_tx_chs,
+ tdm_tx_ch_get,
+ tdm_tx_ch_put),
};
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
+ int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
/**
* msm_common_be_hw_params_fixup - updates settings of ALSA BE hw params.
*
@@ -726,10 +1683,18 @@ int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
__func__, params_format(params), params_rate(params));
switch (dai_link->be_id) {
- case MSM_BACKEND_DAI_INT_BT_SCO_RX:
- case MSM_BACKEND_DAI_INT_BT_SCO_TX:
- channels->min = channels->max = btsco_cfg.channels;
- rate->min = rate->max = 1;
+ case MSM_BACKEND_DAI_USB_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ usb_rx_cfg.bit_format);
+ rate->min = rate->max = usb_rx_cfg.sample_rate;
+ channels->min = channels->max = usb_rx_cfg.channels;
+ break;
+
+ case MSM_BACKEND_DAI_USB_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ usb_tx_cfg.bit_format);
+ rate->min = rate->max = usb_tx_cfg.sample_rate;
+ channels->min = channels->max = usb_tx_cfg.channels;
break;
case MSM_BACKEND_DAI_AFE_PCM_RX:
@@ -737,6 +1702,70 @@ int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
rate->min = rate->max = SAMPLING_RATE_48KHZ;
break;
+ case MSM_BACKEND_DAI_PRI_TDM_RX_0:
+ channels->min = channels->max =
+ tdm_rx_cfg[TDM_PRI][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_rx_cfg[TDM_PRI][TDM_0].bit_format);
+ rate->min = rate->max = tdm_rx_cfg[TDM_PRI][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_PRI_TDM_TX_0:
+ channels->min = channels->max =
+ tdm_tx_cfg[TDM_PRI][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_tx_cfg[TDM_PRI][TDM_0].bit_format);
+ rate->min = rate->max = tdm_tx_cfg[TDM_PRI][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_SEC_TDM_RX_0:
+ channels->min = channels->max =
+ tdm_rx_cfg[TDM_SEC][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_rx_cfg[TDM_SEC][TDM_0].bit_format);
+ rate->min = rate->max = tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_SEC_TDM_TX_0:
+ channels->min = channels->max =
+ tdm_tx_cfg[TDM_SEC][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_tx_cfg[TDM_SEC][TDM_0].bit_format);
+ rate->min = rate->max = tdm_tx_cfg[TDM_SEC][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_TERT_TDM_RX_0:
+ channels->min = channels->max =
+ tdm_rx_cfg[TDM_TERT][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_rx_cfg[TDM_TERT][TDM_0].bit_format);
+ rate->min = rate->max = tdm_rx_cfg[TDM_TERT][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_TERT_TDM_TX_0:
+ channels->min = channels->max =
+ tdm_tx_cfg[TDM_TERT][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_tx_cfg[TDM_TERT][TDM_0].bit_format);
+ rate->min = rate->max = tdm_tx_cfg[TDM_TERT][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_QUAT_TDM_RX_0:
+ channels->min = channels->max =
+ tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_rx_cfg[TDM_QUAT][TDM_0].bit_format);
+ rate->min = rate->max = tdm_rx_cfg[TDM_QUAT][TDM_0].sample_rate;
+ break;
+
+ case MSM_BACKEND_DAI_QUAT_TDM_TX_0:
+ channels->min = channels->max =
+ tdm_tx_cfg[TDM_QUAT][TDM_0].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ tdm_tx_cfg[TDM_QUAT][TDM_0].bit_format);
+ rate->min = rate->max = tdm_tx_cfg[TDM_QUAT][TDM_0].sample_rate;
+ break;
+
case MSM_BACKEND_DAI_AUXPCM_RX:
rate->min = rate->max =
aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate;
@@ -1640,11 +2669,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
if (!strcmp(match->data, "tasha_codec") ||
!strcmp(match->data, "tavil_codec")) {
+ if (!strcmp(match->data, "tasha_codec"))
+ pdata->snd_card_val = EXT_SND_CARD_TASHA;
+ else
+ pdata->snd_card_val = EXT_SND_CARD_TAVIL;
ret = msm_ext_cdc_init(pdev, pdata, &card, &mbhc_cfg);
if (ret)
goto err;
} else if (!strcmp(match->data, "internal_codec")) {
- pdata->int_codec = 1;
+ pdata->snd_card_val = INT_SND_CARD;
ret = msm_int_cdc_init(pdev, pdata, &card, &mbhc_cfg);
if (ret)
goto err;
@@ -1656,12 +2689,15 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
if (!card)
goto err;
- /*reading the gpio configurations from dtsi file*/
- ret = msm_gpioset_initialize(CLIENT_WCD, &pdev->dev);
- if (ret < 0) {
- dev_err(&pdev->dev,
- "%s: error reading dtsi files%d\n", __func__, ret);
- goto err;
+ if (pdata->snd_card_val == INT_SND_CARD) {
+ /*reading the gpio configurations from dtsi file*/
+ ret = msm_gpioset_initialize(CLIENT_WCD, &pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "%s: error reading dtsi files%d\n",
+ __func__, ret);
+ goto err;
+ }
}
/*
@@ -1710,6 +2746,8 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
ret);
goto err;
}
+ if (pdata->snd_card_val != INT_SND_CARD)
+ msm_ext_register_audio_notifier();
return 0;
err:
if (pdata->us_euro_gpio > 0) {
@@ -1738,7 +2776,7 @@ static int msm_asoc_machine_remove(struct platform_device *pdev)
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- if (pdata->int_codec)
+ if (pdata->snd_card_val == INT_SND_CARD)
mutex_destroy(&pdata->cdc_int_mclk0_mutex);
msm_free_auxdev_mem(pdev);
diff --git a/sound/soc/msm/msmfalcon-common.h b/sound/soc/msm/msmfalcon-common.h
index ff8232d6fcbb..5f6b8592acec 100644
--- a/sound/soc/msm/msmfalcon-common.h
+++ b/sound/soc/msm/msmfalcon-common.h
@@ -31,12 +31,46 @@
#define SAMPLING_RATE_352P8KHZ 352800
#define SAMPLING_RATE_384KHZ 384000
+#define TDM_CHANNEL_MAX 8
+#define TDM_SLOT_OFFSET_MAX 8
+
+enum {
+ TDM_0 = 0,
+ TDM_1,
+ TDM_2,
+ TDM_3,
+ TDM_4,
+ TDM_5,
+ TDM_6,
+ TDM_7,
+ TDM_PORT_MAX,
+};
+
+enum {
+ TDM_PRI = 0,
+ TDM_SEC,
+ TDM_TERT,
+ TDM_QUAT,
+ TDM_INTERFACE_MAX,
+};
+
+struct tdm_port {
+ u32 mode;
+ u32 channel;
+};
+
extern const struct snd_kcontrol_new msm_common_snd_controls[];
struct msmfalcon_codec {
void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
enum afe_config_type config_type);
};
+enum {
+ INT_SND_CARD,
+ EXT_SND_CARD_TASHA,
+ EXT_SND_CARD_TAVIL,
+};
+
struct msm_asoc_mach_data {
int us_euro_gpio; /* used by gpio driver API */
int hph_en1_gpio;
@@ -50,6 +84,7 @@ struct msm_asoc_mach_data {
int spk_ext_pa_gpio;
int mclk_freq;
int lb_mode;
+ int snd_card_val;
u8 micbias1_cap_mode;
u8 micbias2_cap_mode;
atomic_t int_mclk0_rsc_ref;
@@ -57,7 +92,6 @@ struct msm_asoc_mach_data {
struct mutex cdc_int_mclk0_mutex;
struct delayed_work disable_int_mclk0_work;
struct afe_clk_set digital_cdc_core_clk;
- bool int_codec;
};
int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
diff --git a/sound/soc/msm/msmfalcon-ext-dai-links.c b/sound/soc/msm/msmfalcon-ext-dai-links.c
index 4dca7908c108..6f066c5945a9 100644
--- a/sound/soc/msm/msmfalcon-ext-dai-links.c
+++ b/sound/soc/msm/msmfalcon-ext-dai-links.c
@@ -16,6 +16,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include "qdsp6v2/msm-pcm-routing-v2.h"
#include "../codecs/wcd9335.h"
#include "msmfalcon-common.h"
@@ -25,7 +26,11 @@
#define __CHIPSET__ "MSMFALCON "
#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
-static struct snd_soc_card snd_soc_card_msm_card;
+#define WCN_CDC_SLIM_RX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX 3
+
+static struct snd_soc_card snd_soc_card_msm_card_tavil;
+static struct snd_soc_card snd_soc_card_msm_card_tasha;
static struct snd_soc_ops msm_ext_slimbus_be_ops = {
.hw_params = msm_snd_hw_params,
@@ -49,6 +54,222 @@ static struct snd_soc_ops msm_aux_pcm_be_ops = {
.shutdown = msm_aux_pcm_snd_shutdown,
};
+static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
+{
+ unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
+ unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX] = {159, 160, 161};
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+ return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+}
+
+static int msm_wcn_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ int ret;
+
+ dev_dbg(rtd->dev, "%s: %s_tx_dai_id_%d\n", __func__,
+ codec_dai->name, codec_dai->id);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret) {
+ dev_err(rtd->dev,
+ "%s: failed to get BTFM codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+ dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
+ __func__, tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
+ if (ret)
+ dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+
+exit:
+ return ret;
+}
+
+static struct snd_soc_ops msm_wcn_ops = {
+ .hw_params = msm_wcn_hw_params,
+};
+
+/*TDM default offset currently only supporting TDM_RX_0 and TDM_TX_0 */
+static unsigned int tdm_slot_offset[TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = {
+ {0, 4, 8, 12, 16, 20, 24, 28},/* TX_0 | RX_0 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_1 | RX_1 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_2 | RX_2 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_3 | RX_3 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_4 | RX_4 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_5 | RX_5 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_6 | RX_6 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_7 | RX_7 */
+};
+
+static unsigned int tdm_param_set_slot_mask(u16 port_id, int slot_width,
+ int slots)
+{
+ unsigned int slot_mask = 0;
+ int i, j;
+ unsigned int *slot_offset;
+
+ for (i = TDM_0; i < TDM_PORT_MAX; i++) {
+ slot_offset = tdm_slot_offset[i];
+
+ for (j = 0; j < TDM_SLOT_OFFSET_MAX; j++) {
+ if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID)
+ slot_mask |=
+ (1 << ((slot_offset[j] * 8) / slot_width));
+ else
+ break;
+ }
+ }
+
+ return slot_mask;
+}
+
+static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ int channels, slot_width, slots;
+ unsigned int slot_mask;
+ unsigned int *slot_offset;
+ int offset_channels = 0;
+ int i;
+
+ pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
+
+ channels = params_channels(params);
+ switch (channels) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /*
+ * up to 8 channels HW config should
+ * use 32 bit slot width for max support of
+ * stream bit width. (slot_width > bit_width)
+ */
+ slot_width = 32;
+ break;
+ default:
+ pr_err("%s: invalid param format 0x%x\n",
+ __func__, params_format(params));
+ return -EINVAL;
+ }
+ slots = 8;
+ slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
+ slot_width,
+ slots);
+ if (!slot_mask) {
+ pr_err("%s: invalid slot_mask 0x%x\n",
+ __func__, slot_mask);
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_err("%s: invalid param channels %d\n",
+ __func__, channels);
+ return -EINVAL;
+ }
+ /* currently only supporting TDM_RX_0 and TDM_TX_0 */
+ switch (cpu_dai->id) {
+ case AFE_PORT_ID_PRIMARY_TDM_RX:
+ case AFE_PORT_ID_SECONDARY_TDM_RX:
+ case AFE_PORT_ID_TERTIARY_TDM_RX:
+ case AFE_PORT_ID_QUATERNARY_TDM_RX:
+ case AFE_PORT_ID_PRIMARY_TDM_TX:
+ case AFE_PORT_ID_SECONDARY_TDM_TX:
+ case AFE_PORT_ID_TERTIARY_TDM_TX:
+ case AFE_PORT_ID_QUATERNARY_TDM_TX:
+ slot_offset = tdm_slot_offset[TDM_0];
+ break;
+ default:
+ pr_err("%s: dai id 0x%x not supported\n",
+ __func__, cpu_dai->id);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) {
+ if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID)
+ offset_channels++;
+ else
+ break;
+ }
+
+ if (offset_channels == 0) {
+ pr_err("%s: slot offset not supported, offset_channels %d\n",
+ __func__, offset_channels);
+ return -EINVAL;
+ }
+
+ if (channels > offset_channels) {
+ pr_err("%s: channels %d exceed offset_channels %d\n",
+ __func__, channels, offset_channels);
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
+ slots, slot_width);
+ if (ret < 0) {
+ pr_err("%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
+ channels, slot_offset);
+ if (ret < 0) {
+ pr_err("%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ } else {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
+ slots, slot_width);
+ if (ret < 0) {
+ pr_err("%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
+ slot_offset, 0, NULL);
+ if (ret < 0) {
+ pr_err("%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static struct snd_soc_ops msm_tdm_be_ops = {
+ .hw_params = msm_tdm_snd_hw_params
+};
+
static struct snd_soc_dai_link msm_ext_tasha_fe_dai[] = {
/* tasha_vifeedback for speaker protection */
{
@@ -1167,6 +1388,145 @@ static struct snd_soc_dai_link msm_ext_common_be_dai[] = {
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_USB_AUDIO_RX,
+ .stream_name = "USB Audio Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.28672",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_USB_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_USB_AUDIO_TX,
+ .stream_name = "USB Audio Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.28673",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_USB_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_TDM_RX_0,
+ .stream_name = "Primary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36864",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_TDM_TX_0,
+ .stream_name = "Primary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36865",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_TDM_RX_0,
+ .stream_name = "Secondary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36880",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_TDM_TX_0,
+ .stream_name = "Secondary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36881",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_TDM_RX_0,
+ .stream_name = "Tertiary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36896",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_TDM_TX_0,
+ .stream_name = "Tertiary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36897",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_TDM_RX_0,
+ .stream_name = "Quaternary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36912",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_TDM_TX_0,
+ .stream_name = "Quaternary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36913",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
@@ -1415,13 +1775,66 @@ static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
},
};
+static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_7_RX,
+ .stream_name = "Slimbus7 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16398",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ /* BT codec driver determines capabilities based on
+ * dai name, bt codecdai name should always contains
+ * supported usecase information
+ */
+ .codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_wcn_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_7_TX,
+ .stream_name = "Slimbus7 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16399",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ .codec_dai_name = "btfm_bt_sco_slim_tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_wcn_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_8_TX,
+ .stream_name = "Slimbus8 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16401",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ .codec_dai_name = "btfm_fm_slim_tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .init = &msm_wcn_init,
+ .ops = &msm_wcn_ops,
+ .ignore_suspend = 1,
+ },
+};
+
static struct snd_soc_dai_link msm_ext_tasha_dai_links[
ARRAY_SIZE(msm_ext_common_fe_dai) +
ARRAY_SIZE(msm_ext_tasha_fe_dai) +
ARRAY_SIZE(msm_ext_common_be_dai) +
ARRAY_SIZE(msm_ext_tasha_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
-ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+ARRAY_SIZE(msm_auxpcm_be_dai_links) +
+ARRAY_SIZE(msm_wcn_be_dai_links)];
static struct snd_soc_dai_link msm_ext_tavil_dai_links[
ARRAY_SIZE(msm_ext_common_fe_dai) +
@@ -1429,7 +1842,8 @@ ARRAY_SIZE(msm_ext_tavil_fe_dai) +
ARRAY_SIZE(msm_ext_common_be_dai) +
ARRAY_SIZE(msm_ext_tavil_be_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
-ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+ARRAY_SIZE(msm_auxpcm_be_dai_links) +
+ARRAY_SIZE(msm_wcn_be_dai_links)];
/**
* populate_snd_card_dailinks - prepares dailink array and initializes card.
@@ -1438,13 +1852,24 @@ ARRAY_SIZE(msm_auxpcm_be_dai_links)];
*
* Returns card on success or NULL on failure.
*/
-struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+struct snd_soc_card *populate_snd_card_dailinks(struct device *dev,
+ int snd_card_val)
{
- struct snd_soc_card *card = &snd_soc_card_msm_card;
+ struct snd_soc_card *card;
struct snd_soc_dai_link *msm_ext_dai_links = NULL;
int ret, len1, len2, len3, len4;
enum codec_variant codec_ver = 0;
+ if (snd_card_val == EXT_SND_CARD_TASHA) {
+ card = &snd_soc_card_msm_card_tasha;
+ } else if (snd_card_val == EXT_SND_CARD_TAVIL) {
+ card = &snd_soc_card_msm_card_tavil;
+ } else {
+ dev_err(dev, "%s: failing as no matching card name\n",
+ __func__);
+ return NULL;
+ }
+
card->dev = dev;
ret = snd_soc_of_parse_card_name(card, "qcom,model");
if (ret) {
@@ -1484,6 +1909,14 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
sizeof(msm_auxpcm_be_dai_links));
len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
+ if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
+ dev_dbg(dev, "%s(): WCN BTFM support present\n",
+ __func__);
+ memcpy(msm_ext_tasha_dai_links + len4,
+ msm_wcn_be_dai_links,
+ sizeof(msm_wcn_be_dai_links));
+ len4 += ARRAY_SIZE(msm_wcn_be_dai_links);
+ }
msm_ext_dai_links = msm_ext_tasha_dai_links;
} else if (strnstr(card->name, "tavil", strlen(card->name))) {
len1 = ARRAY_SIZE(msm_ext_common_fe_dai);
@@ -1512,6 +1945,14 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
sizeof(msm_auxpcm_be_dai_links));
len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
+ if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
+ dev_dbg(dev, "%s(): WCN BTFM support present\n",
+ __func__);
+ memcpy(msm_ext_tavil_dai_links + len4,
+ msm_wcn_be_dai_links,
+ sizeof(msm_wcn_be_dai_links));
+ len4 += ARRAY_SIZE(msm_wcn_be_dai_links);
+ }
msm_ext_dai_links = msm_ext_tavil_dai_links;
} else {
dev_err(dev, "%s: failing as no matching card name\n",
@@ -1520,7 +1961,6 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
}
card->dai_link = msm_ext_dai_links;
card->num_links = len4;
- card->dev = dev;
return card;
}
diff --git a/sound/soc/msm/msmfalcon-external.c b/sound/soc/msm/msmfalcon-external.c
index 046c63bb73cf..3934c50c48a9 100644
--- a/sound/soc/msm/msmfalcon-external.c
+++ b/sound/soc/msm/msmfalcon-external.c
@@ -122,6 +122,7 @@ static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_88P2", "KHZ_96", "KHZ_176P4",
"KHZ_192", "KHZ_352P8", "KHZ_384"};
static const char *const spk_function_text[] = {"Off", "On"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
@@ -140,6 +141,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static int slim_get_sample_rate_val(int sample_rate)
{
@@ -302,6 +304,59 @@ static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
return port_id;
}
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ /*
+ * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
+ * when used for BT_SCO use case. Return either Rx or Tx sample rate
+ * value.
+ */
+ switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+ case SAMPLING_RATE_48KHZ:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+ pr_debug("%s: sample rate = %d", __func__,
+ slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+ return 0;
+}
+
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+ slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 0:
+ default:
+ slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+ slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ }
+ pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
+ __func__,
+ slim_rx_cfg[SLIM_RX_7].sample_rate,
+ slim_tx_cfg[SLIM_TX_7].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -670,6 +725,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+ SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+ msm_bt_sample_rate_get,
+ msm_bt_sample_rate_put),
};
static int msm_slim_get_ch_from_beid(int32_t be_id)
@@ -1627,6 +1685,21 @@ err_mbhc_cal:
EXPORT_SYMBOL(msm_audrx_init);
/**
+ * msm_ext_register_audio_notifier - register SSR notifier.
+ */
+void msm_ext_register_audio_notifier(void)
+{
+ int ret;
+
+ ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN,
+ &service_nb);
+ if (ret < 0)
+ pr_err("%s: Audio notifier register failed ret = %d\n",
+ __func__, ret);
+}
+EXPORT_SYMBOL(msm_ext_register_audio_notifier);
+
+/**
* msm_ext_cdc_init - external codec machine specific init.
*
* @pdev: platform device handle
@@ -1650,24 +1723,16 @@ int msm_ext_cdc_init(struct platform_device *pdev,
wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2;
wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false;
- *card = populate_snd_card_dailinks(&pdev->dev);
+ *card = populate_snd_card_dailinks(&pdev->dev, pdata->snd_card_val);
if (!(*card)) {
dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
ret = -EPROBE_DEFER;
goto err;
}
- (*card)->dev = &pdev->dev;
spdev = pdev;
platform_set_drvdata(pdev, *card);
snd_soc_card_set_drvdata(*card, pdata);
is_initial_boot = true;
- ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN,
- &service_nb);
- if (ret < 0) {
- pr_err("%s: Audio notifier register failed ret = %d\n",
- __func__, ret);
- goto err;
- }
pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,hph-en1-gpio", 0);
if (!gpio_is_valid(pdata->hph_en1_gpio))
diff --git a/sound/soc/msm/msmfalcon-external.h b/sound/soc/msm/msmfalcon-external.h
index 24aa7ea53a09..654cb70b9c84 100644
--- a/sound/soc/msm/msmfalcon-external.h
+++ b/sound/soc/msm/msmfalcon-external.h
@@ -26,12 +26,14 @@ int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
int msm_audrx_init(struct snd_soc_pcm_runtime *rtd);
int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params);
-struct snd_soc_card *populate_snd_card_dailinks(struct device *dev);
+struct snd_soc_card *populate_snd_card_dailinks(struct device *dev,
+ int snd_card_val);
int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
#ifdef CONFIG_SND_SOC_EXT_CODEC
int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
struct snd_soc_card **, struct wcd_mbhc_config *);
+void msm_ext_register_audio_notifier(void);
#else
inline int msm_ext_cdc_init(struct platform_device *pdev,
struct msm_asoc_mach_data *pdata,
@@ -40,5 +42,9 @@ inline int msm_ext_cdc_init(struct platform_device *pdev,
{
return 0;
}
+
+inline void msm_ext_register_audio_notifier(void)
+{
+}
#endif
#endif
diff --git a/sound/soc/msm/msmfalcon-internal.c b/sound/soc/msm/msmfalcon-internal.c
index 3a8b88cdfb64..180ff492e9e9 100644
--- a/sound/soc/msm/msmfalcon-internal.c
+++ b/sound/soc/msm/msmfalcon-internal.c
@@ -27,6 +27,9 @@
#define WCD_MBHC_DEF_RLOADS 5
+#define WCN_CDC_SLIM_RX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX 3
+
enum {
INT0_MI2S = 0,
INT1_MI2S,
@@ -38,6 +41,24 @@ enum {
INT_MI2S_MAX,
};
+enum {
+ BT_SLIM7,
+ FM_SLIM8,
+ SLIM_MAX,
+};
+
+/*TDM default offset currently only supporting TDM_RX_0 and TDM_TX_0 */
+static unsigned int tdm_slot_offset[TDM_PORT_MAX][TDM_SLOT_OFFSET_MAX] = {
+ {0, 4, 8, 12, 16, 20, 24, 28},/* TX_0 | RX_0 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_1 | RX_1 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_2 | RX_2 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_3 | RX_3 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_4 | RX_4 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_5 | RX_5 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_6 | RX_6 */
+ {AFE_SLOT_MAPPING_OFFSET_INVALID},/* TX_7 | RX_7 */
+};
+
static struct afe_clk_set int_mi2s_clk[INT_MI2S_MAX] = {
{
AFE_API_VERSION_I2S_CONFIG,
@@ -114,6 +135,11 @@ static struct dev_config int_mi2s_cfg[] = {
[INT6_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
};
+static struct dev_config bt_fm_cfg[] = {
+ [BT_SLIM7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [FM_SLIM8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
static char const *int_mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_32", "KHZ_44P1", "KHZ_48",
"KHZ_96", "KHZ_192"};
@@ -122,6 +148,7 @@ static const char *const int_mi2s_tx_ch_text[] = {"One", "Two",
"Three", "Four"};
static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_48"};
static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_sample_rate, int_mi2s_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_chs, int_mi2s_ch_text);
@@ -137,6 +164,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_chs, int_mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_format, bit_format_text);
static SOC_ENUM_SINGLE_EXT_DECL(int5_mi2s_tx_chs, int_mi2s_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(loopback_mclk_en, loopback_mclk_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static int msm_dmic_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@@ -544,7 +572,7 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+static int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
struct snd_soc_dai_link *dai_link = rtd->dai_link;
@@ -577,6 +605,38 @@ int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
return 0;
}
+static int msm_btfm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ switch (dai_link->be_id) {
+ case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_7_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ bt_fm_cfg[BT_SLIM7].bit_format);
+ rate->min = rate->max = bt_fm_cfg[BT_SLIM7].sample_rate;
+ channels->min = channels->max =
+ bt_fm_cfg[BT_SLIM7].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_8_TX:
+ rate->min = rate->max = bt_fm_cfg[FM_SLIM8].sample_rate;
+ channels->min = channels->max =
+ bt_fm_cfg[FM_SLIM8].channels;
+ break;
+
+ default:
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return 0;
+}
+
static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -746,6 +806,55 @@ static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
return ret;
}
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ /*
+ * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
+ * when used for BT_SCO use case. Return either Rx or Tx sample rate
+ * value.
+ */
+ switch (bt_fm_cfg[BT_SLIM7].sample_rate) {
+ case SAMPLING_RATE_48KHZ:
+ ucontrol->value.integer.value[0] = 2;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ ucontrol->value.integer.value[0] = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ ucontrol->value.integer.value[0] = 0;
+ break;
+ }
+ pr_debug("%s: sample rate = %d", __func__,
+ bt_fm_cfg[BT_SLIM7].sample_rate);
+
+ return 0;
+}
+
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 0:
+ default:
+ bt_fm_cfg[BT_SLIM7].sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ }
+ pr_debug("%s: sample rates: slim7_rx = %d, value = %d\n",
+ __func__,
+ bt_fm_cfg[BT_SLIM7].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
static const struct snd_kcontrol_new msm_snd_controls[] = {
SOC_ENUM_EXT("INT0_MI2S_RX Format", int0_mi2s_rx_format,
int_mi2s_bit_format_get, int_mi2s_bit_format_put),
@@ -779,6 +888,9 @@ static const struct snd_kcontrol_new msm_snd_controls[] = {
int_mi2s_ch_get, int_mi2s_ch_put),
SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en,
loopback_mclk_get, loopback_mclk_put),
+ SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+ msm_bt_sample_rate_get,
+ msm_bt_sample_rate_put),
};
static const struct snd_kcontrol_new msm_swr_controls[] = {
@@ -1209,6 +1321,210 @@ static int msm_swr_audrx_init(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+static int msm_wcn_init(struct snd_soc_pcm_runtime *rtd)
+{
+ unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
+ unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX] = {159, 160, 161};
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+ return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+}
+
+static int msm_wcn_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ int ret;
+
+ dev_dbg(rtd->dev, "%s: %s_tx_dai_id_%d\n", __func__,
+ codec_dai->name, codec_dai->id);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret) {
+ dev_err(rtd->dev,
+ "%s: failed to get BTFM codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+ dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
+ __func__, tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
+ if (ret)
+ dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+
+exit:
+ return ret;
+}
+
+static unsigned int tdm_param_set_slot_mask(u16 port_id, int slot_width,
+ int slots)
+{
+ unsigned int slot_mask = 0;
+ int i, j;
+ unsigned int *slot_offset;
+
+ for (i = TDM_0; i < TDM_PORT_MAX; i++) {
+ slot_offset = tdm_slot_offset[i];
+
+ for (j = 0; j < TDM_SLOT_OFFSET_MAX; j++) {
+ if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID)
+ slot_mask |=
+ (1 << ((slot_offset[j] * 8) / slot_width));
+ else
+ break;
+ }
+ }
+
+ return slot_mask;
+}
+
+static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ int channels, slot_width, slots;
+ unsigned int slot_mask;
+ unsigned int *slot_offset;
+ int offset_channels = 0;
+ int i;
+
+ pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
+
+ channels = params_channels(params);
+ switch (channels) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S16_LE:
+ /*
+ * up to 8 channels HW config should
+ * use 32 bit slot width for max support of
+ * stream bit width. (slot_width > bit_width)
+ */
+ slot_width = 32;
+ break;
+ default:
+ pr_err("%s: invalid param format 0x%x\n",
+ __func__, params_format(params));
+ return -EINVAL;
+ }
+ slots = 8;
+ slot_mask = tdm_param_set_slot_mask(cpu_dai->id,
+ slot_width,
+ slots);
+ if (!slot_mask) {
+ pr_err("%s: invalid slot_mask 0x%x\n",
+ __func__, slot_mask);
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_err("%s: invalid param channels %d\n",
+ __func__, channels);
+ return -EINVAL;
+ }
+ /* currently only supporting TDM_RX_0 and TDM_TX_0 */
+ switch (cpu_dai->id) {
+ case AFE_PORT_ID_PRIMARY_TDM_RX:
+ case AFE_PORT_ID_SECONDARY_TDM_RX:
+ case AFE_PORT_ID_TERTIARY_TDM_RX:
+ case AFE_PORT_ID_QUATERNARY_TDM_RX:
+ case AFE_PORT_ID_PRIMARY_TDM_TX:
+ case AFE_PORT_ID_SECONDARY_TDM_TX:
+ case AFE_PORT_ID_TERTIARY_TDM_TX:
+ case AFE_PORT_ID_QUATERNARY_TDM_TX:
+ slot_offset = tdm_slot_offset[TDM_0];
+ break;
+ default:
+ pr_err("%s: dai id 0x%x not supported\n",
+ __func__, cpu_dai->id);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < TDM_SLOT_OFFSET_MAX; i++) {
+ if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID)
+ offset_channels++;
+ else
+ break;
+ }
+
+ if (offset_channels == 0) {
+ pr_err("%s: slot offset not supported, offset_channels %d\n",
+ __func__, offset_channels);
+ return -EINVAL;
+ }
+
+ if (channels > offset_channels) {
+ pr_err("%s: channels %d exceed offset_channels %d\n",
+ __func__, channels, offset_channels);
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
+ slots, slot_width);
+ if (ret < 0) {
+ pr_err("%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL,
+ channels, slot_offset);
+ if (ret < 0) {
+ pr_err("%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ } else {
+ ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
+ slots, slot_width);
+ if (ret < 0) {
+ pr_err("%s: failed to set tdm slot, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, channels,
+ slot_offset, 0, NULL);
+ if (ret < 0) {
+ pr_err("%s: failed to set channel map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+
+static struct snd_soc_ops msm_tdm_be_ops = {
+ .hw_params = msm_tdm_snd_hw_params
+};
+
+static struct snd_soc_ops msm_wcn_ops = {
+ .hw_params = msm_wcn_hw_params,
+};
+
static struct snd_soc_ops msm_mi2s_be_ops = {
.startup = msm_mi2s_snd_startup,
.shutdown = msm_mi2s_snd_shutdown,
@@ -2029,6 +2345,145 @@ static struct snd_soc_dai_link msm_int_dai[] = {
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
+ {
+ .name = LPASS_BE_USB_AUDIO_RX,
+ .stream_name = "USB Audio Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.28672",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_USB_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_USB_AUDIO_TX,
+ .stream_name = "USB Audio Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.28673",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_USB_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_TDM_RX_0,
+ .stream_name = "Primary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36864",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_TDM_TX_0,
+ .stream_name = "Primary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36865",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_TDM_RX_0,
+ .stream_name = "Secondary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36880",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_TDM_TX_0,
+ .stream_name = "Secondary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36881",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_TDM_RX_0,
+ .stream_name = "Tertiary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36896",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_TDM_TX_0,
+ .stream_name = "Tertiary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36897",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_TDM_RX_0,
+ .stream_name = "Quaternary TDM0 Playback",
+ .cpu_dai_name = "msm-dai-q6-tdm.36912",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_TDM_TX_0,
+ .stream_name = "Quaternary TDM0 Capture",
+ .cpu_dai_name = "msm-dai-q6-tdm.36913",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_tdm_be_ops,
+ .ignore_suspend = 1,
+ },
};
static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
@@ -2277,10 +2732,64 @@ static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
},
};
+
+static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_7_RX,
+ .stream_name = "Slimbus7 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16398",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ /* BT codec driver determines capabilities based on
+ * dai name, bt codecdai name should always contains
+ * supported usecase information
+ */
+ .codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+ .be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
+ .ops = &msm_wcn_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_7_TX,
+ .stream_name = "Slimbus7 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16399",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ .codec_dai_name = "btfm_bt_sco_slim_tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+ .be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
+ .ops = &msm_wcn_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_8_TX,
+ .stream_name = "Slimbus8 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16401",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "btfmslim_slave",
+ .codec_dai_name = "btfm_fm_slim_tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+ .be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
+ .init = &msm_wcn_init,
+ .ops = &msm_wcn_ops,
+ .ignore_suspend = 1,
+ },
+};
+
static struct snd_soc_dai_link msm_int_dai_links[
ARRAY_SIZE(msm_int_dai) +
ARRAY_SIZE(msm_mi2s_be_dai_links) +
-ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+ARRAY_SIZE(msm_auxpcm_be_dai_links)+
+ARRAY_SIZE(msm_wcn_be_dai_links)];
static struct snd_soc_card msmfalcon_card = {
/* snd_soc_card_msmfalcon */
@@ -2357,6 +2866,14 @@ static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
sizeof(msm_auxpcm_be_dai_links));
len1 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
}
+ if (of_property_read_bool(dev->of_node, "qcom,wcn-btfm")) {
+ dev_dbg(dev, "%s(): WCN BTFM support present\n",
+ __func__);
+ memcpy(dailink + len1,
+ msm_wcn_be_dai_links,
+ sizeof(msm_wcn_be_dai_links));
+ len1 += ARRAY_SIZE(msm_wcn_be_dai_links);
+ }
card->dai_link = dailink;
card->num_links = len1;
return card;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 9681330be33b..9164475386ff 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -280,11 +280,19 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
{ 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_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_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},
@@ -310,12 +318,9 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
LPASS_BE_SEC_AUXPCM_RX},
{ AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
LPASS_BE_SEC_AUXPCM_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},
{ 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},
- { SLIMBUS_5_RX, 0, 0, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_5_RX},
{ 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,
@@ -451,10 +456,6 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
{ 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},
- { 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},
{ 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},
@@ -2257,6 +2258,11 @@ static const struct snd_kcontrol_new ext_ec_ref_mux_ul2 =
msm_route_ec_ref_rx_enum[0],
msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+static const struct snd_kcontrol_new ext_ec_ref_mux_ul3 =
+ SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL3 MUX Mux",
+ msm_route_ec_ref_rx_enum[0],
+ msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put);
+
static const struct snd_kcontrol_new ext_ec_ref_mux_ul4 =
SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL4 MUX Mux",
msm_route_ec_ref_rx_enum[0],
@@ -2834,9 +2840,15 @@ static const struct snd_kcontrol_new tertiary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -2917,15 +2929,6 @@ static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = {
msm_routing_put_audio_mixer),
};
-static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = {
- SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
- MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
- msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
- MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
- msm_routing_put_port_mixer),
-};
-
static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_MI2S_RX ,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -4536,10 +4539,10 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
@@ -4908,10 +4911,10 @@ static const struct snd_kcontrol_new mmul6_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ 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("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0,
@@ -5091,6 +5094,12 @@ static const struct snd_kcontrol_new sec_mi2s_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
@@ -5223,6 +5232,9 @@ static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("Voice2 Stub", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -6159,10 +6171,10 @@ static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
@@ -6198,10 +6210,10 @@ static const struct snd_kcontrol_new tx_voice2_stub_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOICE2_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
@@ -6243,10 +6255,10 @@ static const struct snd_kcontrol_new tx_volte_stub_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
MSM_FRONTEND_DAI_VOLTE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
@@ -6342,10 +6354,10 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_TERT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_QUAT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
@@ -6354,6 +6366,9 @@ static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
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_SLIMBUS_0_RX,
+ MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
@@ -6405,7 +6420,7 @@ static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
};
static const struct snd_kcontrol_new tert_auxpcm_rx_port_mixer_controls[] = {
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_RX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_TERT_AUXPCM_RX,
MSM_BACKEND_DAI_TERT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_TERT_AUXPCM_RX,
@@ -6417,7 +6432,7 @@ static const struct snd_kcontrol_new tert_auxpcm_rx_port_mixer_controls[] = {
};
static const struct snd_kcontrol_new quat_auxpcm_rx_port_mixer_controls[] = {
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
MSM_BACKEND_DAI_QUAT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
@@ -6441,10 +6456,10 @@ static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("TERT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ SOC_SINGLE_EXT("TERT_AUXPCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_TERT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("QUAT_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ SOC_SINGLE_EXT("QUAT_AUXPCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_QUAT_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
};
@@ -7161,17 +7176,20 @@ static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
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_SECONDARY_MI2S_RX,
+ MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
- MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
- msm_routing_put_port_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
- SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
- MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
};
@@ -7313,7 +7331,7 @@ static const struct soc_enum aanc_slim_0_rx_enum =
aanc_slim_0_rx_text);
static const struct snd_kcontrol_new aanc_slim_0_rx_mux[] = {
- SOC_DAPM_ENUM_EXT("AANC_SLIM_0_RX MUX", aanc_slim_0_rx_enum,
+ SOC_ENUM_EXT("AANC_SLIM_0_RX MUX", aanc_slim_0_rx_enum,
msm_routing_slim_0_rx_aanc_mux_get,
msm_routing_slim_0_rx_aanc_mux_put)
};
@@ -8115,10 +8133,14 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIM4_UL_HL", "SLIMBUS4_HOSTLESS Capture",
0, 0, 0, 0),
- SND_SOC_DAPM_AIF_OUT("SLIM8_UL_HL", "SLIMBUS8_HOSTLESS Capture",
- 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIM6_DL_HL", "SLIMBUS6_HOSTLESS Playback",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SLIM6_UL_HL", "SLIMBUS6_HOSTLESS Capture",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIM8_DL_HL", "SLIMBUS8_HOSTLESS Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SLIM8_UL_HL", "SLIMBUS8_HOSTLESS Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
@@ -8430,8 +8452,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("QUIN_MI2S_TX", "Quinary MI2S Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SENARY_MI2S_TX", "Senary MI2S Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
0, 0, 0 , 0),
SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
@@ -8669,8 +8694,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
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),
- SND_SOC_DAPM_MUX("SLIM_0_RX AANC MUX", SND_SOC_NOPM, 0, 0,
- aanc_slim_0_rx_mux),
/* Mixer definitions */
SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -8705,9 +8728,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_MIXER("SEC_MI2S_RX_SD1 Audio Mixer", SND_SOC_NOPM, 0, 0,
secondary_mi2s_rx2_mixer_controls,
ARRAY_SIZE(secondary_mi2s_rx2_mixer_controls)),
- SND_SOC_DAPM_MIXER("SEC_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0,
- mi2s_hl_mixer_controls,
- ARRAY_SIZE(mi2s_hl_mixer_controls)),
SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
primary_mi2s_rx_mixer_controls,
ARRAY_SIZE(primary_mi2s_rx_mixer_controls)),
@@ -9028,6 +9048,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
&ext_ec_ref_mux_ul1),
SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL2 MUX", SND_SOC_NOPM, 0, 0,
&ext_ec_ref_mux_ul2),
+ SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL3 MUX", SND_SOC_NOPM, 0, 0,
+ &ext_ec_ref_mux_ul3),
SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL4 MUX", SND_SOC_NOPM, 0, 0,
&ext_ec_ref_mux_ul4),
SND_SOC_DAPM_MUX("AUDIO_REF_EC_UL5 MUX", SND_SOC_NOPM, 0, 0,
@@ -9691,10 +9713,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"MultiMedia3 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
{"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
- {"MultiMedia1 Mixer", "TERT_AUX_PCM_UL_TX", "TERT_AUX_PCM_TX"},
+ {"MultiMedia1 Mixer", "TERT_AUXPCM_UL_TX", "TERT_AUX_PCM_TX"},
{"MultiMedia3 Mixer", "TERT_AUX_PCM_TX", "TERT_AUX_PCM_TX"},
{"MultiMedia5 Mixer", "TERT_AUX_PCM_TX", "TERT_AUX_PCM_TX"},
- {"MultiMedia1 Mixer", "QUAT_AUX_PCM_UL_TX", "QUAT_AUX_PCM_TX"},
+ {"MultiMedia1 Mixer", "QUAT_AUXPCM_UL_TX", "QUAT_AUX_PCM_TX"},
{"MultiMedia3 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
{"MultiMedia5 Mixer", "QUAT_AUX_PCM_TX", "QUAT_AUX_PCM_TX"},
{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
@@ -10048,6 +10070,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"INTERNAL_BT_SCO_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
{"INTERNAL_BT_SCO_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+ {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
{"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
@@ -10230,6 +10254,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{"AUDIO_REF_EC_UL2 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
{"AUDIO_REF_EC_UL2 MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL3 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
+ {"AUDIO_REF_EC_UL3 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
+ {"AUDIO_REF_EC_UL3 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL3 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+
{"AUDIO_REF_EC_UL4 MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"},
{"AUDIO_REF_EC_UL4 MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"},
{"AUDIO_REF_EC_UL4 MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
@@ -10482,11 +10511,11 @@ static const struct snd_soc_dapm_route intercon[] = {
{"INT_FM_RX", NULL, "INTFM_DL_HL"},
{"INTFM_UL_HL", NULL, "INT_FM_TX"},
- {"INTHFP_UL_HL", "NULL", "HFP_PRI_AUX_UL_HL"},
+ {"INTHFP_UL_HL", NULL, "HFP_PRI_AUX_UL_HL"},
{"HFP_PRI_AUX_UL_HL", "Switch", "AUX_PCM_TX"},
- {"INTHFP_UL_HL", "NULL", "HFP_AUX_UL_HL"},
+ {"INTHFP_UL_HL", NULL, "HFP_AUX_UL_HL"},
{"HFP_AUX_UL_HL", "Switch", "SEC_AUX_PCM_TX"},
- {"INTHFP_UL_HL", "NULL", "HFP_INT_UL_HL"},
+ {"INTHFP_UL_HL", NULL, "HFP_INT_UL_HL"},
{"HFP_INT_UL_HL", "Switch", "INT_BT_SCO_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_DL_HL"},
{"AUXPCM_UL_HL", NULL, "AUX_PCM_TX"},
@@ -10688,8 +10717,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SLIMBUS_0_RX Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"SLIMBUS_0_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
- {"SLIMBUS_0_RX Port Mixer", "TERT_AUX_PCM_UL_TX", "TERT_AUX_PCM_TX"},
- {"SLIMBUS_0_RX Port Mixer", "QUAT_AUX_PCM_UL_TX", "QUAT_AUX_PCM_TX"},
+ {"SLIMBUS_0_RX Port Mixer", "TERT_AUXPCM_UL_TX", "TERT_AUX_PCM_TX"},
+ {"SLIMBUS_0_RX Port Mixer", "QUAT_AUXPCM_UL_TX", "QUAT_AUX_PCM_TX"},
{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
{"SLIMBUS_0_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"SLIMBUS_0_RX Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -10713,12 +10742,12 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
{"TERT_AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
- {"TERT_AUXPCM_RX Port Mixer", "TERT_AUX_PCM_UL_TX", "TERT_AUX_PCM_TX"},
+ {"TERT_AUXPCM_RX Port Mixer", "TERT_AUXPCM_UL_TX", "TERT_AUX_PCM_TX"},
{"TERT_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"TERT_AUX_PCM_RX", NULL, "TERT_AUXPCM_RX Port Mixer"},
{"QUAT_AUXPCM_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
- {"QUAT_AUXPCM_RX Port Mixer", "QUAT_AUX_PCM_UL_TX", "QUAT_AUX_PCM_TX"},
+ {"QUAT_AUXPCM_RX Port Mixer", "QUAT_AUXPCM_UL_TX", "QUAT_AUX_PCM_TX"},
{"QUAT_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"QUAT_AUX_PCM_RX", NULL, "QUAT_AUXPCM_RX Port Mixer"},
@@ -10728,8 +10757,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Voice Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
{"Voice Stub Tx Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"Voice Stub Tx Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
- {"Voice Stub Tx Mixer", "TERT_AUX_PCM_UL_TX", "TERT_AUX_PCM_TX"},
- {"Voice Stub Tx Mixer", "QUAT_AUX_PCM_UL_TX", "QUAT_AUX_PCM_TX"},
+ {"Voice Stub Tx Mixer", "TERT_AUXPCM_UL_TX", "TERT_AUX_PCM_TX"},
+ {"Voice Stub Tx Mixer", "QUAT_AUXPCM_UL_TX", "QUAT_AUX_PCM_TX"},
{"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
{"Voice Stub Tx Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"Voice Stub Tx Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
@@ -10776,8 +10805,6 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SLIMBUS_1_RX Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"SLIMBUS_1_RX Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Mixer"},
- {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
- {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"AFE_PCM_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"},
{"AFE_PCM_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"},
@@ -10869,6 +10896,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SEC_MI2S_RX Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"SEC_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
{"SEC_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"SEC_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Port Mixer"},
{"TERT_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -11404,9 +11432,8 @@ static int msm_routing_probe(struct snd_soc_platform *platform)
snd_soc_add_platform_controls(platform, lsm_function,
ARRAY_SIZE(lsm_function));
- snd_soc_add_platform_controls(platform,
- aanc_slim_0_rx_mux,
- ARRAY_SIZE(aanc_slim_0_rx_mux));
+ snd_soc_add_platform_controls(platform, aanc_slim_0_rx_mux,
+ ARRAY_SIZE(aanc_slim_0_rx_mux));
snd_soc_add_platform_controls(platform, msm_voc_session_controls,
ARRAY_SIZE(msm_voc_session_controls));
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 8a62e900ff28..4fdfd6bb936d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -59,14 +59,15 @@
#define LPASS_BE_SLIMBUS_1_TX "SLIMBUS_1_TX"
#define LPASS_BE_STUB_1_TX "STUB_1_TX"
#define LPASS_BE_SLIMBUS_2_RX "SLIMBUS_2_RX"
+#define LPASS_BE_SLIMBUS_2_TX "SLIMBUS_2_TX"
#define LPASS_BE_SLIMBUS_3_RX "SLIMBUS_3_RX"
#define LPASS_BE_SLIMBUS_3_TX "SLIMBUS_3_TX"
#define LPASS_BE_SLIMBUS_4_RX "SLIMBUS_4_RX"
#define LPASS_BE_SLIMBUS_4_TX "SLIMBUS_4_TX"
+#define LPASS_BE_SLIMBUS_5_RX "SLIMBUS_5_RX"
#define LPASS_BE_SLIMBUS_5_TX "SLIMBUS_5_TX"
#define LPASS_BE_SLIMBUS_6_RX "SLIMBUS_6_RX"
#define LPASS_BE_SLIMBUS_6_TX "SLIMBUS_6_TX"
-#define LPASS_BE_SLIMBUS_5_RX "SLIMBUS_5_RX"
#define LPASS_BE_QUIN_MI2S_RX "QUIN_MI2S_RX"
#define LPASS_BE_QUIN_MI2S_TX "QUIN_MI2S_TX"
#define LPASS_BE_SENARY_MI2S_TX "SENARY_MI2S_TX"
@@ -233,11 +234,19 @@ enum {
MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_SLIMBUS_1_TX,
MSM_BACKEND_DAI_SLIMBUS_2_RX,
- MSM_BACKEND_DAI_SLIMBUS_4_RX,
- MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ MSM_BACKEND_DAI_SLIMBUS_2_TX,
MSM_BACKEND_DAI_SLIMBUS_3_RX,
MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ MSM_BACKEND_DAI_SLIMBUS_5_RX,
MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ MSM_BACKEND_DAI_SLIMBUS_6_RX,
+ MSM_BACKEND_DAI_SLIMBUS_6_TX,
+ MSM_BACKEND_DAI_SLIMBUS_7_RX,
+ MSM_BACKEND_DAI_SLIMBUS_7_TX,
+ MSM_BACKEND_DAI_SLIMBUS_8_RX,
+ MSM_BACKEND_DAI_SLIMBUS_8_TX,
MSM_BACKEND_DAI_EXTPROC_RX,
MSM_BACKEND_DAI_EXTPROC_TX,
MSM_BACKEND_DAI_EXTPROC_EC_TX,
@@ -252,11 +261,8 @@ enum {
MSM_BACKEND_DAI_AUDIO_I2S_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_RX,
MSM_BACKEND_DAI_SEC_AUXPCM_TX,
- MSM_BACKEND_DAI_SLIMBUS_6_RX,
- MSM_BACKEND_DAI_SLIMBUS_6_TX,
MSM_BACKEND_DAI_SPDIF_RX,
MSM_BACKEND_DAI_SECONDARY_MI2S_RX_SD1,
- MSM_BACKEND_DAI_SLIMBUS_5_RX,
MSM_BACKEND_DAI_QUINARY_MI2S_RX,
MSM_BACKEND_DAI_QUINARY_MI2S_TX,
MSM_BACKEND_DAI_SENARY_MI2S_TX,
@@ -325,10 +331,6 @@ enum {
MSM_BACKEND_DAI_QUAT_TDM_RX_7,
MSM_BACKEND_DAI_QUAT_TDM_TX_7,
MSM_BACKEND_DAI_INT_BT_A2DP_RX,
- MSM_BACKEND_DAI_SLIMBUS_7_RX,
- MSM_BACKEND_DAI_SLIMBUS_7_TX,
- MSM_BACKEND_DAI_SLIMBUS_8_RX,
- MSM_BACKEND_DAI_SLIMBUS_8_TX,
MSM_BACKEND_DAI_USB_RX,
MSM_BACKEND_DAI_USB_TX,
MSM_BACKEND_DAI_DISPLAY_PORT_RX,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 22e14f431bb3..e3545405f61d 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -421,12 +421,12 @@ static void config_debug_fs_write(struct audio_buffer *ab)
}
static void config_debug_fs_init(void)
{
- out_buffer = kmalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
+ out_buffer = kzalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
if (out_buffer == NULL) {
pr_err("%s: kmalloc() for out_buffer failed\n", __func__);
goto outbuf_fail;
}
- in_buffer = kmalloc(IN_BUFFER_SIZE, GFP_KERNEL);
+ in_buffer = kzalloc(IN_BUFFER_SIZE, GFP_KERNEL);
if (in_buffer == NULL) {
pr_err("%s: kmalloc() for in_buffer failed\n", __func__);
goto inbuf_fail;