diff options
51 files changed, 823 insertions, 196 deletions
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt index 4b70e670798d..c801e8486f87 100644 --- a/Documentation/devicetree/bindings/cnss/icnss.txt +++ b/Documentation/devicetree/bindings/cnss/icnss.txt @@ -17,14 +17,14 @@ Required properties: - iommus: SMMUs and corresponding Stream IDs needed by WLAN - qcom,wlan-smmu-iova-address: I/O virtual address range as <start length> format to be used for allocations associated between WLAN and SMMU - - <supply-name>-supply: phandle to the regulator device tree node - Required "supply-name" is "vdd-0.8-cx-mx". - - qcom,<supply>-config: Specifies voltage levels for supply. Should be - specified in pairs (min, max), units uV. There can - be optional load in uA and Regulator settle delay in - uS. Optional properties: + - <supply-name>-supply: phandle to the regulator device tree node + optional "supply-name" is "vdd-0.8-cx-mx". + - qcom,<supply>-config: Specifies voltage levels for supply. Should be + specified in pairs (min, max), units uV. There can + be optional load in uA and Regulator settle delay in + uS. - qcom,icnss-vadc: VADC handle for vph_pwr read APIs. - qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs. - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi index 067f2c35eecd..97a134b46713 100644 --- a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -187,11 +187,6 @@ qcom,msm-dai-q6-dev-id = <16393>; }; - sb_4_tx_vi: qcom,msm-dai-q6-sb-4-tx-vi { - compatible = "qcom,msm-dai-q6-dev"; - qcom,msm-dai-q6-dev-id = <20233>; - }; - sb_5_tx: qcom,msm-dai-q6-sb-5-tx { compatible = "qcom,msm-dai-q6-dev"; qcom,msm-dai-q6-dev-id = <16395>; diff --git a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi index ac1e37fa1d63..c4e6393997ec 100644 --- a/arch/arm/boot/dts/qcom/msm8998-audio.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-audio.dtsi @@ -105,8 +105,7 @@ <&dai_tert_auxpcm>, <&dai_quat_auxpcm>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, - <&sb_4_rx>, <&sb_4_tx>, <&sb_4_tx_vi>, - <&sb_5_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>, <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, @@ -127,7 +126,6 @@ "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", - "msm-dai-q6-dev.20233", "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", @@ -164,7 +162,7 @@ }; }; - sound-tavil { + snd_934x: sound-tavil { compatible = "qcom,msm8998-asoc-snd-tavil"; qcom,model = "msm8998-tavil-snd-card"; qcom,ext-disp-audio-rx; @@ -239,8 +237,7 @@ <&dai_tert_auxpcm>, <&dai_quat_auxpcm>, <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>, <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>, - <&sb_4_rx>, <&sb_4_tx>, <&sb_4_tx_vi>, - <&sb_5_tx>, + <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>, <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>, <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, @@ -261,7 +258,6 @@ "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389", "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391", "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393", - "msm-dai-q6-dev.20233", "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224", "msm-dai-q6-dev.225", "msm-dai-q6-dev.241", "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", diff --git a/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi index 48415eb81406..2b925250c5c0 100644 --- a/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998-cdp.dtsi @@ -516,6 +516,10 @@ qcom,mbhc-audio-jack-type = "6-pole-jack"; }; +&snd_934x { + qcom,mbhc-audio-jack-type = "6-pole-jack"; +}; + &soc { gpio_keys { compatible = "gpio-keys"; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index cd895a067f65..ce088c372eea 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -322,6 +322,18 @@ reg = <0x0 0x92a00000 0x0 0x1e00000>; }; + pil_mba_mem: pil_mba_region@94800000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x94800000 0x0 0x200000>; + }; + + buffer_mem: buffer_region@94a00000 { + compatible = "removed-dma-pool"; + no-map; + reg = <0x0 0x94a00000 0x0 0x100000>; + }; + venus_fw_mem: venus_fw_region { compatible = "shared-dma-pool"; alloc-ranges = <0x0 0x80000000 0x0 0x20000000>; @@ -335,7 +347,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0xa00000>; + size = <0x0 0x800000>; }; qseecom_mem: qseecom_region { @@ -1742,6 +1754,10 @@ /* GPIO output to mss */ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>; status = "ok"; + qcom,mba-mem@0 { + compatible = "qcom,pil-mba-mem"; + memory-region = <&pil_mba_mem>; + }; }; qcom,msm-rtb { @@ -2216,4 +2232,9 @@ debounce-interval = <15>; }; }; + + devfreq_spdm_cpu { + qcom,bw-dwnstep = <6750>; + qcom,max-vote = <6750>; + }; }; diff --git a/arch/arm/boot/dts/qcom/sdm658.dtsi b/arch/arm/boot/dts/qcom/sdm658.dtsi index 3eca3dc30e50..3387482dbc18 100644 --- a/arch/arm/boot/dts/qcom/sdm658.dtsi +++ b/arch/arm/boot/dts/qcom/sdm658.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -16,4 +16,67 @@ model = "Qualcomm Technologies, Inc. SDM 658"; compatible = "qcom,sdm658"; qcom,msm-id = <325 0x0>; + + cpus { + /delete-node/ cpu@102; + /delete-node/ cpu@103; + + cpu-map { + cluster1 { + /delete-node/ core2; + /delete-node/ core3; + }; + }; + }; +}; + +&soc { + /delete-node/ jtagmm@7e40000; + /delete-node/ jtagmm@7f40000; + /delete-node/ etm@7e40000; + /delete-node/ etm@7f40000; + /delete-node/ cti@7e20000; + /delete-node/ cti@7f20000; + + devfreq_memlat_4: qcom,arm-memlat-mon-4 { + qcom,cpulist = <&CPU4 &CPU5>; + }; + + cpuss_dump { + /delete-node/ qcom,l1_i_cache102; + /delete-node/ qcom,l1_i_cache103; + /delete-node/ qcom,l1_d_cache102; + /delete-node/ qcom,l1_d_cache103; + /delete-node/ qcom,l1_tlb_dump102; + /delete-node/ qcom,l1_tlb_dump103; + }; + + funnel@7b60000 { + ports { + /delete-node/ port@7; + /delete-node/ port@8; + }; + }; + + qcom,msm-thermal { + qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>, + <1 2 &CPU4 &CPU5>; + }; + + qcom,bcl { + qcom,bcl-hotplug-list = <&CPU4 &CPU5>; + qcom,bcl-soc-hotplug-list = <&CPU4 &CPU5>; + }; + + qcom,spm@178120000 { + qcom,cpu-vctl-list = <&CPU4 &CPU5>; + }; + + qcom,lpm-levels { + qcom,pm-cluster@0 { + qcom,pm-cluster@1 { + qcom,cpu = <&CPU4 &CPU5>; + }; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi index 68ff96829d4f..0524935b9a30 100644 --- a/arch/arm/boot/dts/qcom/sdm660-bus.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-bus.dtsi @@ -1248,4 +1248,46 @@ qcom,slv-rpm-id = <ICBID_SLAVE_SERVICE_SNOC>; }; }; + + devfreq_spdm_cpu { + compatible = "qcom,devfreq_spdm"; + qcom,msm-bus,name = "devfreq_spdm"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <1 512 0 0>, + <1 512 0 0>; + qcom,msm-bus,active-only; + qcom,spdm-client = <0>; + + qcom,bw-upstep = <450>; + qcom,bw-dwnstep = <8200>; + qcom,max-vote = <8200>; + qcom,up-step-multp = <2>; + qcom,spdm-interval = <30>; + + qcom,ports = <24>; + qcom,alpha-up = <8>; + qcom,alpha-down = <15>; + qcom,bucket-size = <8>; + + /*max pl1 freq, max pl2 freq*/ + qcom,pl-freqs = <210000 610000>; + + /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */ + qcom,reject-rate = <5000 5000 5000 5000 5000 5000>; + /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */ + qcom,response-time-us = <5000 5000 5000 5000 5000 5000>; + + /* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */ + qcom,cci-response-time-us = <10000 10000 10000 + 10000 10000 10000>; + qcom,max-cci-freq = <1036800>; + }; + + devfreq_spdm_gov { + compatible = "qcom,gov_spdm_hyp"; + interrupt-names = "spdm-irq"; + interrupts = <0 192 IRQ_TYPE_EDGE_RISING>; + }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi index dce86a7ceec3..51903c8b028d 100644 --- a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi @@ -942,30 +942,6 @@ clock-names = "core_clk", "core_a_clk"; }; - cti_lpass0: cti@7060000 { - compatible = "arm,coresight-cti"; - reg = <0x7060000 0x1000>; - reg-names = "cti-base"; - - coresight-name = "coresight-cti-lpass0"; - - clocks = <&clock_rpmcc RPM_QDSS_CLK>, - <&clock_rpmcc RPM_QDSS_A_CLK>; - clock-names = "core_clk", "core_a_clk"; - }; - - cti_lpass1: cti@7061000 { - compatible = "arm,coresight-cti"; - reg = <0x7061000 0x1000>; - reg-names = "cti-base"; - - coresight-name = "coresight-cti-lpass1"; - - clocks = <&clock_rpmcc RPM_QDSS_CLK>, - <&clock_rpmcc RPM_QDSS_A_CLK>; - clock-names = "core_clk", "core_a_clk"; - }; - cti_turing: cti@7068000 { compatible = "arm,coresight-cti"; reg = <0x7068000 0x1000>; diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi index 57565134788c..37a88ea0dcec 100644 --- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi @@ -52,12 +52,12 @@ trigout_a: trigout_a { mux { pins = "gpio49"; - function = "qdss_cti_trig_out_a"; + function = "qdss_cti0_a"; }; config { pins = "gpio49"; - drive-strength = <2>; + drive-strength = <16>; bias-disable; output-low; }; diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi index 5e2793c3b05b..77e8505408d0 100644 --- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi @@ -52,6 +52,13 @@ status = "ok"; }; +&sdc2_cd_on { + config { + /delete-property/ bias-pull-up; + bias-disable; + }; +}; + &sdhc_2 { /* device core power supply */ vdd-supply = <&pm660l_l5>; @@ -249,6 +256,9 @@ }; }; +/delete-node/ &tasha_hph_en0; +/delete-node/ &tasha_hph_en1; + &tasha_snd { qcom,model = "sdm660-tasha-skus-snd-card"; qcom,audio-routing = diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi index 47db57b3dc0a..462a76ef8bfe 100644 --- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi @@ -695,8 +695,8 @@ qcom,cpr-corner-fmax-map = <2 3 4 5 8>; qcom,cpr-voltage-ceiling = - <724000 724000 724000 788000 868000 - 924000 988000 1068000>; + < 724000 724000 724000 788000 868000 + 1068000 1068000 1068000>; qcom,cpr-voltage-floor = <588000 588000 596000 652000 712000 @@ -729,13 +729,14 @@ 4370 4780>; qcom,cpr-open-loop-voltage-fuse-adjustment = - <13000 31000 27000 37000 21000>; + < (-4000) 4000 7000 19000 (-8000)>; qcom,cpr-closed-loop-voltage-fuse-adjustment = - <0 0 0 0 8000>; + <(-32000) (-30000) (-29000) (-23000) + (-21000)>; qcom,cpr-floor-to-ceiling-max-range = - <32000 32000 32000 40000 40000 + <32000 32000 32000 40000 44000 40000 40000 40000>; }; }; @@ -801,7 +802,7 @@ qcom,cpr-voltage-ceiling = <724000 724000 788000 868000 - 924000 988000 1068000>; + 988000 988000 1068000>; qcom,cpr-voltage-floor = <588000 596000 652000 712000 @@ -840,14 +841,15 @@ 2620 2280>; qcom,cpr-open-loop-voltage-fuse-adjustment = - <31000 39000 53000 40000 29000>; + <16000 27000 39000 39000 20000>; qcom,cpr-closed-loop-voltage-fuse-adjustment = - <0 3000 19000 23000 28000>; + <(-22000) (-9000) (-7000) (-2000) + 11000>; qcom,cpr-floor-to-ceiling-max-range = <40000 40000 40000 40000 - 40000 40000 40000>; + 66000 66000 40000>; }; }; }; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index c14449289594..1767e811a826 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -345,7 +345,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0xa00000>; + size = <0x0 0x800000>; }; qseecom_mem: qseecom_region { @@ -2050,6 +2050,11 @@ reg = <0x6b0 32>; }; + kaslr_offset@6d0 { + compatible = "qcom,msm-imem-kaslr_offset"; + reg = <0x6d0 12>; + }; + pil@94c { compatible = "qcom,msm-imem-pil"; reg = <0x94c 200>; diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig index b0bdabf58d62..740584b30c60 100644 --- a/arch/arm64/configs/sdm660-perf_defconfig +++ b/arch/arm64/configs/sdm660-perf_defconfig @@ -67,6 +67,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index 7b21409c3266..f6c53a1e1ace 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -67,6 +67,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_RANDOMIZE_BASE=y CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_COMPAT=y diff --git a/drivers/clk/qcom/mmcc-sdm660.c b/drivers/clk/qcom/mmcc-sdm660.c index 87e6f8c6be0a..0bf7ef05ed06 100644 --- a/drivers/clk/qcom/mmcc-sdm660.c +++ b/drivers/clk/qcom/mmcc-sdm660.c @@ -1041,7 +1041,7 @@ static const struct freq_tbl ftbl_mclk0_clk_src[] = { F(9600000, P_CXO, 2, 0, 0), F(16666667, P_GPLL0_OUT_MAIN_DIV, 2, 1, 9), F(19200000, P_CXO, 1, 0, 0), - F(24000000, P_GPLL0_OUT_MAIN_DIV, 1, 2, 25), + F(24000000, P_MMPLL10_PLL_OUT_MAIN, 1, 1, 24), F(33333333, P_GPLL0_OUT_MAIN_DIV, 1, 1, 9), F(48000000, P_GPLL0_OUT_MAIN, 1, 2, 25), F(66666667, P_GPLL0_OUT_MAIN, 1, 1, 9), diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 900d37ca0d7c..5dc26d29e4a4 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -687,6 +687,7 @@ static void __init arch_timer_common_init(void) arch_timer_banner(arch_timers_present); arch_counter_register(arch_timers_present); arch_timer_arch_init(); + clocksource_select_force(); } static void __init arch_timer_init(void) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index d8e571981c35..64c4bf8f58a8 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -1542,11 +1542,14 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, struct cpuidle_driver *drv, int idx) { struct lpm_cluster *cluster = per_cpu(cpu_cluster, dev->cpu); - bool success = true; + bool success = false; const struct cpumask *cpumask = get_cpu_mask(dev->cpu); int64_t start_time = ktime_to_ns(ktime_get()), end_time; struct power_params *pwr_params; + if (idx < 0) + return -EINVAL; + pwr_params = &cluster->cpu->levels[idx].pwr; sched_set_cpu_cstate(smp_processor_id(), idx + 1, pwr_params->energy_overhead, pwr_params->latency_us); @@ -1559,7 +1562,7 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, trace_cpu_idle_enter(idx); lpm_stats_cpu_enter(idx, start_time); - if (need_resched() || (idx < 0)) + if (need_resched()) goto exit; BUG_ON(!use_psci); diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c index dc7827872276..23ffa9b554dd 100644 --- a/drivers/gpu/drm/msm/sde/sde_formats.c +++ b/drivers/gpu/drm/msm/sde/sde_formats.c @@ -384,19 +384,19 @@ static const struct sde_format sde_format_map[] = { * the data will be passed by user-space. */ static const struct sde_format sde_format_map_ubwc[] = { - INTERLEAVED_RGB_FMT(BGR565, + INTERLEAVED_RGB_FMT(RGB565, 0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT, C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3, false, 2, 0, SDE_FETCH_UBWC, 2), - INTERLEAVED_RGB_FMT(ABGR8888, + INTERLEAVED_RGB_FMT(RGBA8888, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, true, 4, 0, SDE_FETCH_UBWC, 2), - INTERLEAVED_RGB_FMT(XBGR8888, + INTERLEAVED_RGB_FMT(RGBX8888, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4, false, 4, 0, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index aca8e99650ba..e54342e3935a 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -795,6 +795,7 @@ struct vfe_device { struct msm_vfe_error_info error_info; struct msm_vfe_fetch_engine_info fetch_engine_info; enum msm_vfe_hvx_streaming_cmd hvx_cmd; + uint8_t cur_hvx_state; /* State variables */ uint32_t vfe_hw_version; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 57373c1fc74c..d829aefe6c98 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -1495,6 +1495,10 @@ void msm_vfe47_configure_hvx(struct vfe_device *vfe_dev, uint32_t val; int rc = 0; + if (is_stream_on == vfe_dev->cur_hvx_state) { + ISP_DBG("already in same hvx state\n"); + return; + } if (vfe_dev->buf_mgr->secure_enable == SECURE_MODE) { pr_err("%s: Cannot configure hvx, secure_mode: %d\n", __func__, @@ -1528,6 +1532,7 @@ void msm_vfe47_configure_hvx(struct vfe_device *vfe_dev, val &= 0xFFFFFFF7; msm_camera_io_w_mb(val, vfe_dev->vfe_base + 0x50); } + vfe_dev->cur_hvx_state = is_stream_on; } void msm_vfe47_update_camif_state(struct vfe_device *vfe_dev, diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 1ddf51407884..4e74851dc67d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -39,13 +39,13 @@ static int msm_isp_axi_create_stream(struct vfe_device *vfe_dev, struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd, struct msm_vfe_axi_stream *stream_info) { - uint32_t i; + uint32_t i = 0; int rc = 0; if (stream_info->state != AVAILABLE) { - pr_err("%s:%d invalid state %d expected %d for src %d\n", + pr_err("%s:%d invalid state %d expected %d\n", __func__, __LINE__, stream_info->state, - AVAILABLE, i); + AVAILABLE); return -EINVAL; } diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index df9691be0c28..86b500973538 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -26,6 +26,7 @@ #define MAX_ISP_V4l2_EVENTS 100 +#define MAX_ISP_REG_LIST 100 static DEFINE_MUTEX(bandwidth_mgr_mutex); static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr; @@ -630,6 +631,13 @@ static int msm_isp_set_dual_HW_master_slave_mode( } ISP_DBG("%s: vfe %d num_src %d\n", __func__, vfe_dev->pdev->id, dual_hw_ms_cmd->num_src); + if (dual_hw_ms_cmd->num_src > VFE_SRC_MAX) { + pr_err("%s: Error! Invalid num_src %d\n", __func__, + dual_hw_ms_cmd->num_src); + spin_unlock_irqrestore(&vfe_dev->common_data-> + common_dev_data_lock, flags); + return -EINVAL; + } /* This for loop is for non-primary intf to be marked with Master/Slave * in order for frame id sync. But their timestamp is not saved. * So no sof_info resource is allocated */ @@ -662,6 +670,7 @@ static int msm_isp_set_dual_HW_master_slave_mode( static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) { int rc = 0; + uint32_t count = 0; struct msm_vfe_cfg_cmd_list *proc_cmd = (struct msm_vfe_cfg_cmd_list *)arg; struct msm_vfe_cfg_cmd_list cmd, cmd_next; @@ -685,6 +694,12 @@ static int msm_isp_proc_cmd_list_unlocked(struct vfe_device *vfe_dev, void *arg) sizeof(struct msm_vfe_cfg_cmd_list)); break; } + if (++count >= MAX_ISP_REG_LIST) { + pr_err("%s:%d Error exceeding the max register count:%u\n", + __func__, __LINE__, count); + rc = -EINVAL; + break; + } if (copy_from_user(&cmd_next, (void __user *)cmd.next, sizeof(struct msm_vfe_cfg_cmd_list))) { rc = -EFAULT; @@ -731,6 +746,7 @@ static void msm_isp_compat_to_proc_cmd(struct msm_vfe_cfg_cmd2 *proc_cmd, static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) { int rc = 0; + uint32_t count = 0; struct msm_vfe_cfg_cmd_list_32 *proc_cmd = (struct msm_vfe_cfg_cmd_list_32 *)arg; struct msm_vfe_cfg_cmd_list_32 cmd, cmd_next; @@ -755,6 +771,12 @@ static int msm_isp_proc_cmd_list_compat(struct vfe_device *vfe_dev, void *arg) sizeof(struct msm_vfe_cfg_cmd_list)); break; } + if (++count >= MAX_ISP_REG_LIST) { + pr_err("%s:%d Error exceeding the max register count:%u\n", + __func__, __LINE__, count); + rc = -EINVAL; + break; + } if (copy_from_user(&cmd_next, compat_ptr(cmd.next), sizeof(struct msm_vfe_cfg_cmd_list_32))) { rc = -EFAULT; diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 12d5d7eeb368..48872334cd83 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1284,6 +1284,10 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd, CDBG("%s:%d master %d\n", __func__, __LINE__, master); if (master < MASTER_MAX && master >= 0) { mutex_lock(&cci_dev->cci_master_info[master].mutex); + mutex_lock(&cci_dev->cci_master_info[master]. + mutex_q[PRIORITY_QUEUE]); + mutex_lock(&cci_dev->cci_master_info[master]. + mutex_q[SYNC_QUEUE]); flush_workqueue(cci_dev->write_wq[master]); /* Re-initialize the completion */ reinit_completion(&cci_dev-> @@ -1308,6 +1312,10 @@ static int32_t msm_cci_init(struct v4l2_subdev *sd, if (rc <= 0) pr_err("%s:%d wait failed %d\n", __func__, __LINE__, rc); + mutex_unlock(&cci_dev->cci_master_info[master]. + mutex_q[SYNC_QUEUE]); + mutex_unlock(&cci_dev->cci_master_info[master]. + mutex_q[PRIORITY_QUEUE]); mutex_unlock(&cci_dev->cci_master_info[master].mutex); } return 0; diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c index 5a891592b44f..c94ee509631f 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -452,7 +452,8 @@ static int32_t msm_ois_config(struct msm_ois_ctrl_t *o_ctrl, break; } - if (!conf_array.size) { + if (!conf_array.size || + conf_array.size > I2C_SEQ_REG_DATA_MAX) { pr_err("%s:%d failed\n", __func__, __LINE__); rc = -EFAULT; break; diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index a0d31ded04db..594fba08e623 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -348,6 +348,33 @@ static int mmc_force_err_set(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(mmc_force_err_fops, NULL, mmc_force_err_set, "%llu\n"); +static int mmc_err_state_get(void *data, u64 *val) +{ + struct mmc_host *host = data; + + if (!host) + return -EINVAL; + + *val = host->err_occurred ? 1 : 0; + + return 0; +} + +static int mmc_err_state_clear(void *data, u64 val) +{ + struct mmc_host *host = data; + + if (!host) + return -EINVAL; + + host->err_occurred = false; + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(mmc_err_state, mmc_err_state_get, + mmc_err_state_clear, "%llu\n"); + void mmc_add_host_debugfs(struct mmc_host *host) { struct dentry *root; @@ -393,6 +420,10 @@ void mmc_add_host_debugfs(struct mmc_host *host) root, host, &mmc_ring_buffer_fops)) goto err_node; #endif + if (!debugfs_create_file("err_state", S_IRUSR | S_IWUSR, root, host, + &mmc_err_state)) + goto err_node; + #ifdef CONFIG_MMC_CLKGATE if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), root, &host->clk_delay)) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 21d2a4b8f7ae..1fdc23365c8f 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -179,6 +179,8 @@ static void sdhci_dumpregs(struct sdhci_host *host) readl(host->ioaddr + SDHCI_ADMA_ADDRESS)); } + host->mmc->err_occurred = true; + if (host->ops->dump_vendor_regs) host->ops->dump_vendor_regs(host); sdhci_dump_state(host); diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 210ea654c83f..acd5347f2cae 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -15,6 +15,7 @@ */ #include <linux/etherdevice.h> +#include <linux/moduleparam.h> #include "wil6210.h" #include "wmi.h" #include "ftm.h" diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index a8427c5e3107..9d296a911daa 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -548,6 +548,26 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg, * HELPER FUNCTIONS * ********************/ +static void smblib_rerun_apsd(struct smb_charger *chg) +{ + int rc; + + smblib_dbg(chg, PR_MISC, "re-running APSD\n"); + if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) { + rc = smblib_masked_write(chg, + USBIN_SOURCE_CHANGE_INTRPT_ENB_REG, + AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't enable HVDCP auth IRQ rc=%d\n", + rc); + } + + rc = smblib_masked_write(chg, CMD_APSD_REG, + APSD_RERUN_BIT, APSD_RERUN_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc); +} + static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg) { const struct apsd_result *apsd_result; @@ -565,11 +585,7 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg) chg->hvdcp_disable_votable_indirect)) { apsd_result = smblib_get_apsd_result(chg); if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) { - /* rerun APSD */ - smblib_dbg(chg, PR_MISC, "rerun APSD\n"); - smblib_masked_write(chg, CMD_APSD_REG, - APSD_RERUN_BIT, - APSD_RERUN_BIT); + smblib_rerun_apsd(chg); } } } @@ -581,12 +597,13 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg) const struct apsd_result *apsd_result = smblib_get_apsd_result(chg); /* if PD is active, APSD is disabled so won't have a valid result */ - if (chg->pd_active) { + if (chg->pd_active) chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD; - return apsd_result; - } + else + chg->usb_psy_desc.type = apsd_result->pst; - chg->usb_psy_desc.type = apsd_result->pst; + smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n", + apsd_result->name, chg->pd_active); return apsd_result; } @@ -764,16 +781,7 @@ int smblib_rerun_apsd_if_required(struct smb_charger *chg) apsd_result = smblib_get_apsd_result(chg); if ((apsd_result->pst == POWER_SUPPLY_TYPE_UNKNOWN) || (apsd_result->pst == POWER_SUPPLY_TYPE_USB)) { - /* rerun APSD */ - pr_info("Reruning APSD type = %s at bootup\n", - apsd_result->name); - rc = smblib_masked_write(chg, CMD_APSD_REG, - APSD_RERUN_BIT, - APSD_RERUN_BIT); - if (rc < 0) { - smblib_err(chg, "Couldn't rerun APSD rc = %d\n", rc); - return rc; - } + smblib_rerun_apsd(chg); } return 0; diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index 09c50a81a943..cc809cbdd839 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -4187,7 +4187,6 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr) if (ctx->local_open_state == GLINK_CHANNEL_OPENED || ctx->local_open_state == GLINK_CHANNEL_OPENING) { ctx->transport_ptr = dummy_xprt_ctx; - rwref_write_put(&ctx->ch_state_lhb2); glink_core_move_ch_node(xprt_ptr, dummy_xprt_ctx, ctx); } else { /* local state is in either CLOSED or CLOSING */ @@ -4197,9 +4196,9 @@ static void glink_core_channel_cleanup(struct glink_core_xprt_ctx *xprt_ptr) /* Channel should be fully closed now. Delete here */ if (ch_is_fully_closed(ctx)) glink_delete_ch_from_list(ctx, false); - rwref_write_put(&ctx->ch_state_lhb2); } rwref_put(&ctx->ch_state_lhb2); + rwref_write_put(&ctx->ch_state_lhb2); ctx = get_first_ch_ctx(xprt_ptr); } spin_lock_irqsave(&xprt_ptr->xprt_ctx_lock_lhb1, flags); diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 4e541773c805..0a68eaf79e60 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -213,7 +213,7 @@ struct icnss_clk_info { }; static struct icnss_vreg_info icnss_vreg_info[] = { - {NULL, "vdd-0.8-cx-mx", 800000, 800000, 0, 0, true}, + {NULL, "vdd-0.8-cx-mx", 800000, 800000, 0, 0, false}, {NULL, "vdd-1.8-xo", 1800000, 1800000, 0, 0, false}, {NULL, "vdd-1.3-rfa", 1304000, 1304000, 0, 0, false}, {NULL, "vdd-3.3-ch0", 3312000, 3312000, 0, 0, false}, diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 7784b597e959..39c7de8c3048 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -186,6 +186,7 @@ extern void clocksource_suspend(void); extern void clocksource_resume(void); extern struct clocksource * __init clocksource_default_clock(void); extern void clocksource_mark_unstable(struct clocksource *cs); +extern void clocksource_select_force(void); extern u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cycles); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 5374bd6c4cbe..055b879dfa6b 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -534,6 +534,8 @@ struct mmc_host { struct dentry *debugfs_root; + bool err_occurred; + struct mmc_async_req *areq; /* active async req */ struct mmc_context_info context_info; /* async synchronization info */ diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index ddc21d0c1bbb..06c273252484 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -933,7 +933,6 @@ struct adm_cmd_connect_afe_port_v5 { #define SLIMBUS_3_TX 0x4007 #define SLIMBUS_4_RX 0x4008 #define SLIMBUS_4_TX 0x4009 -#define SLIMBUS_TX_VI 0x4f09 #define SLIMBUS_5_RX 0x400a #define SLIMBUS_5_TX 0x400b #define SLIMBUS_6_RX 0x400c @@ -10224,12 +10223,108 @@ struct asm_session_cmd_set_mtmx_strstr_params_v2 { */ }; +/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the + * audio client choose the rendering decision that the audio DSP should use. + */ +#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD 0x00012F0D + +/* Indicates that rendering decision will be based on default rate + * (session clock based rendering, device driven). + * 1. The default session clock based rendering is inherently driven + * by the timing of the device. + * 2. After the initial decision is made (first buffer after a run + * command), subsequent data rendering decisions are made with + * respect to the rate at which the device is rendering, thus deriving + * its timing from the device. + * 3. While this decision making is simple, it has some inherent limitations + * (mentioned in the next section). + * 4. If this API is not set, the session clock based rendering will be assumed + * and this will ensure that the DSP is backward compatible. + */ +#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT 0 + +/* Indicates that rendering decision will be based on local clock rate. + * 1. In the DSP loopback/client loopback use cases (frame based + * inputs), the incoming data into audio DSP is time-stamped at the + * local clock rate (STC). + * 2. This TS rate may match the incoming data rate or maybe different + * from the incoming data rate. + * 3. Regardless, the data will be time-stamped with local STC and + * therefore, the client is recommended to set this mode for these + * use cases. This method is inherently more robust to sequencing + * (AFE Start/Stop) and device switches, among other benefits. + * 4. This API will inform the DSP to compare every incoming buffer TS + * against local STC. + * 5. DSP will continue to honor render windows APIs, as before. + */ +#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC 1 + +/* Structure for rendering decision parameter */ +struct asm_session_mtmx_strtr_param_render_mode_t { + /* Specifies the type of rendering decision the audio DSP should use. + * + * @values + * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT + * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC + */ + u32 flags; +} __packed; + +/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the + * audio client to specify the clock recovery mechanism that the audio DSP + * should use. + */ + +#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD 0x00012F0E + +/* Indicates that default clock recovery will be used (no clock recovery). + * If the client wishes that no clock recovery be done, the client can + * choose this. This means that no attempt will made by the DSP to try and + * match the rates of the input and output audio. + */ +#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE 0 + +/* Indicates that independent clock recovery needs to be used. + * 1. In the DSP loopback/client loopback use cases (frame based inputs), + * the client should choose the independent clock recovery option. + * 2. This basically de-couples the audio and video from knowing each others + * clock sources and lets the audio DSP independently rate match the input + * and output rates. + * 3. After drift detection, the drift correction is achieved by either pulling + * the PLLs (if applicable) or by stream to device rate matching + * (for PCM use cases) by comparing drift with respect to STC. + * 4. For passthrough use cases, since the PLL pulling is the only option, + * a best effort will be made. + * If PLL pulling is not possible / available, the rendering will be + * done without rate matching. + */ +#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO 1 + +/* Payload of the #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC parameter. + */ +struct asm_session_mtmx_strtr_param_clk_rec_t { + /* Specifies the type of clock recovery that the audio DSP should + * use for rate matching. + */ + + /* @values + * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_DEFAULT + * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_INDEPENDENT + */ + u32 flags; +} __packed; + +union asm_session_mtmx_strtr_param_config { + struct asm_session_mtmx_strtr_param_window_v2_t window_param; + struct asm_session_mtmx_strtr_param_render_mode_t render_param; + struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param; +} __packed; + struct asm_mtmx_strtr_params { struct apr_hdr hdr; struct asm_session_cmd_set_mtmx_strstr_params_v2 param; struct asm_stream_param_data_v2 data; - u32 window_lsw; - u32 window_msw; + union asm_session_mtmx_strtr_param_config config; } __packed; #define ASM_SESSION_CMD_GET_MTMX_STRTR_PARAMS_V2 0x00010DCF diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 76bb795119c2..4947c30287a3 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -642,6 +642,14 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac, struct asm_session_mtmx_strtr_param_window_v2_t *window_param, uint32_t param_id); +/* Configure DSP render mode */ +int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac, + uint32_t render_mode); + +/* Configure DSP clock recovery mode */ +int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac, + uint32_t clk_rec_mode); + /* Retrieve the current DSP path delay */ int q6asm_get_path_delay(struct audio_client *ac); diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index e050bc758b3b..30481056cce1 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -132,20 +132,42 @@ struct snd_compr_audio_info { __u32 reserved[15]; } __attribute__((packed, aligned(4))); +#define SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER 0 +#define SNDRV_COMPRESS_RENDER_MODE_STC_MASTER 1 + +#define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0 +#define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1 + /** * enum sndrv_compress_encoder * @SNDRV_COMPRESS_ENCODER_PADDING: no of samples appended by the encoder at the * end of the track * @SNDRV_COMPRESS_ENCODER_DELAY: no of samples inserted by the encoder at the * beginning of the track + * @SNDRV_COMPRESS_PATH_DELAY: dsp path delay in microseconds + * @SNDRV_COMPRESS_RENDER_MODE: dsp render mode (audio master or stc) + * @SNDRV_COMPRESS_CLK_REC_MODE: clock recovery mode ( none or auto) + * @SNDRV_COMPRESS_RENDER_WINDOW: render window + * @SNDRV_COMPRESS_START_DELAY: start delay */ enum sndrv_compress_encoder { SNDRV_COMPRESS_ENCODER_PADDING = 1, SNDRV_COMPRESS_ENCODER_DELAY = 2, SNDRV_COMPRESS_MIN_BLK_SIZE = 3, SNDRV_COMPRESS_MAX_BLK_SIZE = 4, + SNDRV_COMPRESS_PATH_DELAY = 5, + SNDRV_COMPRESS_RENDER_MODE = 6, + SNDRV_COMPRESS_CLK_REC_MODE = 7, + SNDRV_COMPRESS_RENDER_WINDOW = 8, + SNDRV_COMPRESS_START_DELAY = 9, }; +#define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY +#define SNDRV_COMPRESS_RENDER_MODE SNDRV_COMPRESS_RENDER_MODE +#define SNDRV_COMPRESS_CLK_REC_MODE SNDRV_COMPRESS_CLK_REC_MODE +#define SNDRV_COMPRESS_RENDER_WINDOW SNDRV_COMPRESS_RENDER_WINDOW +#define SNDRV_COMPRESS_START_DELAY SNDRV_COMPRESS_START_DELAY + /** * struct snd_compr_metadata - compressed stream metadata * @key: key id diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index b98810d2f3b4..89cc82a38e4d 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -108,7 +108,7 @@ static int finished_booting; #ifdef CONFIG_CLOCKSOURCE_WATCHDOG static void clocksource_watchdog_work(struct work_struct *work); -static void clocksource_select(void); +static void clocksource_select(bool force); static LIST_HEAD(watchdog_list); static struct clocksource *watchdog; @@ -415,7 +415,7 @@ static int clocksource_watchdog_kthread(void *data) { mutex_lock(&clocksource_mutex); if (__clocksource_watchdog_kthread()) - clocksource_select(); + clocksource_select(false); mutex_unlock(&clocksource_mutex); return 0; } @@ -555,11 +555,12 @@ static inline void clocksource_update_max_deferment(struct clocksource *cs) #ifndef CONFIG_ARCH_USES_GETTIMEOFFSET -static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) +static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur, + bool force) { struct clocksource *cs; - if (!finished_booting || list_empty(&clocksource_list)) + if ((!finished_booting && !force) || list_empty(&clocksource_list)) return NULL; /* @@ -577,13 +578,13 @@ static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur) return NULL; } -static void __clocksource_select(bool skipcur) +static void __clocksource_select(bool skipcur, bool force) { bool oneshot = tick_oneshot_mode_active(); struct clocksource *best, *cs; /* Find the best suitable clocksource */ - best = clocksource_find_best(oneshot, skipcur); + best = clocksource_find_best(oneshot, skipcur, force); if (!best) return; @@ -623,22 +624,40 @@ static void __clocksource_select(bool skipcur) * Select the clocksource with the best rating, or the clocksource, * which is selected by userspace override. */ -static void clocksource_select(void) +static void clocksource_select(bool force) { - __clocksource_select(false); + return __clocksource_select(false, force); } static void clocksource_select_fallback(void) { - __clocksource_select(true); + __clocksource_select(true, false); } #else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */ -static inline void clocksource_select(void) { } + +static inline void clocksource_select(bool force) { } static inline void clocksource_select_fallback(void) { } #endif +/** + * clocksource_select_force - Force re-selection of the best clocksource + * among registered clocksources + * + * clocksource_select() can't select the best clocksource before + * calling clocksource_done_booting() and since clocksource_select() + * should be called with clocksource_mutex held, provide a new API + * can be called from other files to select best clockrouce irrespective + * of finished_booting flag. + */ +void clocksource_select_force(void) +{ + mutex_lock(&clocksource_mutex); + clocksource_select(true); + mutex_unlock(&clocksource_mutex); +} + /* * clocksource_done_booting - Called near the end of core bootup * @@ -655,7 +674,7 @@ static int __init clocksource_done_booting(void) * Run the watchdog first to eliminate unstable clock sources */ __clocksource_watchdog_kthread(); - clocksource_select(); + clocksource_select(false); mutex_unlock(&clocksource_mutex); return 0; } @@ -744,6 +763,7 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq } EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale); + /** * __clocksource_register_scale - Used to install new clocksources * @cs: clocksource to be registered @@ -765,7 +785,7 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq) mutex_lock(&clocksource_mutex); clocksource_enqueue(cs); clocksource_enqueue_watchdog(cs); - clocksource_select(); + clocksource_select(false); clocksource_select_watchdog(false); mutex_unlock(&clocksource_mutex); return 0; @@ -788,7 +808,7 @@ void clocksource_change_rating(struct clocksource *cs, int rating) { mutex_lock(&clocksource_mutex); __clocksource_change_rating(cs, rating); - clocksource_select(); + clocksource_select(false); clocksource_select_watchdog(false); mutex_unlock(&clocksource_mutex); } @@ -892,7 +912,7 @@ static ssize_t sysfs_override_clocksource(struct device *dev, ret = sysfs_get_uname(buf, override_name, count); if (ret >= 0) - clocksource_select(); + clocksource_select(false); mutex_unlock(&clocksource_mutex); diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index 4fe9e2d50f7a..192d9291a8f3 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -9319,6 +9319,7 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec) snd_soc_dapm_ignore_suspend(dapm, "AIF3 Playback"); snd_soc_dapm_ignore_suspend(dapm, "AIF3 Capture"); snd_soc_dapm_ignore_suspend(dapm, "AIF4 Playback"); + snd_soc_dapm_ignore_suspend(dapm, "AIF4 MAD TX"); snd_soc_dapm_ignore_suspend(dapm, "VIfeed"); snd_soc_dapm_sync(dapm); diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 6324e81759de..041a91e28988 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -2906,7 +2906,6 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, break; case MSM_BACKEND_DAI_SLIMBUS_4_TX: - case MSM_BACKEND_DAI_SLIMBUS_TX_VI: param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_FORMAT_S32_LE); rate->min = rate->max = SAMPLING_RATE_8KHZ; @@ -3699,8 +3698,7 @@ static int msm_snd_hw_params(struct snd_pcm_substream *substream, /* For <codec>_tx3 case */ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX) user_set_tx_ch = slim_tx_cfg[1].channels; - else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX || - dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_TX_VI) + else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX) user_set_tx_ch = msm_vi_feed_tx_ch; else user_set_tx_ch = tx_ch_cnt; @@ -5728,12 +5726,12 @@ static struct snd_soc_dai_link msm_tasha_be_dai_links[] = { /* Slimbus VI Recording */ { .name = LPASS_BE_SLIMBUS_TX_VI, - .stream_name = "Slimbus VI Capture", - .cpu_dai_name = "msm-dai-q6-dev.20233", + .stream_name = "Slimbus4 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16393", .platform_name = "msm-pcm-routing", .codec_name = "tasha_codec", .codec_dai_name = "tasha_vifeedback", - .be_id = MSM_BACKEND_DAI_SLIMBUS_TX_VI, + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX, .be_hw_params_fixup = msm_be_hw_params_fixup, .ops = &msm_be_ops, .ignore_suspend = 1, @@ -5913,16 +5911,15 @@ static struct snd_soc_dai_link msm_tavil_be_dai_links[] = { .ignore_pmdown_time = 1, .ignore_suspend = 1, }, - /* Slimbus VI Recording */ { .name = LPASS_BE_SLIMBUS_TX_VI, - .stream_name = "Slimbus VI Capture", - .cpu_dai_name = "msm-dai-q6-dev.20233", + .stream_name = "Slimbus4 Capture", + .cpu_dai_name = "msm-dai-q6-dev.16393", .platform_name = "msm-pcm-routing", .codec_name = "tavil_codec", .codec_dai_name = "tavil_vifeedback", - .be_id = MSM_BACKEND_DAI_SLIMBUS_TX_VI, + .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX, .be_hw_params_fixup = msm_be_hw_params_fixup, .ops = &msm_be_ops, .ignore_suspend = 1, diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 7f032dcceabd..4fa80c679b46 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -160,6 +160,10 @@ struct msm_compr_audio { uint32_t stream_available; uint32_t next_stream; + uint32_t run_mode; + uint32_t start_delay_lsw; + uint32_t start_delay_msw; + uint64_t marker_timestamp; struct msm_compr_gapless_state gapless_state; @@ -215,6 +219,99 @@ static int msm_compr_send_dec_params(struct snd_compr_stream *cstream, struct msm_compr_dec_params *dec_params, int stream_id); +static int msm_compr_set_render_mode(struct msm_compr_audio *prtd, + uint32_t render_mode) { + int ret = -EINVAL; + struct audio_client *ac = prtd->audio_client; + + pr_debug("%s, got render mode %u\n", __func__, render_mode); + + if (render_mode == SNDRV_COMPRESS_RENDER_MODE_AUDIO_MASTER) { + render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT; + } else if (render_mode == SNDRV_COMPRESS_RENDER_MODE_STC_MASTER) { + render_mode = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC; + prtd->run_mode = ASM_SESSION_CMD_RUN_STARTIME_RUN_WITH_DELAY; + } else { + pr_err("%s, Invalid render mode %u\n", __func__, + render_mode); + ret = -EINVAL; + goto exit; + } + + ret = q6asm_send_mtmx_strtr_render_mode(ac, render_mode); + if (ret) { + pr_err("%s, Render mode can't be set error %d\n", __func__, + ret); + } +exit: + return ret; +} + +static int msm_compr_set_clk_rec_mode(struct audio_client *ac, + uint32_t clk_rec_mode) { + int ret = -EINVAL; + + pr_debug("%s, got clk rec mode %u\n", __func__, clk_rec_mode); + + if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_NONE) { + clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE; + } else if (clk_rec_mode == SNDRV_COMPRESS_CLK_REC_MODE_AUTO) { + clk_rec_mode = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO; + } else { + pr_err("%s, Invalid clk rec_mode mode %u\n", __func__, + clk_rec_mode); + ret = -EINVAL; + goto exit; + } + + ret = q6asm_send_mtmx_strtr_clk_rec_mode(ac, clk_rec_mode); + if (ret) { + pr_err("%s, clk rec mode can't be set, error %d\n", __func__, + ret); + } + +exit: + return ret; +} + +static int msm_compr_set_render_window(struct audio_client *ac, + uint32_t ws_lsw, uint32_t ws_msw, + uint32_t we_lsw, uint32_t we_msw) +{ + int ret = -EINVAL; + struct asm_session_mtmx_strtr_param_window_v2_t asm_mtmx_strtr_window; + uint32_t param_id; + + pr_debug("%s, ws_lsw 0x%x ws_msw 0x%x we_lsw 0x%x we_ms 0x%x\n", + __func__, ws_lsw, ws_msw, we_lsw, we_msw); + + memset(&asm_mtmx_strtr_window, 0, + sizeof(struct asm_session_mtmx_strtr_param_window_v2_t)); + asm_mtmx_strtr_window.window_lsw = ws_lsw; + asm_mtmx_strtr_window.window_msw = ws_msw; + param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_START_V2; + ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window, + param_id); + if (ret) { + pr_err("%s, start window can't be set error %d\n", __func__, + ret); + goto exit; + } + + asm_mtmx_strtr_window.window_lsw = we_lsw; + asm_mtmx_strtr_window.window_msw = we_msw; + param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_WINDOW_END_V2; + ret = q6asm_send_mtmx_strtr_window(ac, &asm_mtmx_strtr_window, + param_id); + if (ret) { + pr_err("%s, end window can't be set error %d\n", __func__, + ret); + } + +exit: + return ret; +} + static int msm_compr_set_volume(struct snd_compr_stream *cstream, uint32_t volume_l, uint32_t volume_r) { @@ -1586,6 +1683,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; kfree(prtd); + runtime->private_data = NULL; return 0; } @@ -1645,6 +1743,7 @@ static int msm_compr_capture_free(struct snd_compr_stream *cstream) q6asm_audio_client_free(ac); kfree(prtd); + runtime->private_data = NULL; return 0; } @@ -1963,7 +2062,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) msm_compr_read_buffer(prtd); } /* issue RUN command for the stream */ - q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + q6asm_run_nowait(prtd->audio_client, prtd->run_mode, + prtd->start_delay_msw, prtd->start_delay_lsw); break; case SNDRV_PCM_TRIGGER_STOP: spin_lock_irqsave(&prtd->lock, flags); @@ -2047,7 +2147,8 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) prtd->gapless_state.gapless_transition); if (!prtd->gapless_state.gapless_transition) { atomic_set(&prtd->start, 1); - q6asm_run_nowait(prtd->audio_client, 0, 0, 0); + q6asm_run_nowait(prtd->audio_client, prtd->run_mode, + 0, 0); } break; case SND_COMPR_TRIGGER_PARTIAL_DRAIN: @@ -2717,11 +2818,14 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream, return -EINVAL; } - if (prtd->compr_passthr != LEGACY_PCM) { + if (((metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) || + (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY)) && + (prtd->compr_passthr != LEGACY_PCM)) { pr_debug("%s: No trailing silence for compress_type[%d]\n", __func__, prtd->compr_passthr); return 0; } + ac = prtd->audio_client; if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) { pr_debug("%s, got encoder padding %u", __func__, metadata->value[0]); @@ -2729,11 +2833,63 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream, } else if (metadata->key == SNDRV_COMPRESS_ENCODER_DELAY) { pr_debug("%s, got encoder delay %u", __func__, metadata->value[0]); prtd->gapless_state.initial_samples_drop = metadata->value[0]; + } else if (metadata->key == SNDRV_COMPRESS_RENDER_MODE) { + return msm_compr_set_render_mode(prtd, metadata->value[0]); + } else if (metadata->key == SNDRV_COMPRESS_CLK_REC_MODE) { + return msm_compr_set_clk_rec_mode(ac, metadata->value[0]); + } else if (metadata->key == SNDRV_COMPRESS_RENDER_WINDOW) { + return msm_compr_set_render_window( + ac, + metadata->value[0], + metadata->value[1], + metadata->value[2], + metadata->value[3]); + } else if (metadata->key == SNDRV_COMPRESS_START_DELAY) { + prtd->start_delay_lsw = metadata->value[0]; + prtd->start_delay_msw = metadata->value[1]; } return 0; } +static int msm_compr_get_metadata(struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata) +{ + struct msm_compr_audio *prtd; + struct audio_client *ac; + int ret = -EINVAL; + + pr_debug("%s\n", __func__); + + if (!metadata || !cstream || !cstream->runtime) + return ret; + + if (metadata->key != SNDRV_COMPRESS_PATH_DELAY) { + pr_err("%s, unsupported key %d\n", __func__, metadata->key); + return ret; + } + + prtd = cstream->runtime->private_data; + if (!prtd || !prtd->audio_client) { + pr_err("%s: prtd or audio client is NULL\n", __func__); + return ret; + } + + ac = prtd->audio_client; + ret = q6asm_get_path_delay(prtd->audio_client); + if (ret) { + pr_err("%s: get_path_delay failed, ret=%d\n", __func__, ret); + return ret; + } + + pr_debug("%s, path delay(in us) %u\n", __func__, ac->path_delay); + + metadata->value[0] = ac->path_delay; + + return ret; +} + + static int msm_compr_set_next_track_param(struct snd_compr_stream *cstream, union snd_codec_options *codec_options) { @@ -3889,6 +4045,7 @@ static struct snd_compr_ops msm_compr_ops = { .pointer = msm_compr_pointer, .set_params = msm_compr_set_params, .set_metadata = msm_compr_set_metadata, + .get_metadata = msm_compr_get_metadata, .set_next_track_param = msm_compr_set_next_track_param, .ack = msm_compr_ack, .copy = msm_compr_copy, diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index 19e2fad2920d..d7efefdb3a04 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -1773,7 +1773,6 @@ static int msm_dai_q6_hw_params(struct snd_pcm_substream *substream, case SLIMBUS_2_TX: case SLIMBUS_3_TX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_TX: case SLIMBUS_6_TX: case SLIMBUS_7_TX: @@ -1928,7 +1927,6 @@ static int msm_dai_q6_set_channel_map(struct snd_soc_dai *dai, case SLIMBUS_2_TX: case SLIMBUS_3_TX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_TX: case SLIMBUS_6_TX: case SLIMBUS_7_TX: @@ -2348,9 +2346,6 @@ static const struct snd_kcontrol_new sb_config_controls[] = { msm_dai_q6_cal_info_put), SOC_ENUM_EXT("SLIM_2_RX Format", sb_config_enum[0], msm_dai_q6_sb_format_get, - msm_dai_q6_sb_format_put), - SOC_ENUM_EXT("SLIM_TX_VI Format", sb_config_enum[0], - msm_dai_q6_sb_format_get, msm_dai_q6_sb_format_put) }; @@ -2409,11 +2404,6 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai) snd_ctl_new1(&sb_config_controls[0], dai_data)); break; - case SLIMBUS_TX_VI: - rc = snd_ctl_add(dai->component->card->snd_card, - snd_ctl_new1(&sb_config_controls[3], - dai_data)); - break; case SLIMBUS_2_RX: rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(&sb_config_controls[1], @@ -3302,25 +3292,6 @@ static struct snd_soc_dai_driver msm_dai_q6_slimbus_tx_dai[] = { }, { .capture = { - .stream_name = "Slimbus VI Capture", - .aif_name = "SLIMBUS_TX_VI", - .rates = SNDRV_PCM_RATE_8000_96000 | - SNDRV_PCM_RATE_192000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, - .channels_min = 1, - .channels_max = 4, - .rate_min = 8000, - .rate_max = 192000, - }, - .ops = &msm_dai_q6_ops, - .id = SLIMBUS_TX_VI, - .probe = msm_dai_q6_dai_probe, - .remove = msm_dai_q6_dai_remove, - }, - { - .capture = { .stream_name = "Slimbus5 Capture", .aif_name = "SLIMBUS_5_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | @@ -4677,9 +4648,6 @@ register_slim_playback: case SLIMBUS_4_TX: strlcpy(stream_name, "Slimbus4 Capture", 80); goto register_slim_capture; - case SLIMBUS_TX_VI: - strlcpy(stream_name, "Slimbus VI Capture", 80); - goto register_slim_capture; case SLIMBUS_5_TX: strlcpy(stream_name, "Slimbus5 Capture", 80); goto register_slim_capture; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c index d65108e04e0b..b1a1ea54a73e 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -684,6 +684,7 @@ done: mutex_unlock(&prtd->lock); prtd->prepared--; kfree(prtd); + runtime->private_data = NULL; return 0; } static int msm_afe_prepare(struct snd_pcm_substream *substream) diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 33c5b6486cca..9c247124a383 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -570,6 +570,8 @@ static int msm_pcm_close(struct snd_pcm_substream *substream) SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); + runtime->private_data = NULL; + return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index e14f410bd310..7928c3791f96 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -804,6 +804,8 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_PLAYBACK); kfree(prtd); + runtime->private_data = NULL; + return 0; } @@ -909,6 +911,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream) msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id, SNDRV_PCM_STREAM_CAPTURE); kfree(prtd); + runtime->private_data = NULL; return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 3677a06c65ae..c3db926be5d9 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -96,7 +96,6 @@ enum { #define SLIMBUS_2_TX_TEXT "SLIMBUS_2_TX" #define SLIMBUS_3_TX_TEXT "SLIMBUS_3_TX" #define SLIMBUS_4_TX_TEXT "SLIMBUS_4_TX" -#define SLIMBUS_TX_VI_TEXT "SLIMBUS_TX_VI" #define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX" #define TERT_MI2S_TX_TEXT "TERT_MI2S_TX" #define QUAT_MI2S_TX_TEXT "QUAT_MI2S_TX" @@ -109,7 +108,7 @@ static const char * const lsm_port_text[] = { SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT, SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT, TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT, - INT3_MI2S_TX_TEXT, SLIMBUS_TX_VI_TEXT + INT3_MI2S_TX_TEXT }; struct msm_pcm_route_bdai_pp_params { @@ -538,7 +537,6 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { LPASS_BE_INT6_MI2S_RX}, { AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_INT6_MI2S_TX}, - { SLIMBUS_TX_VI, 0, {0}, {0}, 0, 0, 0, 0, 0, LPASS_BE_SLIMBUS_TX_VI}, }; /* Track ASM playback & capture sessions of DAI @@ -5681,9 +5679,6 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = { SOC_SINGLE_EXT("SLIM_4_TX", MSM_BACKEND_DAI_SLIMBUS_4_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), - SOC_SINGLE_EXT("SLIM_TX_VI", MSM_BACKEND_DAI_SLIMBUS_TX_VI, - MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, - msm_routing_put_audio_mixer), SOC_SINGLE_EXT("SLIM_6_TX", MSM_BACKEND_DAI_SLIMBUS_6_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), @@ -10994,8 +10989,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture", 0, 0, 0, 0), - SND_SOC_DAPM_AIF_IN("SLIMBUS_TX_VI", "Slimbus VI Capture", - 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("SENARY_TX", "Senary_mi2s Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("INT5_MI2S_TX", "INT5 MI2S Capture", @@ -11759,7 +11752,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia4 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"}, {"MultiMedia8 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"}, {"MultiMedia1 Mixer", "SLIM_4_TX", "SLIMBUS_4_TX"}, - {"MultiMedia1 Mixer", "SLIM_TX_VI", "SLIMBUS_TX_VI"}, {"MultiMedia1 Mixer", "SLIM_6_TX", "SLIMBUS_6_TX"}, {"MultiMedia1 Mixer", "SLIM_7_TX", "SLIMBUS_7_TX"}, {"MultiMedia1 Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"}, @@ -13921,7 +13913,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_1_TX", NULL, "BE_IN" }, {"SLIMBUS_3_TX", NULL, "BE_IN" }, {"SLIMBUS_4_TX", NULL, "BE_IN" }, - {"SLIMBUS_TX_VI", NULL, "BE_IN" }, {"SLIMBUS_5_TX", NULL, "BE_IN" }, {"SLIMBUS_6_TX", NULL, "BE_IN" }, {"SLIMBUS_7_TX", NULL, "BE_IN" }, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 94c79f00afec..fcd155e71317 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -70,8 +70,8 @@ #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_TX_VI "SLIMBUS_TX_VI" +#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" @@ -362,7 +362,6 @@ enum { MSM_BACKEND_DAI_INT5_MI2S_TX, MSM_BACKEND_DAI_INT6_MI2S_RX, MSM_BACKEND_DAI_INT6_MI2S_TX, - MSM_BACKEND_DAI_SLIMBUS_TX_VI, MSM_BACKEND_DAI_MAX, }; diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 4a4f02c7b9b6..2da7e6dc11e7 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -2463,6 +2463,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, pr_err("%s: DTS_EAGLE mmap did not work!", __func__); } + memset(&open, 0, sizeof(struct adm_cmd_device_open_v5)); open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); @@ -2506,6 +2507,8 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology, if ((this_adm.num_ec_ref_rx_chans != 0) && (path != 1) && (open.endpoint_id_2 != 0xFFFF)) { + memset(&open_v6, 0, + sizeof(struct adm_cmd_device_open_v6)); memcpy(&open_v6, &open, sizeof(struct adm_cmd_device_open_v5)); open_v6.hdr.opcode = ADM_CMD_DEVICE_OPEN_V6; diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index fcff383b9c3b..80729b3052b7 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -547,7 +547,6 @@ int afe_get_port_type(u16 port_id) case SLIMBUS_2_TX: case SLIMBUS_3_TX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_TX: case SLIMBUS_6_TX: case SLIMBUS_7_TX: @@ -652,7 +651,6 @@ int afe_sizeof_cfg_cmd(u16 port_id) case SLIMBUS_3_TX: case SLIMBUS_4_RX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_RX: case SLIMBUS_5_TX: case SLIMBUS_6_RX: @@ -2939,13 +2937,6 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, return ret; } - /* - * Virtual SLIMBUS_TX_VI shares afe port with SLIMBUS_4_TX. - * port_id changes to physical port of SLIMBUS_4_TX. - */ - if (port_id == SLIMBUS_TX_VI) - port_id = SLIMBUS_4_TX; - if ((port_id == RT_PROXY_DAI_001_RX) || (port_id == RT_PROXY_DAI_002_TX)) { pr_debug("%s: before incrementing pcm_afe_instance %d"\ @@ -3132,7 +3123,6 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, case SLIMBUS_3_TX: case SLIMBUS_4_RX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_RX: case SLIMBUS_5_TX: case SLIMBUS_6_RX: @@ -3325,7 +3315,6 @@ int afe_get_port_index(u16 port_id) case RT_PROXY_PORT_001_TX: return IDX_RT_PROXY_PORT_001_TX; case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX; case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX; - case SLIMBUS_TX_VI: return IDX_SLIMBUS_4_TX; case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX; case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX; case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX; @@ -5494,14 +5483,6 @@ int afe_close(int port_id) goto fail_cmd; } pr_debug("%s: port_id = 0x%x\n", __func__, port_id); - - /* - * Virtual SLIMBUS_TX_VI shares afe port with SLIMBUS_4_TX. - * port_id changes to physical port of SLIMBUS_4_TX. - */ - if (port_id == SLIMBUS_TX_VI) - port_id = SLIMBUS_4_TX; - if ((port_id == RT_PROXY_DAI_001_RX) || (port_id == RT_PROXY_DAI_002_TX)) { pr_debug("%s: before decrementing pcm_afe_instance %d\n", diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index d55c28fab652..c3a4719542ef 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -7934,16 +7934,18 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac, matrix.param.data_payload_addr_lsw = 0; matrix.param.data_payload_addr_msw = 0; matrix.param.mem_map_handle = 0; - matrix.param.data_payload_size = sizeof(matrix) - - sizeof(matrix.hdr) - sizeof(matrix.param); + matrix.param.data_payload_size = + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct asm_session_mtmx_strtr_param_window_v2_t); matrix.param.direction = 0; /* RX */ matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC; matrix.data.param_id = param_id; - matrix.data.param_size = matrix.param.data_payload_size - - sizeof(matrix.data); + matrix.data.param_size = + sizeof(struct asm_session_mtmx_strtr_param_window_v2_t); matrix.data.reserved = 0; - matrix.window_lsw = window_param->window_lsw; - matrix.window_msw = window_param->window_msw; + memcpy(&(matrix.config.window_param), + window_param, + sizeof(struct asm_session_mtmx_strtr_param_window_v2_t)); rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix); if (rc < 0) { @@ -7973,7 +7975,177 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac, rc = 0; fail_cmd: return rc; -}; +} + +int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac, + uint32_t render_mode) +{ + struct asm_mtmx_strtr_params matrix; + struct asm_session_mtmx_strtr_param_render_mode_t render_param; + int sz = 0; + int rc = 0; + + pr_debug("%s: render mode is %d\n", __func__, render_mode); + + if (!ac) { + pr_err("%s: audio client handle is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + if (ac->apr == NULL) { + pr_err("%s: ac->apr is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + if ((render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT) && + (render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC)) { + pr_err("%s: Invalid render mode %d\n", __func__, render_mode); + rc = -EINVAL; + goto exit; + } + + memset(&render_param, 0, + sizeof(struct asm_session_mtmx_strtr_param_render_mode_t)); + render_param.flags = render_mode; + + memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params)); + sz = sizeof(struct asm_mtmx_strtr_params); + q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE); + atomic_set(&ac->cmd_state, -1); + matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2; + + matrix.param.data_payload_addr_lsw = 0; + matrix.param.data_payload_addr_msw = 0; + matrix.param.mem_map_handle = 0; + matrix.param.data_payload_size = + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct asm_session_mtmx_strtr_param_render_mode_t); + matrix.param.direction = 0; /* RX */ + matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC; + matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD; + matrix.data.param_size = + sizeof(struct asm_session_mtmx_strtr_param_render_mode_t); + matrix.data.reserved = 0; + memcpy(&(matrix.config.render_param), + &render_param, + sizeof(struct asm_session_mtmx_strtr_param_render_mode_t)); + + rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix); + if (rc < 0) { + pr_err("%s: Render mode send failed paramid [0x%x]\n", + __func__, matrix.data.param_id); + rc = -EINVAL; + goto exit; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, Render mode send paramid [0x%x]\n", + __func__, matrix.data.param_id); + rc = -ETIMEDOUT; + goto exit; + } + + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto exit; + } + rc = 0; +exit: + return rc; +} + +int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac, + uint32_t clk_rec_mode) +{ + struct asm_mtmx_strtr_params matrix; + struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param; + int sz = 0; + int rc = 0; + + pr_debug("%s: clk rec mode is %d\n", __func__, clk_rec_mode); + + if (!ac) { + pr_err("%s: audio client handle is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + if (ac->apr == NULL) { + pr_err("%s: ac->apr is NULL\n", __func__); + rc = -EINVAL; + goto exit; + } + + if ((clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE) && + (clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO)) { + pr_err("%s: Invalid clk rec mode %d\n", __func__, clk_rec_mode); + rc = -EINVAL; + goto exit; + } + + memset(&clk_rec_param, 0, + sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t)); + clk_rec_param.flags = clk_rec_mode; + + memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params)); + sz = sizeof(struct asm_mtmx_strtr_params); + q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE); + atomic_set(&ac->cmd_state, -1); + matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2; + + matrix.param.data_payload_addr_lsw = 0; + matrix.param.data_payload_addr_msw = 0; + matrix.param.mem_map_handle = 0; + matrix.param.data_payload_size = + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t); + matrix.param.direction = 0; /* RX */ + matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC; + matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD; + matrix.data.param_size = + sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t); + matrix.data.reserved = 0; + memcpy(&(matrix.config.clk_rec_param), + &clk_rec_param, + sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t)); + + rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix); + if (rc < 0) { + pr_err("%s: clk rec mode send failed paramid [0x%x]\n", + __func__, matrix.data.param_id); + rc = -EINVAL; + goto exit; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, clk rec mode send paramid [0x%x]\n", + __func__, matrix.data.param_id); + rc = -ETIMEDOUT; + goto exit; + } + + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto exit; + } + rc = 0; +exit: + return rc; +} static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id) { diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c index a4951dc77378..3b745c24f90e 100644 --- a/sound/soc/msm/qdsp6v2/q6audio-v2.c +++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -64,7 +64,6 @@ int q6audio_get_port_index(u16 port_id) case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX; case SLIMBUS_4_RX: return IDX_SLIMBUS_4_RX; case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX; - case SLIMBUS_TX_VI: return IDX_SLIMBUS_4_TX; case SLIMBUS_5_RX: return IDX_SLIMBUS_5_RX; case SLIMBUS_5_TX: return IDX_SLIMBUS_5_TX; case SLIMBUS_6_RX: return IDX_SLIMBUS_6_RX; @@ -312,7 +311,6 @@ int q6audio_get_port_id(u16 port_id) case SLIMBUS_3_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_3_TX; case SLIMBUS_4_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_RX; case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX; - case SLIMBUS_TX_VI: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX; case SLIMBUS_5_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_RX; case SLIMBUS_5_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_5_TX; case SLIMBUS_6_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_6_RX; @@ -690,7 +688,6 @@ int q6audio_validate_port(u16 port_id) case SLIMBUS_3_TX: case SLIMBUS_4_RX: case SLIMBUS_4_TX: - case SLIMBUS_TX_VI: case SLIMBUS_5_RX: case SLIMBUS_5_TX: case SLIMBUS_6_RX: diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index eb894d073c07..736b9c45e59a 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -527,6 +527,11 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream, cstream, &async_domain); } else { be_list[j++] = be; + if (j == DPCM_MAX_BE_USERS) { + dev_dbg(fe->dev, + "ASoC: MAX backend users!\n"); + break; + } } } for (i = 0; i < j; i++) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 13649f96b370..0ba9dfb854b3 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2403,6 +2403,10 @@ void dpcm_be_dai_prepare_async(struct snd_soc_pcm_runtime *fe, int stream, dpcm, domain); } else { dpcm_async[i++] = dpcm; + if (i == DPCM_MAX_BE_USERS) { + dev_dbg(fe->dev, "ASoC: MAX backend users!\n"); + break; + } } } |
