diff options
75 files changed, 2812 insertions, 657 deletions
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt index 8adfeebb1580..af80de7f5f1f 100644 --- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt +++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt @@ -215,6 +215,12 @@ First Level Node - FG Gen3 device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. +- qcom,battery-thermal-coefficients + Usage: optional + Value type: <u8> + Definition: Byte array of battery thermal coefficients. + This should be exactly 3 bytes in length. + - qcom,fg-jeita-hyst-temp Usage: optional Value type: <u32> @@ -320,6 +326,27 @@ First Level Node - FG Gen3 device to be configured in conjunction with the charger side configuration for proper functionality. +- qcom,slope-limit-temp-threshold + Usage: optional + Value type: <u32> + Definition: Battery temperature threshold to decide when slope limit + coefficients should be applied along with charging status. + Unit is in decidegC. + +- qcom,slope-limit-coeffs + Usage: optional + Value type: <prop-encoded-array> + Definition: A list of integers which holds the slope limit coefficients + in the following order. Allowed size is 4. Possible values + are from 0 to 31. Unit is in decipercentage. + Element 0 - Low temperature discharging + Element 1 - Low temperature charging + Element 2 - High temperature discharging + Element 3 - High temperature charging + These coefficients have to be specified along with the + property "qcom,slope-limit-temp-threshold" to make dynamic + slope limit adjustment functional. + ========================================================== Second Level Nodes - Peripherals managed by FG Gen3 driver ========================================================== @@ -354,6 +381,9 @@ pmi8998_fg: qpnp,fg { qcom,ki-coeff-soc-dischg = <30 60 90>; qcom,ki-coeff-med-dischg = <800 1000 1400>; qcom,ki-coeff-hi-dischg = <1200 1500 2100>; + qcom,slope-limit-temp-threshold = <100>; + qcom,slope-limit-coeffs = <10 11 12 13>; + qcom,battery-thermal-coefficients = [9d 50 ff]; status = "okay"; qcom,fg-batt-soc@4000 { diff --git a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts index f84708d73bd8..6288031fdd50 100644 --- a/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts +++ b/arch/arm/boot/dts/qcom/apq8998-v2.1-mediabox.dts @@ -21,10 +21,6 @@ qcom,board-id = <8 1>; }; -&pil_modem { - status = "disabled"; -}; - &msm_ath10k_wlan { status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi index ca5b22cd34ee..131ad649ef8b 100644 --- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi @@ -607,6 +607,8 @@ qcom,lra-high-z = "opt1"; qcom,lra-auto-res-mode = "qwd"; qcom,lra-res-cal-period = <4>; + qcom,correct-lra-drive-freq; + qcom,misc-trim-error-rc19p2-clk-reg-present; }; }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi index 932757fa0bb4..c21c136907d4 100644 --- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi @@ -646,6 +646,8 @@ qcom,lra-high-z = "opt1"; qcom,lra-auto-res-mode = "qwd"; qcom,lra-res-cal-period = <4>; + qcom,correct-lra-drive-freq; + qcom,misc-trim-error-rc19p2-clk-reg-present; }; flash_led: qcom,leds@d300 { diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi index 8acbb6600415..697b049235bd 100644 --- a/arch/arm/boot/dts/qcom/msm8998.dtsi +++ b/arch/arm/boot/dts/qcom/msm8998.dtsi @@ -1750,7 +1750,7 @@ tx-fifo-resize; snps,nominal-elastic-buffer; snps,disable-clk-gating; - snps,hird_thresh = <0x10>; + snps,hird-threshold = /bits/ 8 <0x10>; snps,num-gsi-evt-buffs = <0x3>; }; diff --git a/arch/arm/boot/dts/qcom/sdm630-gpu.dtsi b/arch/arm/boot/dts/qcom/sdm630-gpu.dtsi new file mode 100644 index 000000000000..eec0862e5ee3 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm630-gpu.dtsi @@ -0,0 +1,271 @@ +/* Copyright (c) 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 + * 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 { + pil_gpu: qcom,kgsl-hyp { + compatible = "qcom,pil-tz-generic"; + qcom,pas-id = <13>; + qcom,firmware-name = "a508_zap"; + }; + + msm_bus: qcom,kgsl-busmon{ + label = "kgsl-busmon"; + compatible = "qcom,kgsl-busmon"; + }; + + gpubw: qcom,gpubw { + compatible = "qcom,devbw"; + governor = "bw_vbif"; + qcom,src-dst-ports = <26 512>; + /* + * active-only flag is used while registering the bus + * governor. It helps release the bus vote when the CPU + * subsystem is inactive + */ + qcom,active-only; + /* + * IB votes in MBPS, derived using below formula + * IB = (DDR frequency * DDR bus width in Bytes * Dual rate) + * Note: IB vote is per DDR channel vote + */ + qcom,bw-tbl = + < 0 /* off */ >, + < 381 /* 100 MHz */ >, + < 572 /* 150 MHz */ >, + < 762 /* 200 MHz */ >, + < 1144 /* 300 MHz */ >, + < 1571 /* 412 MHz */ >, + < 2086 /* 547 MHz */ >, + < 2597 /* 681 MHz */ >, + < 2929 /* 768 MHz */ >, + < 3879 /* 1017 MHz */ >, + < 4943 /* 1296 MHz */ >, + < 5161 /* 1353 MHz */ >; + }; + + msm_gpu: qcom,kgsl-3d0@5000000 { + label = "kgsl-3d0"; + compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; + status = "ok"; + reg = <0x5000000 0x40000>; + reg-names = "kgsl_3d0_reg_memory"; + interrupts = <0 300 0>; + interrupt-names = "kgsl_3d0_irq"; + qcom,id = <0>; + + qcom,chipid = <0x05000800>; + + qcom,initial-pwrlevel = <5>; + + /* <HZ/12> */ + qcom,idle-timeout = <80>; + + qcom,highest-bank-bit = <14>; + + /* size in bytes */ + qcom,snapshot-size = <1048576>; + + clocks = <&clock_gfx GPUCC_GFX3D_CLK>, + <&clock_gcc GCC_GPU_CFG_AHB_CLK>, + <&clock_gfx GPUCC_RBBMTIMER_CLK>, + <&clock_gcc GCC_GPU_BIMC_GFX_CLK>, + <&clock_gcc GCC_BIMC_GFX_CLK>, + <&clock_gpu GPUCC_RBCPR_CLK>; + + clock-names = "core_clk", "iface_clk", "rbbmtimer_clk", + "mem_clk", "alt_mem_iface_clk", "rbcpr_clk"; + + /* Bus Scale Settings */ + qcom,gpubw-dev = <&gpubw>; + qcom,bus-control; + /* GPU to BIMC bus width, VBIF data transfer in 1 cycle */ + qcom,bus-width = <32>; + qcom,msm-bus,name = "grp3d"; + qcom,msm-bus,num-cases = <14>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <26 512 0 0>, + <26 512 0 400000>, /* 1 bus=100 */ + <26 512 0 600000>, /* 2 bus=150 */ + <26 512 0 800000>, /* 3 bus=200 */ + <26 512 0 1200000>, /* 4 bus=300 */ + <26 512 0 1648000>, /* 5 bus=412 */ + <26 512 0 2188000>, /* 6 bus=547 */ + <26 512 0 2724000>, /* 7 bus=681 */ + <26 512 0 3072000>, /* 8 bus=768 */ + <26 512 0 4068000>, /* 9 bus=1017 */ + <26 512 0 5184000>, /* 10 bus=1296 */ + <26 512 0 5412000>; /* 11 bus=1353 */ + + /* GDSC regulator names */ + regulator-names = "vddcx", "vdd"; + /* GDSC oxili regulators */ + vddcx-supply = <&gdsc_gpu_cx>; + vdd-supply = <&gdsc_gpu_gx>; + + /* CPU latency parameter */ + qcom,pm-qos-active-latency = <349>; + qcom,pm-qos-wakeup-latency = <349>; + + /* Quirks */ + qcom,gpu-quirk-dp2clockgating-disable; + qcom,gpu-quirk-lmloadkill-disable; + + /* Enable context aware freq. scaling */ + qcom,enable-ca-jump; + + /* Context aware jump busy penalty in us */ + qcom,ca-busy-penalty = <12000>; + + /* Context aware jump target power level */ + qcom,ca-target-pwrlevel = <4>; + + /* GPU Mempools */ + qcom,gpu-mempools { + #address-cells= <1>; + #size-cells = <0>; + compatible = "qcom,gpu-mempools"; + + qcom,mempool-max-pages = <32768>; + + /* 4K Page Pool configuration */ + qcom,gpu-mempool@0 { + reg = <0>; + qcom,mempool-page-size = <4096>; + }; + /* 64K Page Pool configuration */ + qcom,gpu-mempool@1 { + reg = <1>; + qcom,mempool-page-size = <65536>; + }; + }; + + /* Power levels */ + qcom,gpu-pwrlevels { + #address-cells = <1>; + #size-cells = <0>; + + compatible = "qcom,gpu-pwrlevels"; + + /* TURBO */ + qcom,gpu-pwrlevel@0 { + reg = <0>; + qcom,gpu-freq = <775000000>; + qcom,bus-freq = <11>; + qcom,bus-min = <10>; + qcom,bus-max = <11>; + }; + + /* TURBO */ + qcom,gpu-pwrlevel@1 { + reg = <1>; + qcom,gpu-freq = <700000000>; + qcom,bus-freq = <10>; + qcom,bus-min = <9>; + qcom,bus-max = <11>; + }; + + /* NOM_L1 */ + qcom,gpu-pwrlevel@2 { + reg = <2>; + qcom,gpu-freq = <647000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <8>; + qcom,bus-max = <9>; + }; + + /* NOM */ + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <588000000>; + qcom,bus-freq = <9>; + qcom,bus-min = <7>; + qcom,bus-max = <9>; + }; + + /* SVS_L1 */ + qcom,gpu-pwrlevel@4 { + reg = <4>; + qcom,gpu-freq = <465000000>; + qcom,bus-freq = <8>; + qcom,bus-min = <6>; + qcom,bus-max = <9>; + }; + + /* SVS */ + qcom,gpu-pwrlevel@5 { + reg = <5>; + qcom,gpu-freq = <370000000>; + qcom,bus-freq = <5>; + qcom,bus-min = <4>; + qcom,bus-max = <7>; + }; + + /* Low SVS */ + qcom,gpu-pwrlevel@6 { + reg = <6>; + qcom,gpu-freq = <240000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <3>; + qcom,bus-max = <5>; + }; + + /* Min SVS */ + qcom,gpu-pwrlevel@7 { + reg = <7>; + qcom,gpu-freq = <160000000>; + qcom,bus-freq = <3>; + qcom,bus-min = <2>; + qcom,bus-max = <4>; + }; + + /* XO */ + qcom,gpu-pwrlevel@8 { + reg = <8>; + qcom,gpu-freq = <19200000>; + qcom,bus-freq = <0>; + qcom,bus-min = <0>; + qcom,bus-max = <0>; + }; + }; + }; + + kgsl_msm_iommu: qcom,kgsl-iommu { + compatible = "qcom,kgsl-smmu-v2"; + + reg = <0x05040000 0x10000>; + qcom,protect = <0x40000 0x10000>; + qcom,micro-mmu-control = <0x6000>; + + clocks = <&clock_gcc GCC_GPU_CFG_AHB_CLK>, + <&clock_gcc GCC_GPU_BIMC_GFX_CLK>, + <&clock_gcc GCC_BIMC_GFX_CLK>; + + clock-names = "iface_clk", "mem_clk", "alt_mem_iface_clk"; + + qcom,secure_align_mask = <0xfff>; + qcom,retention; + qcom,hyp_secure_alloc; + + gfx3d_user: gfx3d_user { + compatible = "qcom,smmu-kgsl-cb"; + label = "gfx3d_user"; + iommus = <&kgsl_smmu 0>; + qcom,gpu-offset = <0x48000>; + }; + + gfx3d_secure: gfx3d_secure { + compatible = "qcom,smmu-kgsl-cb"; + iommus = <&kgsl_smmu 2>; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi index 6779d80d76cf..59afb993fb83 100644 --- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi @@ -20,5 +20,85 @@ pinctrl-0 = <&uart_console_active>; }; +&ufsphy1 { + vdda-phy-supply = <&pm660l_l1>; + vdda-pll-supply = <&pm660_l10>; + vddp-ref-clk-supply = <&pm660_l1>; + vdda-phy-max-microamp = <51400>; + vdda-pll-max-microamp = <14200>; + vddp-ref-clk-max-microamp = <100>; + vddp-ref-clk-always-on; + status = "ok"; +}; + +&ufs1 { + vdd-hba-supply = <&gdsc_ufs>; + vdd-hba-fixed-regulator; + vcc-supply = <&pm660l_l4>; + vccq2-supply = <&pm660_l8>; + vcc-max-microamp = <500000>; + vccq2-max-microamp = <600000>; + status = "ok"; +}; + +&sdhc_1 { + /* device core power supply */ + vdd-supply = <&pm660l_l4>; + qcom,vdd-voltage-level = <2950000 2950000>; + qcom,vdd-current-level = <200 570000>; + + /* device communication power supply */ + vdd-io-supply = <&pm660_l8>; + qcom,vdd-io-always-on; + qcom,vdd-io-lpm-sup; + qcom,vdd-io-voltage-level = <1800000 1800000>; + qcom,vdd-io-current-level = <200 325000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>; + pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 + 384000000>; + + qcom,nonremovable; + qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v"; + + status = "ok"; +}; + +&sdhc_2 { + /* device core power supply */ + vdd-supply = <&pm660l_l5>; + qcom,vdd-voltage-level = <2950000 2950000>; + qcom,vdd-current-level = <15000 800000>; + + /* device communication power supply */ + vdd-io-supply = <&pm660l_l2>; + qcom,vdd-io-voltage-level = <1800000 2950000>; + qcom,vdd-io-current-level = <200 22000>; + + pinctrl-names = "active", "sleep"; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>; + + #address-cells = <0>; + interrupt-parent = <&sdhc_2>; + interrupts = <0 1 2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xffffffff>; + interrupt-map = <0 &intc 0 0 125 0 + 1 &intc 0 0 221 0 + 2 &tlmm 54 0>; + interrupt-names = "hc_irq", "pwr_irq", "status_irq"; + cd-gpios = <&tlmm 54 0x1>; + + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 + 200000000>; + qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; + + status = "ok"; +}; + &soc { }; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 15b62afc0347..302a9a197128 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -1247,7 +1247,7 @@ dcc: dcc@10b3000 { compatible = "qcom,dcc"; reg = <0x10b3000 0x1000>, - <0x10b4000 0x800>; + <0x10b4000 0x2000>; reg-names = "dcc-base", "dcc-ram-base"; clocks = <&clock_gcc GCC_DCC_AHB_CLK>; @@ -1913,6 +1913,7 @@ #include "msm-arm-smmu-630.dtsi" #include "msm-audio.dtsi" #include "sdm660-audio.dtsi" +#include "sdm630-gpu.dtsi" #include "sdm660-camera.dtsi" #include "sdm630-pm.dtsi" #include "sdm660-vidc.dtsi" diff --git a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi index 431da5036a4b..dce86a7ceec3 100644 --- a/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-coresight.dtsi @@ -25,6 +25,7 @@ arm,buffer-size = <0x400000>; arm,sg-enable; + arm,default-sink; coresight-ctis = <&cti0 &cti8>; diff --git a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi index ec79dd63e4d2..32ffde6eca24 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi @@ -494,7 +494,7 @@ qcom,aux-cfg-settings = [00 13 00 00 0a 28 0a 03 b7 03]; qcom,logical2physical-lane-map = [00 01 02 03]; qcom,phy-register-offset = <0x4>; - qcom,max-pclk-frequency-khz = <593470>; + qcom,max-pclk-frequency-khz = <300000>; qcom,core-supply-entries { #address-cells = <1>; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 6077699ebea9..4d8a72fea6a8 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1614,7 +1614,7 @@ dcc: dcc@10b3000 { compatible = "qcom,dcc"; reg = <0x10b3000 0x1000>, - <0x10b4000 0x800>; + <0x10b4000 0x2000>; reg-names = "dcc-base", "dcc-ram-base"; clocks = <&clock_gcc GCC_DCC_AHB_CLK>; diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig index 013bada10783..73c12f90016c 100644 --- a/arch/arm/configs/sdm660-perf_defconfig +++ b/arch/arm/configs/sdm660-perf_defconfig @@ -498,6 +498,7 @@ CONFIG_MSM_MMCC_660=y CONFIG_CLOCK_CPU_OSM=y CONFIG_QCOM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y CONFIG_ARM_SMMU=y CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig index 22da2099accc..5c8dbe8e8302 100644 --- a/arch/arm/configs/sdm660_defconfig +++ b/arch/arm/configs/sdm660_defconfig @@ -499,6 +499,8 @@ CONFIG_MSM_MMCC_660=y CONFIG_CLOCK_CPU_OSM=y CONFIG_QCOM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_IOMMU_IO_PGTABLE_FAST=y +CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y CONFIG_ARM_SMMU=y CONFIG_IOMMU_DEBUG=y CONFIG_IOMMU_DEBUG_TRACKING=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 2e2d1657e604..012a3aafcf33 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -178,6 +178,9 @@ extern void __cpuc_flush_dcache_area(void *, size_t); * is visible to DMA, or data written by DMA to system memory is * visible to the CPU. */ +extern void __dma_map_area(const void *, size_t, int); +extern void __dma_unmap_area(const void *, size_t, int); + extern void dmac_inv_range(const void *, const void *); extern void dmac_clean_range(const void *, const void *); extern void dmac_flush_range(const void *, const void *); diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h index 4111592f0130..d8a572f9c187 100644 --- a/arch/arm/include/asm/device.h +++ b/arch/arm/include/asm/device.h @@ -7,7 +7,7 @@ #define ASMARM_DEVICE_H struct dev_archdata { - struct dma_map_ops *dma_ops; + const struct dma_map_ops *dma_ops; #ifdef CONFIG_DMABOUNCE struct dmabounce_device_info *dmabounce; #endif diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h index b4e74af0abb7..74643f5b41c4 100644 --- a/arch/arm/include/asm/dma-iommu.h +++ b/arch/arm/include/asm/dma-iommu.h @@ -8,6 +8,7 @@ #include <linux/dma-debug.h> #include <linux/kmemcheck.h> #include <linux/kref.h> +#include <linux/dma-mapping-fast.h> struct dma_iommu_mapping { /* iommu specific data */ @@ -22,6 +23,8 @@ struct dma_iommu_mapping { spinlock_t lock; struct kref kref; + + struct dma_fast_smmu_mapping *fast; }; #ifdef CONFIG_ARM_DMA_USE_IOMMU diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index ccb3aa64640d..05ff03aead43 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -17,14 +17,14 @@ extern struct dma_map_ops arm_dma_ops; extern struct dma_map_ops arm_coherent_dma_ops; -static inline struct dma_map_ops *__generic_dma_ops(struct device *dev) +static inline const struct dma_map_ops *__generic_dma_ops(struct device *dev) { if (dev && dev->archdata.dma_ops) return dev->archdata.dma_ops; return &arm_dma_ops; } -static inline struct dma_map_ops *get_dma_ops(struct device *dev) +static inline const struct dma_map_ops *get_dma_ops(struct device *dev) { if (xen_initial_domain()) return xen_dma_ops; @@ -32,7 +32,8 @@ static inline struct dma_map_ops *get_dma_ops(struct device *dev) return __generic_dma_ops(dev); } -static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops) +static inline void set_dma_ops(struct device *dev, + const struct dma_map_ops *ops) { BUG_ON(!dev); dev->archdata.dma_ops = ops; diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index 1f442995cdbf..7a4893e61866 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -161,6 +161,12 @@ static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { } #define dmac_flush_range __glue(_CACHE,_dma_flush_range) #define dmac_inv_range __glue(_CACHE, _dma_inv_range) #define dmac_clean_range __glue(_CACHE, _dma_clean_range) +#define dmac_map_area __glue(_CACHE, _dma_map_area) +#define dmac_unmap_area __glue(_CACHE, _dma_unmap_area) + +#define __dma_map_area dmac_map_area +#define __dma_unmap_area dmac_unmap_area +#define __dma_flush_range dmac_flush_range #endif #endif diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 330061d3d081..b58d8e0d9ed1 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -29,6 +29,7 @@ #include <linux/sizes.h> #include <linux/cma.h> #include <linux/msm_dma_iommu_mapping.h> +#include <linux/dma-mapping-fast.h> #include <asm/memory.h> #include <asm/highmem.h> @@ -1019,7 +1020,7 @@ static void __dma_page_dev_to_cpu(struct page *page, unsigned long off, int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs) { - struct dma_map_ops *ops = get_dma_ops(dev); + const struct dma_map_ops *ops = get_dma_ops(dev); struct scatterlist *s; int i, j; @@ -1053,7 +1054,7 @@ int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir, struct dma_attrs *attrs) { - struct dma_map_ops *ops = get_dma_ops(dev); + const struct dma_map_ops *ops = get_dma_ops(dev); struct scatterlist *s; int i; @@ -1072,7 +1073,7 @@ void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - struct dma_map_ops *ops = get_dma_ops(dev); + const struct dma_map_ops *ops = get_dma_ops(dev); struct scatterlist *s; int i; @@ -1091,7 +1092,7 @@ void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) { - struct dma_map_ops *ops = get_dma_ops(dev); + const struct dma_map_ops *ops = get_dma_ops(dev); struct scatterlist *s; int i; @@ -1988,7 +1989,7 @@ static void arm_iommu_sync_single_for_device(struct device *dev, __dma_page_cpu_to_dev(page, offset, size, dir); } -struct dma_map_ops iommu_ops = { +const struct dma_map_ops iommu_ops = { .alloc = arm_iommu_alloc_attrs, .free = arm_iommu_free_attrs, .mmap = arm_iommu_mmap_attrs, @@ -2007,7 +2008,7 @@ struct dma_map_ops iommu_ops = { .set_dma_mask = arm_dma_set_mask, }; -struct dma_map_ops iommu_coherent_ops = { +const struct dma_map_ops iommu_coherent_ops = { .alloc = arm_iommu_alloc_attrs, .free = arm_iommu_free_attrs, .mmap = arm_iommu_mmap_attrs, @@ -2166,6 +2167,11 @@ int arm_iommu_attach_device(struct device *dev, { int err; int s1_bypass = 0; + int is_fast = 0; + + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + if (is_fast) + return fast_smmu_attach_device(dev, mapping); err = __arm_iommu_attach_device(dev, mapping); if (err) @@ -2182,6 +2188,7 @@ EXPORT_SYMBOL_GPL(arm_iommu_attach_device); static void __arm_iommu_detach_device(struct device *dev) { struct dma_iommu_mapping *mapping; + int is_fast; mapping = to_dma_iommu_mapping(dev); if (!mapping) { @@ -2191,6 +2198,9 @@ static void __arm_iommu_detach_device(struct device *dev) if (msm_dma_unmap_all_for_dev(dev)) dev_warn(dev, "IOMMU detach with outstanding mappings\n"); + iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast); + if (is_fast) + return fast_smmu_detach_device(dev, mapping); iommu_detach_device(mapping->domain, dev); kref_put(&mapping->kref, release_iommu_mapping); @@ -2226,7 +2236,7 @@ void arm_iommu_detach_device(struct device *dev) } EXPORT_SYMBOL_GPL(arm_iommu_detach_device); -static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) +static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) { return coherent ? &iommu_coherent_ops : &iommu_ops; } @@ -2289,7 +2299,7 @@ static struct dma_map_ops *arm_get_dma_map_ops(bool coherent) void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, struct iommu_ops *iommu, bool coherent) { - struct dma_map_ops *dma_ops; + const struct dma_map_ops *dma_ops; dev->archdata.dma_coherent = coherent; if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) diff --git a/arch/arm/mm/dma.h b/arch/arm/mm/dma.h index 70ea6852f94e..29c54f7d81f3 100644 --- a/arch/arm/mm/dma.h +++ b/arch/arm/mm/dma.h @@ -4,9 +4,6 @@ #include <asm/glue-cache.h> #ifndef MULTI_CACHE -#define dmac_map_area __glue(_CACHE,_dma_map_area) -#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area) - /* * These are private to the dma-mapping API. Do not use directly. * Their sole purpose is to ensure that data held in the cache diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 176bd7fad9a9..03c5bc89b6f5 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -345,6 +345,7 @@ CONFIG_THERMAL_TSENS8974=y CONFIG_THERMAL_QPNP_ADC_TM=y CONFIG_MFD_SPMI_PMIC=y CONFIG_WCD9335_CODEC=y +CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_RPM_SMD=y CONFIG_REGULATOR_QPNP=y @@ -394,7 +395,7 @@ CONFIG_MSM_VIDC_VMEM=y CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_QCOM_KGSL=y -CONFIG_DRM=y +CONFIG_FB=y CONFIG_FB_MSM=y CONFIG_FB_MSM_MDSS=y CONFIG_FB_MSM_MDSS_WRITEBACK=y @@ -518,6 +519,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y @@ -562,6 +564,7 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_FUSE_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_ECRYPT_FS=y CONFIG_ECRYPT_FS_MESSAGING=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index a7d2b895e08c..b4ddd9a2bed5 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -332,6 +332,7 @@ CONFIG_THERMAL_TSENS8974=y CONFIG_THERMAL_QPNP_ADC_TM=y CONFIG_MFD_SPMI_PMIC=y CONFIG_WCD9335_CODEC=y +CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_RPM_SMD=y CONFIG_REGULATOR_QPNP=y @@ -382,7 +383,7 @@ CONFIG_MSM_VIDC_VMEM=y CONFIG_MSM_VIDC_GOVERNORS=y CONFIG_MSM_SDE_ROTATOR=y CONFIG_QCOM_KGSL=y -CONFIG_DRM=y +CONFIG_FB=y CONFIG_FB_MSM=y CONFIG_FB_MSM_MDSS=y CONFIG_FB_MSM_MDSS_WRITEBACK=y @@ -519,6 +520,7 @@ CONFIG_MSM_IPC_ROUTER_MHI_XPRT=y CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y CONFIG_MSM_GLINK_PKT=y CONFIG_MSM_SPM=y +CONFIG_QCOM_SCM=y CONFIG_QCOM_SCM_XPU=y CONFIG_QCOM_WATCHDOG_V2=y CONFIG_QCOM_MEMORY_DUMP_V2=y @@ -568,6 +570,7 @@ CONFIG_EXT4_FS_ICE_ENCRYPTION=y CONFIG_FUSE_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y +CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_ECRYPT_FS=y CONFIG_ECRYPT_FS_MESSAGING=y diff --git a/arch/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig index d0fdb7206d5b..06b4554ec362 100644 --- a/arch/arm64/configs/msmcortex_mediabox_defconfig +++ b/arch/arm64/configs/msmcortex_mediabox_defconfig @@ -225,6 +225,10 @@ CONFIG_BTFM_SLIM_WCN3990=y CONFIG_CFG80211=y CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y CONFIG_RFKILL=y CONFIG_NFC_NQ=y CONFIG_IPC_ROUTER=y @@ -274,6 +278,9 @@ CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_ATH_CARDS=y CONFIG_WIL6210=m +CONFIG_ATH10K=m +CONFIG_ATH10K_TARGET_SNOC=m +CONFIG_ATH10K_SNOC=y CONFIG_CLD_LL_CORE=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y @@ -472,7 +479,6 @@ CONFIG_LEDS_QPNP=y CONFIG_LEDS_QPNP_FLASH_V2=y CONFIG_LEDS_QPNP_WLED=y CONFIG_LEDS_SYSCON=y -CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_CPU=y CONFIG_SWITCH=y diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig index ef8bac8e2947..af8902054b8a 100644 --- a/arch/arm64/configs/sdm660_defconfig +++ b/arch/arm64/configs/sdm660_defconfig @@ -59,6 +59,7 @@ CONFIG_CLEANCACHE=y CONFIG_CMA=y CONFIG_CMA_DEBUGFS=y CONFIG_ZSMALLOC=y +CONFIG_FORCE_ALLOC_FROM_DMA_ZONE=y CONFIG_PROCESS_RECLAIM=y CONFIG_SECCOMP=y CONFIG_ARMV8_DEPRECATED=y diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 152c81ca50ea..87a48268b663 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -840,7 +840,8 @@ static ssize_t firmware_direct_write(struct file *filp, struct kobject *kobj, mutex_lock(&fw_lock); fw = fw_priv->fw; - if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->buf->status)) { + if (!fw || !fw_priv->buf || + test_bit(FW_STATUS_DONE, &fw_priv->buf->status)) { retval = -ENODEV; goto out; } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 0345e977a2d4..88bd6afdeea5 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1981,6 +1981,7 @@ static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan, if (err) goto bail; chan->session[0].dev = me->dev; + chan->session[0].smmu.dev = me->dev; } *session = &chan->session[idx]; diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c index a5e5ad34db16..ab21334d5813 100644 --- a/drivers/crypto/msm/ice.c +++ b/drivers/crypto/msm/ice.c @@ -53,6 +53,8 @@ #define QCOM_SDCC_ICE_DEV "icesdcc" #define QCOM_ICE_TYPE_NAME_LEN 8 #define QCOM_ICE_MAX_BIST_CHECK_COUNT 100 +#define QCOM_ICE_UFS 10 +#define QCOM_ICE_SDCC 20 struct ice_clk_info { struct list_head list; @@ -838,7 +840,7 @@ static int qcom_ice_restore_config(void) return ret; } -static int qcom_ice_restore_key_config(void) +static int qcom_ice_restore_key_config(struct ice_device *ice_dev) { struct scm_desc desc = {0}; int ret = -1; @@ -846,7 +848,12 @@ static int qcom_ice_restore_key_config(void) /* For ice 3, key configuration needs to be restored in case of reset */ desc.arginfo = TZ_OS_KS_RESTORE_KEY_CONFIG_ID_PARAM_ID; - desc.args[0] = 10; /* UFS_ICE */ + + if (!strcmp(ice_dev->ice_instance_type, "sdcc")) + desc.args[0] = QCOM_ICE_SDCC; + + if (!strcmp(ice_dev->ice_instance_type, "ufs")) + desc.args[0] = QCOM_ICE_UFS; ret = scm_call2(TZ_OS_KS_RESTORE_KEY_CONFIG_ID, &desc); @@ -1135,7 +1142,7 @@ static int qcom_ice_finish_power_collapse(struct ice_device *ice_dev) * restore it */ } else if (ICE_REV(ice_dev->ice_hw_version, MAJOR) > 2) { - err = qcom_ice_restore_key_config(); + err = qcom_ice_restore_key_config(ice_dev); if (err) goto out; diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h index 743f5e72d1a8..ceb48282081d 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.h @@ -64,6 +64,18 @@ enum sde_hw_filter { SDE_SCALE_FILTER_MAX }; +enum sde_hw_filter_alpa { + SDE_SCALE_ALPHA_PIXEL_REP, + SDE_SCALE_ALPHA_BIL +}; + +enum sde_hw_filter_yuv { + SDE_SCALE_2D_4X4, + SDE_SCALE_2D_CIR, + SDE_SCALE_1D_SEP, + SDE_SCALE_BIL +}; + struct sde_hw_sharp_cfg { u32 strength; u32 edge_thr; diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index 3ca74926cfac..b3de45302dea 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -60,6 +60,9 @@ #define SDE_PLANE_DIRTY_SHARPEN 0x4 #define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF +#define SDE_QSEED3_DEFAULT_PRELOAD_H 0x4 +#define SDE_QSEED3_DEFAULT_PRELOAD_V 0x3 + /** * enum sde_plane_qos - Different qos configurations for each pipe * @@ -615,6 +618,73 @@ static void _sde_plane_setup_scaler3(struct sde_plane *psde, const struct sde_format *fmt, uint32_t chroma_subsmpl_h, uint32_t chroma_subsmpl_v) { + uint32_t decimated, i; + + if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h || + !chroma_subsmpl_v) { + SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n" + , psde, scale_cfg, fmt, chroma_subsmpl_h, + chroma_subsmpl_v); + return; + } + + memset(scale_cfg, 0, sizeof(*scale_cfg)); + + decimated = DECIMATED_DIMENSION(src_w, + psde->pipe_cfg.horz_decimation); + scale_cfg->phase_step_x[SDE_SSPP_COMP_0] = + mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_w); + decimated = DECIMATED_DIMENSION(src_h, + psde->pipe_cfg.vert_decimation); + scale_cfg->phase_step_y[SDE_SSPP_COMP_0] = + mult_frac((1 << PHASE_STEP_SHIFT), decimated, dst_h); + + + scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2] = + scale_cfg->phase_step_y[SDE_SSPP_COMP_0] / chroma_subsmpl_v; + scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2] = + scale_cfg->phase_step_x[SDE_SSPP_COMP_0] / chroma_subsmpl_h; + + scale_cfg->phase_step_x[SDE_SSPP_COMP_2] = + scale_cfg->phase_step_x[SDE_SSPP_COMP_1_2]; + scale_cfg->phase_step_y[SDE_SSPP_COMP_2] = + scale_cfg->phase_step_y[SDE_SSPP_COMP_1_2]; + + scale_cfg->phase_step_x[SDE_SSPP_COMP_3] = + scale_cfg->phase_step_x[SDE_SSPP_COMP_0]; + scale_cfg->phase_step_y[SDE_SSPP_COMP_3] = + scale_cfg->phase_step_y[SDE_SSPP_COMP_0]; + + for (i = 0; i < SDE_MAX_PLANES; i++) { + scale_cfg->src_width[i] = DECIMATED_DIMENSION(src_w, + psde->pipe_cfg.horz_decimation); + scale_cfg->src_height[i] = DECIMATED_DIMENSION(src_h, + psde->pipe_cfg.vert_decimation); + if (SDE_FORMAT_IS_YUV(fmt)) + scale_cfg->src_width[i] &= ~0x1; + if (i == SDE_SSPP_COMP_1_2 || i == SDE_SSPP_COMP_2) { + scale_cfg->src_width[i] /= chroma_subsmpl_h; + scale_cfg->src_height[i] /= chroma_subsmpl_v; + } + scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H; + scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V; + psde->pixel_ext.num_ext_pxls_top[i] = + scale_cfg->src_height[i]; + psde->pixel_ext.num_ext_pxls_left[i] = + scale_cfg->src_width[i]; + } + if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h) + && (src_w == dst_w)) + return; + + scale_cfg->dst_width = dst_w; + scale_cfg->dst_height = dst_h; + scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL; + scale_cfg->uv_filter_cfg = SDE_SCALE_BIL; + scale_cfg->alpha_filter_cfg = SDE_SCALE_ALPHA_BIL; + scale_cfg->lut_flag = 0; + scale_cfg->blend_cfg = 1; + scale_cfg->enable = 1; } /** @@ -901,6 +971,7 @@ static void _sde_plane_setup_scaler(struct sde_plane *psde, error = _sde_plane_setup_scaler3_lut(psde, pstate); if (error || !psde->pixel_ext_usr) { + memset(pe, 0, sizeof(struct sde_hw_pixel_ext)); /* calculate default config for QSEED3 */ _sde_plane_setup_scaler3(psde, psde->pipe_cfg.src_rect.w, diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c index f936f3c2ebb1..563ce16885b3 100644 --- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c @@ -445,11 +445,11 @@ static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data, struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent); struct i2c_msg msg[1]; + mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1); if (retval < 0) - return retval; - - mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex); + goto exit; retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr); if (retval != PAGE_SELECT_LEN) { diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c index 004f34ecbff8..df5140d23015 100644 --- a/drivers/iommu/dma-mapping-fast.c +++ b/drivers/iommu/dma-mapping-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -17,7 +17,8 @@ #include <linux/vmalloc.h> #include <asm/cacheflush.h> #include <asm/dma-iommu.h> - +#include <linux/slab.h> +#include <linux/vmalloc.h> /* some redundant definitions... :( TODO: move to io-pgtable-fast.h */ #define FAST_PAGE_SHIFT 12 @@ -632,7 +633,7 @@ static void __fast_smmu_mapped_over_stale(struct dma_fast_smmu_mapping *fast, dev_err(fast->dev, "Mapped over stale tlb at %pa\n", &iova); dev_err(fast->dev, "bitmap (failure at idx %lu):\n", bitmap_idx); dev_err(fast->dev, "ptep: %p pmds: %p diff: %lu\n", ptep, - fast->pgtbl_pmds, ptep - fast->pgtbl_pmds); + fast->pgtbl_pmds, bitmap_idx); print_hex_dump(KERN_ERR, "bmap: ", DUMP_PREFIX_ADDRESS, 32, 8, fast->bitmap, fast->bitmap_size, false); } @@ -682,7 +683,7 @@ static const struct dma_map_ops fast_smmu_dma_ops = { * fast_smmu_attach_device function. */ static struct dma_fast_smmu_mapping *__fast_smmu_create_mapping_sized( - dma_addr_t base, size_t size) + dma_addr_t base, u64 size) { struct dma_fast_smmu_mapping *fast; @@ -725,7 +726,7 @@ int fast_smmu_attach_device(struct device *dev, int atomic_domain = 1; struct iommu_domain *domain = mapping->domain; struct iommu_pgtbl_info info; - size_t size = mapping->bits << PAGE_SHIFT; + u64 size = (u64)mapping->bits << PAGE_SHIFT; if (mapping->base + size > (SZ_1G * 4ULL)) return -EINVAL; diff --git a/drivers/iommu/io-pgtable-fast.c b/drivers/iommu/io-pgtable-fast.c index a71fcdbb1899..ba0af42f8df3 100644 --- a/drivers/iommu/io-pgtable-fast.c +++ b/drivers/iommu/io-pgtable-fast.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -20,6 +20,7 @@ #include <linux/types.h> #include <linux/io-pgtable-fast.h> #include <asm/cacheflush.h> +#include <linux/vmalloc.h> #include "io-pgtable.h" @@ -263,11 +264,18 @@ static size_t av8l_fast_unmap(struct io_pgtable_ops *ops, unsigned long iova, return size; } +#if defined(CONFIG_ARM64) +#define FAST_PGDNDX(va) (((va) & 0x7fc0000000) >> 27) +#elif defined(CONFIG_ARM) +#define FAST_PGDNDX(va) (((va) & 0xc0000000) >> 27) +#endif + static phys_addr_t av8l_fast_iova_to_phys(struct io_pgtable_ops *ops, unsigned long iova) { struct av8l_fast_io_pgtable *data = iof_pgtable_ops_to_data(ops); av8l_fast_iopte pte, *pgdp, *pudp, *pmdp; + unsigned long pgd; phys_addr_t phys; const unsigned long pts = AV8L_FAST_PTE_TYPE_SHIFT; const unsigned long ptm = AV8L_FAST_PTE_TYPE_MASK; @@ -277,8 +285,9 @@ static phys_addr_t av8l_fast_iova_to_phys(struct io_pgtable_ops *ops, /* TODO: clean up some of these magic numbers... */ - pgdp = (av8l_fast_iopte *) - (((unsigned long)data->pgd) | ((iova & 0x7fc0000000) >> 27)); + pgd = (unsigned long)data->pgd | FAST_PGDNDX(iova); + pgdp = (av8l_fast_iopte *)pgd; + pte = *pgdp; if (((pte >> pts) & ptm) != ptt) return 0; @@ -464,6 +473,9 @@ av8l_fast_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie) reg |= (64ULL - cfg->ias) << AV8L_FAST_TCR_T0SZ_SHIFT; reg |= AV8L_FAST_TCR_EPD1_FAULT << AV8L_FAST_TCR_EPD1_SHIFT; +#if defined(CONFIG_ARM) + reg |= ARM_32_LPAE_TCR_EAE; +#endif cfg->av8l_fast_cfg.tcr = reg; /* MAIRs */ @@ -549,7 +561,7 @@ static bool av8l_fast_range_has_specific_mapping(struct io_pgtable_ops *ops, const phys_addr_t phys_start, const size_t size) { - unsigned long iova = iova_start; + u64 iova = iova_start; phys_addr_t phys = phys_start; while (iova < (iova_start + size)) { @@ -565,11 +577,12 @@ static bool av8l_fast_range_has_specific_mapping(struct io_pgtable_ops *ops, static int __init av8l_fast_positive_testing(void) { int failed = 0; - unsigned long iova; + u64 iova; struct io_pgtable_ops *ops; struct io_pgtable_cfg cfg; struct av8l_fast_io_pgtable *data; av8l_fast_iopte *pmds; + u64 max = SZ_1G * 4ULL - 1; cfg = (struct io_pgtable_cfg) { .quirks = 0, @@ -589,19 +602,18 @@ static int __init av8l_fast_positive_testing(void) pmds = data->pmds; /* map the entire 4GB VA space with 4K map calls */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_4K) { + for (iova = 0; iova < max; iova += SZ_4K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_4K, IOMMU_READ))) { failed++; continue; } } - if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - SZ_1G * 4UL))) + max))) failed++; /* unmap it all */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_4K) { + for (iova = 0; iova < max; iova += SZ_4K) { if (WARN_ON(ops->unmap(ops, iova, SZ_4K) != SZ_4K)) failed++; } @@ -610,7 +622,7 @@ static int __init av8l_fast_positive_testing(void) av8l_fast_clear_stale_ptes(pmds, false); /* map the entire 4GB VA space with 8K map calls */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_8K) { + for (iova = 0; iova < max; iova += SZ_8K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_8K, IOMMU_READ))) { failed++; continue; @@ -618,11 +630,11 @@ static int __init av8l_fast_positive_testing(void) } if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - SZ_1G * 4UL))) + max))) failed++; /* unmap it all with 8K unmap calls */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_8K) { + for (iova = 0; iova < max; iova += SZ_8K) { if (WARN_ON(ops->unmap(ops, iova, SZ_8K) != SZ_8K)) failed++; } @@ -631,7 +643,7 @@ static int __init av8l_fast_positive_testing(void) av8l_fast_clear_stale_ptes(pmds, false); /* map the entire 4GB VA space with 16K map calls */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_16K) { + for (iova = 0; iova < max; iova += SZ_16K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_16K, IOMMU_READ))) { failed++; continue; @@ -639,11 +651,11 @@ static int __init av8l_fast_positive_testing(void) } if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - SZ_1G * 4UL))) + max))) failed++; /* unmap it all */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_16K) { + for (iova = 0; iova < max; iova += SZ_16K) { if (WARN_ON(ops->unmap(ops, iova, SZ_16K) != SZ_16K)) failed++; } @@ -652,7 +664,7 @@ static int __init av8l_fast_positive_testing(void) av8l_fast_clear_stale_ptes(pmds, false); /* map the entire 4GB VA space with 64K map calls */ - for (iova = 0; iova < SZ_1G * 4UL; iova += SZ_64K) { + for (iova = 0; iova < max; iova += SZ_64K) { if (WARN_ON(ops->map(ops, iova, iova, SZ_64K, IOMMU_READ))) { failed++; continue; @@ -660,11 +672,11 @@ static int __init av8l_fast_positive_testing(void) } if (WARN_ON(!av8l_fast_range_has_specific_mapping(ops, 0, 0, - SZ_1G * 4UL))) + max))) failed++; /* unmap it all at once */ - if (WARN_ON(ops->unmap(ops, 0, SZ_1G * 4UL) != SZ_1G * 4UL)) + if (WARN_ON(ops->unmap(ops, 0, max) != max)) failed++; free_io_pgtable_ops(ops); diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index 937ce3f6279c..75fcde6e2c20 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -839,7 +839,7 @@ static int iommu_debug_profiling_fast_dma_api_show(struct seq_file *s, if (!virt) goto out; - mapping = arm_iommu_create_mapping(&platform_bus_type, 0, SZ_1G * 4UL); + mapping = arm_iommu_create_mapping(&platform_bus_type, 0, SZ_1G * 4ULL); if (!mapping) { seq_puts(s, "fast_smmu_create_mapping failed\n"); goto out_kfree; @@ -939,8 +939,8 @@ static const struct file_operations iommu_debug_profiling_fast_dma_api_fops = { static int __tlb_stress_sweep(struct device *dev, struct seq_file *s) { int i, ret = 0; - unsigned long iova; - const unsigned long max = SZ_1G * 4UL; + u64 iova; + const u64 max = SZ_1G * 4ULL - 1; void *virt; phys_addr_t phys; dma_addr_t dma_addr; @@ -1012,8 +1012,8 @@ static int __tlb_stress_sweep(struct device *dev, struct seq_file *s) } /* we're all full again. unmap everything. */ - for (dma_addr = 0; dma_addr < max; dma_addr += SZ_8K) - dma_unmap_single(dev, dma_addr, SZ_8K, DMA_TO_DEVICE); + for (iova = 0; iova < max; iova += SZ_8K) + dma_unmap_single(dev, (dma_addr_t)iova, SZ_8K, DMA_TO_DEVICE); out: free_pages((unsigned long)virt, get_order(SZ_8K)); @@ -1046,7 +1046,7 @@ static int __rand_va_sweep(struct device *dev, struct seq_file *s, const size_t size) { u64 iova; - const unsigned long max = SZ_1G * 4UL; + const u64 max = SZ_1G * 4ULL - 1; int i, remapped, unmapped, ret = 0; void *virt; dma_addr_t dma_addr, dma_addr2; @@ -1078,9 +1078,9 @@ static int __rand_va_sweep(struct device *dev, struct seq_file *s, fib_init(&fib); for (iova = get_next_fib(&fib) * size; iova < max - size; - iova = get_next_fib(&fib) * size) { - dma_addr = iova; - dma_addr2 = max - size - iova; + iova = (u64)get_next_fib(&fib) * size) { + dma_addr = (dma_addr_t)(iova); + dma_addr2 = (dma_addr_t)((max + 1) - size - iova); if (dma_addr == dma_addr2) { WARN(1, "%s test needs update! The random number sequence is folding in on itself and should be changed.\n", @@ -1106,8 +1106,8 @@ static int __rand_va_sweep(struct device *dev, struct seq_file *s, ret = -EINVAL; } - for (dma_addr = 0; dma_addr < max; dma_addr += size) - dma_unmap_single(dev, dma_addr, size, DMA_TO_DEVICE); + for (iova = 0; iova < max; iova += size) + dma_unmap_single(dev, (dma_addr_t)iova, size, DMA_TO_DEVICE); out: free_pages((unsigned long)virt, get_order(size)); @@ -1135,10 +1135,11 @@ static int __check_mapping(struct device *dev, struct iommu_domain *domain, static int __full_va_sweep(struct device *dev, struct seq_file *s, const size_t size, struct iommu_domain *domain) { - unsigned long iova; + u64 iova; dma_addr_t dma_addr; void *virt; phys_addr_t phys; + const u64 max = SZ_1G * 4ULL - 1; int ret = 0, i; virt = (void *)__get_free_pages(GFP_KERNEL, get_order(size)); @@ -1153,7 +1154,7 @@ static int __full_va_sweep(struct device *dev, struct seq_file *s, } phys = virt_to_phys(virt); - for (iova = 0, i = 0; iova < SZ_1G * 4UL; iova += size, ++i) { + for (iova = 0, i = 0; iova < max; iova += size, ++i) { unsigned long expected = iova; dma_addr = dma_map_single(dev, virt, size, DMA_TO_DEVICE); @@ -1201,8 +1202,8 @@ static int __full_va_sweep(struct device *dev, struct seq_file *s, } out: - for (dma_addr = 0; dma_addr < SZ_1G * 4UL; dma_addr += size) - dma_unmap_single(dev, dma_addr, size, DMA_TO_DEVICE); + for (iova = 0; iova < max; iova += size) + dma_unmap_single(dev, (dma_addr_t)iova, size, DMA_TO_DEVICE); free_pages((unsigned long)virt, get_order(size)); return ret; @@ -1391,7 +1392,8 @@ static int __apply_to_new_mapping(struct seq_file *s, int ret = -EINVAL, fast = 1; phys_addr_t pt_phys; - mapping = arm_iommu_create_mapping(&platform_bus_type, 0, SZ_1G * 4UL); + mapping = arm_iommu_create_mapping(&platform_bus_type, 0, + (SZ_1G * 4ULL)); if (!mapping) goto out; @@ -1460,7 +1462,9 @@ static int iommu_debug_functional_arm_dma_api_show(struct seq_file *s, size_t sizes[] = {SZ_4K, SZ_64K, SZ_2M, SZ_1M * 12, 0}; int ret = -EINVAL; - mapping = arm_iommu_create_mapping(&platform_bus_type, 0, SZ_1G * 4UL); + /* Make the size equal to MAX_ULONG */ + mapping = arm_iommu_create_mapping(&platform_bus_type, 0, + (SZ_1G * 4ULL - 1)); if (!mapping) goto out; diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c index 08809a93d4b2..54d395d5e78d 100644 --- a/drivers/leds/leds-qpnp-flash-v2.c +++ b/drivers/leds/leds-qpnp-flash-v2.c @@ -1076,6 +1076,8 @@ static int qpnp_flash_led_switch_set(struct flash_switch_data *snode, bool on) pr_err("trigger lmh mitigation failed, rc=%d\n", rc); return rc; } + /* Wait for LMH mitigation to take effect */ + udelay(500); } if (led->trigger_chgr) { 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 09de276e8418..df9691be0c28 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 @@ -1746,11 +1746,38 @@ void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev) static int msm_isp_process_iommu_page_fault(struct vfe_device *vfe_dev) { int rc = vfe_dev->buf_mgr->pagefault_debug_disable; + uint32_t irq_status0, irq_status1; + uint32_t overflow_mask; + unsigned long irq_flags; - pr_err("%s:%d] VFE%d Handle Page fault!\n", __func__, - __LINE__, vfe_dev->pdev->id); - - msm_isp_halt_send_error(vfe_dev, ISP_EVENT_IOMMU_P_FAULT); + /* Check if any overflow bit is set */ + vfe_dev->hw_info->vfe_ops.core_ops. + get_overflow_mask(&overflow_mask); + vfe_dev->hw_info->vfe_ops.irq_ops. + read_irq_status(vfe_dev, &irq_status0, &irq_status1); + overflow_mask &= irq_status1; + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + if (overflow_mask || + atomic_read(&vfe_dev->error_info.overflow_state) != + NO_OVERFLOW) { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + pr_err_ratelimited("%s: overflow detected during IOMMU\n", + __func__); + /* Don't treat the Overflow + Page fault scenario as fatal. + * Instead try to do a recovery. Using an existing event as + * as opposed to creating a new event. + */ + msm_isp_halt_send_error(vfe_dev, ISP_EVENT_PING_PONG_MISMATCH); + } else { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %pK\n", + __func__, __LINE__, vfe_dev->pdev->id, vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0); + msm_isp_halt_send_error(vfe_dev, ISP_EVENT_IOMMU_P_FAULT); + } if (vfe_dev->buf_mgr->pagefault_debug_disable == 0) { vfe_dev->buf_mgr->pagefault_debug_disable = 1; @@ -1859,6 +1886,7 @@ int msm_isp_process_overflow_irq( vfe_dev->recovery_irq1_mask = vfe_dev->irq1_mask; vfe_dev->hw_info->vfe_ops.core_ops. set_halt_restart_mask(vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0); /* mask off other vfe if dual vfe is used */ if (vfe_dev->is_split) { int other_vfe_id; @@ -1875,6 +1903,7 @@ int msm_isp_process_overflow_irq( temp_vfe->recovery_irq1_mask = temp_vfe->irq1_mask; temp_vfe->hw_info->vfe_ops.core_ops. set_halt_restart_mask(temp_vfe); + temp_vfe->hw_info->vfe_ops.axi_ops.halt(temp_vfe, 0); } /* reset irq status so skip further process */ @@ -2143,7 +2172,8 @@ static void msm_vfe_iommu_fault_handler(struct iommu_domain *domain, if (vfe_dev->vfe_open_cnt > 0) { atomic_set(&vfe_dev->error_info.overflow_state, HALT_ENFORCED); - pr_err("%s: fault address is %lx\n", __func__, iova); + pr_err_ratelimited("%s: fault address is %lx\n", + __func__, iova); msm_isp_process_iommu_page_fault(vfe_dev); } else { pr_err("%s: no handling, vfe open cnt = %d\n", diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 1cf2c54aa8b8..7885149440f9 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1770,6 +1770,17 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) goto end; } + for (i = 0; i < queue_len; i++) { + processed_frame[i] = cpp_timer.data.processed_frame[i]; + if (!processed_frame[i]) { + pr_warn("process frame null , queue len %d", queue_len); + msm_cpp_flush_queue_and_release_buffer(cpp_dev, + queue_len); + msm_cpp_set_micro_irq_mask(cpp_dev, 1, 0x8); + goto end; + } + } + atomic_set(&cpp_timer.used, 1); pr_warn("Starting timer to fire in %d ms. (jiffies=%lu)\n", CPP_CMD_TIMEOUT_MS, jiffies); @@ -1778,9 +1789,6 @@ static void msm_cpp_do_timeout_work(struct work_struct *work) msm_cpp_set_micro_irq_mask(cpp_dev, 1, 0x8); - for (i = 0; i < MAX_CPP_PROCESSING_FRAME; i++) - processed_frame[i] = cpp_timer.data.processed_frame[i]; - for (i = 0; i < queue_len; i++) { pr_warn("Rescheduling for identity=0x%x, frame_id=%03d\n", processed_frame[i]->identity, diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index 39811aa84e8e..cd48f871eb79 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -528,6 +528,12 @@ static int32_t msm_actuator_piezo_move_focus( return -EFAULT; } + if (dest_step_position > a_ctrl->total_steps) { + pr_err("Step pos greater than total steps = %d\n", + dest_step_position); + return -EFAULT; + } + a_ctrl->i2c_tbl_index = 0; a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, (num_steps * diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c index 44c5c08f074c..c9dfb52861bc 100644 --- a/drivers/media/platform/msm/vidc/msm_smem.c +++ b/drivers/media/platform/msm/vidc/msm_smem.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 @@ -75,6 +75,14 @@ static int get_device_address(struct smem_client *smem_client, goto mem_map_failed; } + /* Check if the dmabuf size matches expected size */ + if (buf->size < *buffer_size) { + rc = -EINVAL; + dprintk(VIDC_ERR, + "Size mismatch! Dmabuf size: %zu Expected Size: %lu", + buf->size, *buffer_size); + goto mem_buf_size_mismatch; + } /* Prepare a dma buf for dma on the given device */ attach = dma_buf_attach(buf, cb->dev); if (IS_ERR_OR_NULL(attach)) { @@ -143,6 +151,7 @@ mem_map_sg_failed: dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL); mem_map_table_failed: dma_buf_detach(buf, attach); +mem_buf_size_mismatch: mem_buf_attach_failed: dma_buf_put(buf); mem_map_failed: @@ -193,12 +202,12 @@ static void put_device_address(struct smem_client *smem_client, } } -static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, +static int ion_user_to_kernel(struct smem_client *client, int fd, u32 size, struct msm_smem *mem, enum hal_buffer buffer_type) { struct ion_handle *hndl; ion_phys_addr_t iova = 0; - unsigned long buffer_size = 0; + unsigned long buffer_size = size; int rc = 0; unsigned long align = SZ_4K; unsigned long ion_flags = 0; @@ -207,10 +216,11 @@ static int ion_user_to_kernel(struct smem_client *client, int fd, u32 offset, dprintk(VIDC_DBG, "%s ion handle: %pK\n", __func__, hndl); if (IS_ERR_OR_NULL(hndl)) { dprintk(VIDC_ERR, "Failed to get handle: %pK, %d, %d, %pK\n", - client, fd, offset, hndl); + client, fd, size, hndl); rc = -ENOMEM; goto fail_import_fd; } + mem->kvaddr = NULL; rc = ion_handle_get_flags(client->clnt, hndl, &ion_flags); if (rc) { @@ -430,7 +440,7 @@ static void ion_delete_client(struct smem_client *client) ion_client_destroy(client->clnt); } -struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, +struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 size, enum hal_buffer buffer_type) { struct smem_client *client = clt; @@ -447,7 +457,7 @@ struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, } switch (client->mem_type) { case SMEM_ION: - rc = ion_user_to_kernel(clt, fd, offset, mem, buffer_type); + rc = ion_user_to_kernel(clt, fd, size, mem, buffer_type); break; default: dprintk(VIDC_ERR, "Mem type not supported\n"); diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index a20252f08f44..b7e2c297a1ad 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -704,7 +704,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "YCbCr Semiplanar 4:2:0", .description = "Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12, - .num_planes = 2, .get_frame_size = get_frame_size_nv12, .type = CAPTURE_PORT, }, @@ -712,7 +711,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "UBWC YCbCr Semiplanar 4:2:0", .description = "UBWC Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12_UBWC, - .num_planes = 2, .get_frame_size = get_frame_size_nv12_ubwc, .type = CAPTURE_PORT, }, @@ -720,7 +718,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "UBWC YCbCr Semiplanar 4:2:0 10bit", .description = "UBWC Y/CbCr 4:2:0 10bit", .fourcc = V4L2_PIX_FMT_NV12_TP10_UBWC, - .num_planes = 2, .get_frame_size = get_frame_size_nv12_ubwc_10bit, .type = CAPTURE_PORT, }, @@ -728,7 +725,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "Mpeg4", .description = "Mpeg4 compressed format", .fourcc = V4L2_PIX_FMT_MPEG4, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -736,7 +732,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "Mpeg2", .description = "Mpeg2 compressed format", .fourcc = V4L2_PIX_FMT_MPEG2, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -744,7 +739,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "H263", .description = "H263 compressed format", .fourcc = V4L2_PIX_FMT_H263, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -752,7 +746,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "VC1", .description = "VC-1 compressed format", .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -760,7 +753,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "VC1 SP", .description = "VC-1 compressed format G", .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -768,7 +760,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "H264", .description = "H264 compressed format", .fourcc = V4L2_PIX_FMT_H264, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -776,7 +767,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "H264_MVC", .description = "H264_MVC compressed format", .fourcc = V4L2_PIX_FMT_H264_MVC, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -784,7 +774,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "HEVC", .description = "HEVC compressed format", .fourcc = V4L2_PIX_FMT_HEVC, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -792,7 +781,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "HEVC_HYBRID", .description = "HEVC compressed format", .fourcc = V4L2_PIX_FMT_HEVC_HYBRID, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -800,7 +788,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "VP8", .description = "VP8 compressed format", .fourcc = V4L2_PIX_FMT_VP8, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -808,7 +795,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "VP9", .description = "VP9 compressed format", .fourcc = V4L2_PIX_FMT_VP9, - .num_planes = 1, .get_frame_size = get_frame_size_compressed_full_yuv, .type = OUTPUT_PORT, }, @@ -816,7 +802,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "DIVX 311", .description = "DIVX 311 compressed format", .fourcc = V4L2_PIX_FMT_DIVX_311, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, }, @@ -824,7 +809,6 @@ struct msm_vidc_format vdec_formats[] = { .name = "DIVX", .description = "DIVX 4/5/6 compressed format", .fourcc = V4L2_PIX_FMT_DIVX, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = OUTPUT_PORT, } @@ -896,10 +880,10 @@ int msm_vdec_prepare_buf(struct msm_vidc_inst *inst, case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (b->length != inst->fmts[CAPTURE_PORT].num_planes) { + if (b->length != inst->prop.num_planes[CAPTURE_PORT]) { dprintk(VIDC_ERR, "Planes mismatch: needed: %d, allocated: %d\n", - inst->fmts[CAPTURE_PORT].num_planes, + inst->prop.num_planes[CAPTURE_PORT], b->length); rc = -EINVAL; break; @@ -975,10 +959,10 @@ int msm_vdec_release_buf(struct msm_vidc_inst *inst, case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (b->length != inst->fmts[CAPTURE_PORT].num_planes) { + if (b->length != inst->prop.num_planes[CAPTURE_PORT]) { dprintk(VIDC_ERR, "Planes mismatch: needed: %d, to release: %d\n", - inst->fmts[CAPTURE_PORT].num_planes, b->length); + inst->prop.num_planes[CAPTURE_PORT], b->length); rc = -EINVAL; break; } @@ -1090,6 +1074,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) struct hfi_device *hdev; int rc = 0, i = 0, stride = 0, scanlines = 0, color_format = 0; unsigned int *plane_sizes = NULL, extra_idx = 0; + int num_planes = 0; if (!inst || !f || !inst->core || !inst->core->device) { dprintk(VIDC_ERR, @@ -1106,7 +1091,9 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) return -ENOTSUPP; f->fmt.pix_mp.pixelformat = fmt->fourcc; - f->fmt.pix_mp.num_planes = fmt->num_planes; + f->fmt.pix_mp.num_planes = inst->prop.num_planes[fmt->type]; + num_planes = inst->prop.num_planes[fmt->type]; + if (inst->in_reconfig) { inst->prop.height[OUTPUT_PORT] = inst->reconfig_height; inst->prop.width[OUTPUT_PORT] = inst->reconfig_width; @@ -1126,7 +1113,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { plane_sizes = &inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[0]; - for (i = 0; i < fmt->num_planes; ++i) { + for (i = 0; i < num_planes; ++i) { if (!plane_sizes[i]) { f->fmt.pix_mp.plane_fmt[i].sizeimage = get_frame_size(inst, fmt, f->type, i); @@ -1169,7 +1156,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->prop.height[CAPTURE_PORT], inst->prop.width[CAPTURE_PORT]); - extra_idx = EXTRADATA_IDX(fmt->num_planes); + extra_idx = EXTRADATA_IDX(num_planes); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { f->fmt.pix_mp.plane_fmt[extra_idx].sizeimage = VENUS_EXTRADATA_SIZE( @@ -1177,7 +1164,7 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->prop.width[CAPTURE_PORT]); } - for (i = 0; i < fmt->num_planes; ++i) + for (i = 0; i < num_planes; ++i) inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage; @@ -1276,7 +1263,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->fmts[fmt->type].get_frame_size(0, f->fmt.pix_mp.height, f->fmt.pix_mp.width); - extra_idx = EXTRADATA_IDX(inst->fmts[fmt->type].num_planes); + extra_idx = EXTRADATA_IDX(inst->prop.num_planes[fmt->type]); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { f->fmt.pix_mp.plane_fmt[extra_idx].sizeimage = VENUS_EXTRADATA_SIZE( @@ -1284,8 +1271,8 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->prop.width[CAPTURE_PORT]); } - f->fmt.pix_mp.num_planes = inst->fmts[fmt->type].num_planes; - for (i = 0; i < inst->fmts[fmt->type].num_planes; ++i) { + f->fmt.pix_mp.num_planes = inst->prop.num_planes[fmt->type]; + for (i = 0; i < inst->prop.num_planes[fmt->type]; ++i) { inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage; } @@ -1346,14 +1333,14 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) msm_comm_try_set_prop(inst, HAL_PARAM_FRAME_SIZE, &frame_sz); max_input_size = get_frame_size( -inst, &inst->fmts[fmt->type], f->type, 0); + inst, &inst->fmts[fmt->type], f->type, 0); if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size || !f->fmt.pix_mp.plane_fmt[0].sizeimage) { f->fmt.pix_mp.plane_fmt[0].sizeimage = max_input_size; } - f->fmt.pix_mp.num_planes = inst->fmts[fmt->type].num_planes; - for (i = 0; i < inst->fmts[fmt->type].num_planes; ++i) { + f->fmt.pix_mp.num_planes = inst->prop.num_planes[fmt->type]; + for (i = 0; i < inst->prop.num_planes[fmt->type]; ++i) { inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage; } @@ -1467,7 +1454,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, switch (q->type) { case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - *num_planes = inst->fmts[OUTPUT_PORT].num_planes; + *num_planes = inst->prop.num_planes[OUTPUT_PORT]; if (*num_buffers < MIN_NUM_OUTPUT_BUFFERS || *num_buffers > MAX_NUM_OUTPUT_BUFFERS) *num_buffers = MIN_NUM_OUTPUT_BUFFERS; @@ -1480,7 +1467,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n"); - *num_planes = inst->fmts[CAPTURE_PORT].num_planes; + *num_planes = inst->prop.num_planes[CAPTURE_PORT]; rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); if (rc) { dprintk(VIDC_ERR, "Failed to open instance\n"); @@ -1564,8 +1551,7 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, break; } - extra_idx = - EXTRADATA_IDX(inst->fmts[CAPTURE_PORT].num_planes); + extra_idx = EXTRADATA_IDX(*num_planes); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { sizes[extra_idx] = VENUS_EXTRADATA_SIZE( @@ -1944,8 +1930,14 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) } inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; + inst->prop.num_planes[CAPTURE_PORT] = 2; + inst->fmts[CAPTURE_PORT] = vdec_formats[0]; + inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH; + inst->prop.num_planes[OUTPUT_PORT] = 1; + inst->fmts[OUTPUT_PORT] = vdec_formats[2]; + inst->capability.height.min = MIN_SUPPORTED_HEIGHT; inst->capability.height.max = DEFAULT_HEIGHT; inst->capability.width.min = MIN_SUPPORTED_WIDTH; @@ -1958,10 +1950,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->buffer_mode_set[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC; inst->prop.fps = DEFAULT_FPS; inst->operating_rate = 0; - memcpy(&inst->fmts[OUTPUT_PORT], &vdec_formats[2], - sizeof(struct msm_vidc_format)); - memcpy(&inst->fmts[CAPTURE_PORT], &vdec_formats[0], - sizeof(struct msm_vidc_format)); return rc; } diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index c909511db251..ce6736509d61 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -1343,7 +1343,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "YCbCr Semiplanar 4:2:0", .description = "Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12, - .num_planes = 1, .get_frame_size = get_frame_size_nv12, .type = OUTPUT_PORT, }, @@ -1351,7 +1350,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "UBWC YCbCr Semiplanar 4:2:0", .description = "UBWC Y/CbCr 4:2:0", .fourcc = V4L2_PIX_FMT_NV12_UBWC, - .num_planes = 1, .get_frame_size = get_frame_size_nv12_ubwc, .type = OUTPUT_PORT, }, @@ -1359,7 +1357,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "RGBA 8:8:8:8", .description = "RGBA 8:8:8:8", .fourcc = V4L2_PIX_FMT_RGB32, - .num_planes = 1, .get_frame_size = get_frame_size_rgba, .type = OUTPUT_PORT, }, @@ -1367,7 +1364,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "UBWC RGBA 8:8:8:8", .description = "UBWC RGBA 8:8:8:8", .fourcc = V4L2_PIX_FMT_RGBA8888_UBWC, - .num_planes = 1, .get_frame_size = get_frame_size_rgba_ubwc, .type = OUTPUT_PORT, }, @@ -1375,7 +1371,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "Mpeg4", .description = "Mpeg4 compressed format", .fourcc = V4L2_PIX_FMT_MPEG4, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, }, @@ -1383,7 +1378,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "H263", .description = "H263 compressed format", .fourcc = V4L2_PIX_FMT_H263, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, }, @@ -1391,7 +1385,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "H264", .description = "H264 compressed format", .fourcc = V4L2_PIX_FMT_H264, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, }, @@ -1399,7 +1392,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "VP8", .description = "VP8 compressed format", .fourcc = V4L2_PIX_FMT_VP8, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, }, @@ -1407,7 +1399,6 @@ static struct msm_vidc_format venc_formats[] = { .name = "HEVC", .description = "HEVC compressed format", .fourcc = V4L2_PIX_FMT_HEVC, - .num_planes = 1, .get_frame_size = get_frame_size_compressed, .type = CAPTURE_PORT, }, @@ -1415,57 +1406,71 @@ static struct msm_vidc_format venc_formats[] = { .name = "YCrCb Semiplanar 4:2:0", .description = "Y/CrCb 4:2:0", .fourcc = V4L2_PIX_FMT_NV21, - .num_planes = 1, .get_frame_size = get_frame_size_nv21, .type = OUTPUT_PORT, }, }; -static void msm_venc_update_plane_count(struct msm_vidc_inst *inst, int type) +static int msm_venc_set_csc(struct msm_vidc_inst *inst) { - struct v4l2_ctrl *ctrl = NULL; - u32 extradata = 0; + int rc = 0; + int count = 0; + struct hal_vpe_color_space_conversion vpe_csc; - if (!inst) - return; + while (count < HAL_MAX_MATRIX_COEFFS) { + if (count < HAL_MAX_BIAS_COEFFS) + vpe_csc.csc_bias[count] = + vpe_csc_601_to_709_bias_coeff[count]; + if (count < HAL_MAX_LIMIT_COEFFS) + vpe_csc.csc_limit[count] = + vpe_csc_601_to_709_limit_coeff[count]; + vpe_csc.csc_matrix[count] = + vpe_csc_601_to_709_matrix_coeff[count]; + count = count + 1; + } + rc = msm_comm_try_set_prop(inst, + HAL_PARAM_VPE_COLOR_SPACE_CONVERSION, &vpe_csc); + if (rc) + dprintk(VIDC_ERR, "Setting VPE coefficients failed\n"); - inst->fmts[type].num_planes = 1; + return rc; +} - ctrl = v4l2_ctrl_find(&inst->ctrl_handler, - V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA); +static void msm_venc_register_extradata( + struct msm_vidc_inst *inst, u32 extradata) { + struct session_prop *prop = NULL; - if (ctrl) - extradata = v4l2_ctrl_g_ctrl(ctrl); + if (!inst) + return; - if (type == CAPTURE_PORT) { - switch (extradata) { + prop = &inst->prop; + switch (extradata) { case V4L2_MPEG_VIDC_EXTRADATA_MULTISLICE_INFO: case V4L2_MPEG_VIDC_EXTRADATA_NUM_CONCEALED_MB: case V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER: case V4L2_MPEG_VIDC_EXTRADATA_LTR: case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI: - inst->fmts[CAPTURE_PORT].num_planes = 2; - default: + prop->extradata[CAPTURE_PORT] |= extradata; + prop->num_planes[CAPTURE_PORT] = 2; + dprintk(VIDC_DBG, "Output Extradata: %#x", + prop->extradata[CAPTURE_PORT]); break; - } - } else if (type == OUTPUT_PORT) { - switch (extradata) { case V4L2_MPEG_VIDC_EXTRADATA_INPUT_CROP: case V4L2_MPEG_VIDC_EXTRADATA_DIGITAL_ZOOM: case V4L2_MPEG_VIDC_EXTRADATA_ASPECT_RATIO: case V4L2_MPEG_VIDC_EXTRADATA_YUV_STATS: case V4L2_MPEG_VIDC_EXTRADATA_ROI_QP: case V4L2_MPEG_VIDC_EXTRADATA_PQ_INFO: - inst->fmts[OUTPUT_PORT].num_planes = 2; + prop->extradata[OUTPUT_PORT] |= extradata; + prop->num_planes[OUTPUT_PORT] = 2; + dprintk(VIDC_DBG, "Input Extradata: %#x", + prop->extradata[OUTPUT_PORT]); break; default: - break; - } + dprintk(VIDC_ERR, "Unknown extradata: %d", extradata); } } -static int msm_venc_set_csc(struct msm_vidc_inst *inst); - static int msm_venc_queue_setup(struct vb2_queue *q, const void *parg, unsigned int *num_buffers, @@ -1508,7 +1513,7 @@ static int msm_venc_queue_setup(struct vb2_queue *q, switch (q->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - *num_planes = 1; + *num_planes = inst->prop.num_planes[CAPTURE_PORT]; buff_req = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); if (buff_req) { @@ -1534,9 +1539,6 @@ static int msm_venc_queue_setup(struct vb2_queue *q, temp, *num_buffers); } - msm_venc_update_plane_count(inst, CAPTURE_PORT); - *num_planes = inst->fmts[CAPTURE_PORT].num_planes; - for (i = 0; i < *num_planes; i++) { int extra_idx = EXTRADATA_IDX(*num_planes); @@ -1571,7 +1573,7 @@ static int msm_venc_queue_setup(struct vb2_queue *q, break; case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - *num_planes = 1; + *num_planes = inst->prop.num_planes[OUTPUT_PORT]; *num_buffers = inst->buff_req.buffer[0].buffer_count_actual = max(*num_buffers, inst->buff_req.buffer[0]. @@ -1593,9 +1595,6 @@ static int msm_venc_queue_setup(struct vb2_queue *q, dprintk(VIDC_DBG, "actual input buffer count set to fw = %d\n", *num_buffers); - msm_venc_update_plane_count(inst, OUTPUT_PORT); - *num_planes = inst->fmts[OUTPUT_PORT].num_planes; - rc = call_hfi_op(hdev, session_set_property, inst->session, property_id, &new_buf_count); if (rc) @@ -1610,7 +1609,7 @@ static int msm_venc_queue_setup(struct vb2_queue *q, inst->prop.width[OUTPUT_PORT]); extra_idx = - EXTRADATA_IDX(inst->fmts[OUTPUT_PORT].num_planes); + EXTRADATA_IDX(*num_planes); if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { buff_req_buffer = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); @@ -2992,6 +2991,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) !!(inst->flags & VIDC_SECURE)); break; case V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA: + msm_venc_register_extradata(inst, (u32)ctrl->val); property_id = HAL_PARAM_INDEX_EXTRADATA; extra.index = msm_comm_get_hal_extradata_index(ctrl->val); extra.enable = 1; @@ -3633,8 +3633,14 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) } inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; + inst->prop.num_planes[CAPTURE_PORT] = 1; + inst->fmts[CAPTURE_PORT] = venc_formats[4]; + inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH; + inst->prop.num_planes[OUTPUT_PORT] = 1; + inst->fmts[OUTPUT_PORT] = venc_formats[0]; + inst->capability.height.min = MIN_SUPPORTED_HEIGHT; inst->capability.height.max = DEFAULT_HEIGHT; inst->capability.width.min = MIN_SUPPORTED_WIDTH; @@ -3648,10 +3654,6 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->prop.fps = DEFAULT_FPS; inst->capability.pixelprocess_capabilities = 0; inst->operating_rate = 0; - memcpy(&inst->fmts[CAPTURE_PORT], &venc_formats[4], - sizeof(struct msm_vidc_format)); - memcpy(&inst->fmts[OUTPUT_PORT], &venc_formats[0], - sizeof(struct msm_vidc_format)); return rc; } @@ -3720,37 +3722,13 @@ int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f) return rc; } -static int msm_venc_set_csc(struct msm_vidc_inst *inst) -{ - int rc = 0; - int count = 0; - struct hal_vpe_color_space_conversion vpe_csc; - - while (count < HAL_MAX_MATRIX_COEFFS) { - if (count < HAL_MAX_BIAS_COEFFS) - vpe_csc.csc_bias[count] = - vpe_csc_601_to_709_bias_coeff[count]; - if (count < HAL_MAX_LIMIT_COEFFS) - vpe_csc.csc_limit[count] = - vpe_csc_601_to_709_limit_coeff[count]; - vpe_csc.csc_matrix[count] = - vpe_csc_601_to_709_matrix_coeff[count]; - count = count + 1; - } - rc = msm_comm_try_set_prop(inst, - HAL_PARAM_VPE_COLOR_SPACE_CONVERSION, &vpe_csc); - if (rc) - dprintk(VIDC_ERR, "Setting VPE coefficients failed\n"); - - return rc; -} - int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) { struct msm_vidc_format *fmt = NULL; int rc = 0; - int i; + int extra_idx = 0; struct hfi_device *hdev; + if (!inst || !f) { dprintk(VIDC_ERR, "Invalid input, inst = %pK, format = %pK\n", inst, f); @@ -3777,9 +3755,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) memcpy(&inst->fmts[fmt->type], fmt, sizeof(struct msm_vidc_format)); - - msm_venc_update_plane_count(inst, CAPTURE_PORT); - fmt->num_planes = inst->fmts[CAPTURE_PORT].num_planes; + f->fmt.pix_mp.num_planes = inst->prop.num_planes[CAPTURE_PORT]; rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE); if (rc) { @@ -3833,10 +3809,7 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) } memcpy(&inst->fmts[fmt->type], fmt, sizeof(struct msm_vidc_format)); - - msm_venc_update_plane_count(inst, OUTPUT_PORT); - fmt->num_planes = inst->fmts[OUTPUT_PORT].num_planes; - + f->fmt.pix_mp.num_planes = inst->prop.num_planes[OUTPUT_PORT]; msm_comm_set_color_format(inst, HAL_BUFFER_INPUT, fmt->fourcc); } else { dprintk(VIDC_ERR, "%s - Unsupported buf type: %d\n", @@ -3845,8 +3818,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) goto exit; } - f->fmt.pix_mp.num_planes = fmt->num_planes; - if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { struct hal_frame_size frame_sz = {0}; struct hal_buffer_requirements *bufreq = NULL; @@ -3872,16 +3843,23 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT); f->fmt.pix_mp.plane_fmt[0].sizeimage = bufreq ? bufreq->buffer_size : 0; + + extra_idx = EXTRADATA_IDX(inst->prop.num_planes[fmt->type]); + if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { + bufreq = get_buff_req_buffer(inst, + HAL_BUFFER_EXTRADATA_OUTPUT); + f->fmt.pix_mp.plane_fmt[extra_idx].sizeimage = + bufreq ? bufreq->buffer_size : 0; + } + } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { struct hal_buffer_requirements *bufreq = NULL; - int extra_idx = 0; - for (i = 0; i < inst->fmts[fmt->type].num_planes; ++i) { - f->fmt.pix_mp.plane_fmt[i].sizeimage = - inst->fmts[fmt->type].get_frame_size(i, - f->fmt.pix_mp.height, f->fmt.pix_mp.width); - } - extra_idx = EXTRADATA_IDX(inst->fmts[fmt->type].num_planes); + f->fmt.pix_mp.plane_fmt[0].sizeimage = + inst->fmts[fmt->type].get_frame_size(0, + f->fmt.pix_mp.height, f->fmt.pix_mp.width); + + extra_idx = EXTRADATA_IDX(inst->prop.num_planes[fmt->type]); if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) { bufreq = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_INPUT); @@ -3919,14 +3897,12 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) fmt = &inst->fmts[CAPTURE_PORT]; height = inst->prop.height[CAPTURE_PORT]; width = inst->prop.width[CAPTURE_PORT]; - msm_venc_update_plane_count(inst, CAPTURE_PORT); - num_planes = inst->fmts[CAPTURE_PORT].num_planes; + num_planes = inst->prop.num_planes[CAPTURE_PORT]; } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { fmt = &inst->fmts[OUTPUT_PORT]; height = inst->prop.height[OUTPUT_PORT]; width = inst->prop.width[OUTPUT_PORT]; - msm_venc_update_plane_count(inst, OUTPUT_PORT); - num_planes = inst->fmts[OUTPUT_PORT].num_planes; + num_planes = inst->prop.num_planes[OUTPUT_PORT]; } else { dprintk(VIDC_ERR, "Invalid type: %x\n", f->type); return -ENOTSUPP; @@ -4027,10 +4003,10 @@ int msm_venc_prepare_buf(struct msm_vidc_inst *inst, case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - if (b->length != inst->fmts[CAPTURE_PORT].num_planes) { + if (b->length != inst->prop.num_planes[CAPTURE_PORT]) { dprintk(VIDC_ERR, "Planes mismatch: needed: %d, allocated: %d\n", - inst->fmts[CAPTURE_PORT].num_planes, + inst->prop.num_planes[CAPTURE_PORT], b->length); rc = -EINVAL; break; @@ -4098,10 +4074,10 @@ int msm_venc_release_buf(struct msm_vidc_inst *inst, break; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: { if (b->length != - inst->fmts[CAPTURE_PORT].num_planes) { + inst->prop.num_planes[CAPTURE_PORT]) { dprintk(VIDC_ERR, "Planes mismatch: needed: %d, to release: %d\n", - inst->fmts[CAPTURE_PORT].num_planes, + inst->prop.num_planes[CAPTURE_PORT], b->length); rc = -EINVAL; break; diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 662dcf7c8303..ec3246ed9d67 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -364,7 +364,7 @@ static struct msm_smem *map_buffer(struct msm_vidc_inst *inst, struct msm_smem *handle = NULL; handle = msm_comm_smem_user_to_kernel(inst, p->reserved[0], - p->reserved[1], + p->length, buffer_type); if (!handle) { dprintk(VIDC_ERR, @@ -433,8 +433,10 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) goto exit; } - dprintk(VIDC_DBG, "[MAP] Create binfo = %pK fd = %d type = %d\n", - binfo, b->m.planes[0].reserved[0], b->type); + dprintk(VIDC_DBG, + "[MAP] Create binfo = %pK fd = %d size = %d type = %d\n", + binfo, b->m.planes[0].reserved[0], + b->m.planes[0].length, b->type); for (i = 0; i < b->length; ++i) { rc = 0; @@ -686,7 +688,7 @@ static bool valid_v4l2_buffer(struct v4l2_buffer *b, MAX_PORT_NUM; return port != MAX_PORT_NUM && - inst->fmts[port].num_planes == b->length; + inst->prop.num_planes[port] == b->length; } int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b) @@ -1317,9 +1319,6 @@ static void cleanup_instance(struct msm_vidc_inst *inst) "Failed to release output buffers\n"); } - if (inst->extradata_handle) - msm_comm_smem_free(inst, inst->extradata_handle); - debugfs_remove_recursive(inst->debugfs_root); mutex_lock(&inst->pending_getpropq.lock); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 50ea4a200dfa..1365bec268cf 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -898,12 +898,12 @@ static int wait_for_sess_signal_receipt(struct msm_vidc_inst *inst, if (!rc) { dprintk(VIDC_ERR, "Wait interrupted or timed out: %d\n", SESSION_MSG_INDEX(cmd)); - msm_comm_kill_session(inst); call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "sess resp timeout can potentially crash the system\n"); msm_comm_print_debug_info(inst); BUG_ON(inst->core->resources.debug_timeout); + msm_comm_kill_session(inst); rc = -EIO; } else { rc = 0; @@ -1217,7 +1217,8 @@ static void handle_event_change(enum hal_command_response cmd, void *data) "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT due to bit-depth change\n"); } - if (inst->pic_struct != event_notify->pic_struct) { + if (inst->fmts[CAPTURE_PORT].fourcc == V4L2_PIX_FMT_NV12 && + inst->pic_struct != event_notify->pic_struct) { inst->pic_struct = event_notify->pic_struct; event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT; ptr[2] |= V4L2_EVENT_PICSTRUCT_FLAG; @@ -1693,19 +1694,11 @@ static void handle_sys_error(enum hal_command_response cmd, void *data) dprintk(VIDC_ERR, "SYS_ERROR can potentially crash the system\n"); - /* - * For SYS_ERROR, there will not be any inst pointer. - * Just grab one of the inst from instances list and - * use it. - */ - mutex_lock(&core->lock); - inst = list_first_entry_or_null(&core->instances, - struct msm_vidc_inst, list); + list_for_each_entry(inst, &core->instances, list) + msm_comm_print_inst_info(inst); mutex_unlock(&core->lock); - msm_comm_print_debug_info(inst); - BUG_ON(core->resources.debug_timeout); } @@ -2079,7 +2072,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data) ns_to_timeval(time_usec * NSEC_PER_USEC); vbuf->flags = 0; extra_idx = - EXTRADATA_IDX(inst->fmts[CAPTURE_PORT].num_planes); + EXTRADATA_IDX(inst->prop.num_planes[CAPTURE_PORT]); if (extra_idx && extra_idx < VIDEO_MAX_PLANES) { vb->planes[extra_idx].m.userptr = (unsigned long)fill_buf_done->extra_data_buffer; @@ -3639,7 +3632,7 @@ static void populate_frame_data(struct vidc_frame_data *data, data->buffer_type = msm_comm_get_hal_output_buffer(inst); } - extra_idx = EXTRADATA_IDX(inst->fmts[port].num_planes); + extra_idx = EXTRADATA_IDX(inst->prop.num_planes[port]); if (extra_idx && extra_idx < VIDEO_MAX_PLANES && vb->planes[extra_idx].m.userptr) { data->extradata_addr = vb->planes[extra_idx].m.userptr; @@ -4065,7 +4058,6 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, __func__, inst, SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)); inst->state = MSM_VIDC_CORE_INVALID; - msm_comm_kill_session(inst); call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data); dprintk(VIDC_ERR, "SESS_PROP timeout can potentially crash the system\n"); @@ -4073,6 +4065,7 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, msm_comm_print_debug_info(inst); BUG_ON(inst->core->resources.debug_timeout); + msm_comm_kill_session(inst); rc = -ETIMEDOUT; goto exit; } else { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c index 2e1df75cb248..1248a1c08103 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.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 @@ -290,7 +290,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, write_str(&dbg_buf, "capability: %s\n", i == OUTPUT_PORT ? "Output" : "Capture"); write_str(&dbg_buf, "name : %s\n", inst->fmts[i].name); - write_str(&dbg_buf, "planes : %d\n", inst->fmts[i].num_planes); + write_str(&dbg_buf, "planes : %d\n", inst->prop.num_planes[i]); write_str( &dbg_buf, "type: %s\n", inst->fmts[i].type == OUTPUT_PORT ? "Output" : "Capture"); @@ -311,7 +311,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, write_str(&dbg_buf, "count: %u\n", inst->bufq[i].vb2_bufq.num_buffers); - for (j = 0; j < inst->fmts[i].num_planes; j++) + for (j = 0; j < inst->prop.num_planes[i]; j++) write_str(&dbg_buf, "size for plane %d: %u\n", j, inst->bufq[i].vb2_bufq.plane_sizes[j]); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 3ad85f53a8b0..690a61f4824f 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -143,7 +143,6 @@ struct msm_vidc_format { char name[MAX_NAME_LENGTH]; u8 description[32]; u32 fourcc; - int num_planes; int type; u32 (*get_frame_size)(int plane, u32 height, u32 width); }; @@ -165,6 +164,8 @@ struct msm_video_device { struct session_prop { u32 width[MAX_PORT_NUM]; u32 height[MAX_PORT_NUM]; + u32 num_planes[MAX_PORT_NUM]; + u32 extradata[MAX_PORT_NUM]; u32 fps; u32 bitrate; }; @@ -276,7 +277,6 @@ struct msm_vidc_inst { struct completion completions[SESSION_MSG_END - SESSION_MSG_START + 1]; struct v4l2_ctrl **cluster; struct v4l2_fh event_handler; - struct msm_smem *extradata_handle; bool in_reconfig; u32 reconfig_width; u32 reconfig_height; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 487c243e18ec..4fd8e260d80e 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1365,6 +1365,10 @@ static int __init ath10k_snoc_init(void) { int ret; + if (!icnss_is_fw_ready()) { + pr_err("failed to get fw ready indication\n"); + return -EAGAIN; + } ret = platform_driver_register(&ath10k_snoc_driver); if (ret) pr_err("failed to register ath10k snoc driver: %d\n", diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 0a3928a8fe90..ca06394c48bb 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -21,6 +21,10 @@ #define WIL_MAX_ROC_DURATION_MS 5000 +bool disable_ap_sme; +module_param(disable_ap_sme, bool, S_IRUGO); +MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME"); + #define CHAN60G(_channel, _flags) { \ .band = IEEE80211_BAND_60GHZ, \ .center_freq = 56160 + (2160 * (_channel)), \ @@ -147,9 +151,16 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_AP] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | + BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) }, [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | @@ -1411,6 +1422,28 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid); + + if (!disable_ap_sme) { + wil_err(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (params->aid > WIL_MAX_DMG_AID) { + wil_err(wil, "invalid aid\n"); + return -EINVAL; + } + + return wmi_new_sta(wil, mac, params->aid); +} + static int wil_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) @@ -1427,6 +1460,52 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int authorize; + int cid, i; + struct vring_tx_data *txdata = NULL; + + wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac, + params->sta_flags_mask, params->sta_flags_set); + + if (!disable_ap_sme) { + wil_dbg_misc(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + return 0; + + cid = wil_find_cid(wil, mac); + if (cid < 0) { + wil_err(wil, "station not found\n"); + return -ENOLINK; + } + + for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) + if (wil->vring2cid_tid[i][0] == cid) { + txdata = &wil->vring_tx_data[i]; + break; + } + + if (!txdata) { + wil_err(wil, "vring data not found\n"); + return -ENOLINK; + } + + authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); + txdata->dot1x_open = authorize ? 1 : 0; + wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i, + txdata->dot1x_open); + + return 0; +} + /* probe_client handling */ static void wil_probe_client_handle(struct wil6210_priv *wil, struct wil_probe_client_req *req) @@ -1610,7 +1689,9 @@ static struct cfg80211_ops wil_cfg80211_ops = { .change_beacon = wil_cfg80211_change_beacon, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, + .add_station = wil_cfg80211_add_station, .del_station = wil_cfg80211_del_station, + .change_station = wil_cfg80211_change_station, .probe_client = wil_cfg80211_probe_client, .change_bss = wil_cfg80211_change_bss, /* P2P device */ @@ -1631,10 +1712,11 @@ static void wil_wiphy_init(struct wiphy *wiphy) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_MONITOR); - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_PS_ON_BY_DEFAULT; + if (!disable_ap_sme) + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); wiphy->probe_resp_offload = diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index d3e420f1b26b..865bb11e2a07 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1705,6 +1705,7 @@ static const struct dbg_off dbg_wil_off[] = { WIL_FIELD(recovery_count, S_IRUGO, doff_u32), WIL_FIELD(ap_isolate, S_IRUGO, doff_u32), WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR, doff_u8), + WIL_FIELD(chip_revision, S_IRUGO, doff_u8), {}, }; diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c index 82aae2d705b4..540fc20984d8 100644 --- a/drivers/net/wireless/ath/wil6210/fw.c +++ b/drivers/net/wireless/ath/wil6210/fw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,8 +19,9 @@ #include "wil6210.h" #include "fw.h" -MODULE_FIRMWARE(WIL_FW_NAME); -MODULE_FIRMWARE(WIL_FW2_NAME); +MODULE_FIRMWARE(WIL_FW_NAME_DEFAULT); +MODULE_FIRMWARE(WIL_FW_NAME_SPARROW_PLUS); +MODULE_FIRMWARE(WIL_BOARD_FILE_NAME); static void wil_memset_toio_32(volatile void __iomem *dst, u32 val, diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 8f40eb301924..f4901587c005 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -537,3 +537,22 @@ out: release_firmware(fw); return rc; } + +/** + * wil_fw_verify_file_exists - checks if firmware file exist + * + * @wil: driver context + * @name: firmware file name + * + * return value - boolean, true for success, false for failure + */ +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name) +{ + const struct firmware *fw; + int rc; + + rc = request_firmware(&fw, name, wil_to_dev(wil)); + if (!rc) + release_firmware(fw); + return rc != -ENOENT; +} diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index eb1fd9dd09ba..32e217e7159e 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -176,8 +176,12 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { - if (!from_event) - wmi_disconnect_sta(wil, sta->addr, reason_code, true); + if (!from_event) { + bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? + disable_ap_sme : false; + wmi_disconnect_sta(wil, sta->addr, reason_code, + true, del_sta); + } switch (wdev->iftype) { case NL80211_IFTYPE_AP: @@ -943,16 +947,16 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil_set_oob_mode(wil, oob_mode); if (load_fw) { - wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME, - WIL_FW2_NAME); + wil_info(wil, "Use firmware <%s> + board <%s>\n", + wil->wil_fw_name, WIL_BOARD_FILE_NAME); wil_halt_cpu(wil); memset(wil->fw_version, 0, sizeof(wil->fw_version)); /* Loading f/w from the file */ - rc = wil_request_firmware(wil, WIL_FW_NAME, true); + rc = wil_request_firmware(wil, wil->wil_fw_name, true); if (rc) return rc; - rc = wil_request_firmware(wil, WIL_FW2_NAME, true); + rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true); if (rc) return rc; diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index fdbc51ae1e1a..c97263b45cbd 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -36,18 +36,38 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, static void wil_set_capabilities(struct wil6210_priv *wil) { - u32 rev_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & + RGF_USER_REVISION_ID_MASK); bitmap_zero(wil->hw_capabilities, hw_capability_last); bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); - - switch (rev_id) { - case JTAG_DEV_ID_SPARROW_B0: - wil->hw_name = "Sparrow B0"; - wil->hw_version = HW_VER_SPARROW_B0; + wil->wil_fw_name = WIL_FW_NAME_DEFAULT; + wil->chip_revision = chip_revision; + + switch (jtag_id) { + case JTAG_DEV_ID_SPARROW: + switch (chip_revision) { + case REVISION_ID_SPARROW_D0: + wil->hw_name = "Sparrow D0"; + wil->hw_version = HW_VER_SPARROW_D0; + if (wil_fw_verify_file_exists(wil, + WIL_FW_NAME_SPARROW_PLUS)) + wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS; + break; + case REVISION_ID_SPARROW_B0: + wil->hw_name = "Sparrow B0"; + wil->hw_version = HW_VER_SPARROW_B0; + break; + default: + wil->hw_name = "Unknown"; + wil->hw_version = HW_VER_UNKNOWN; + break; + } break; default: - wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id); + wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", + jtag_id, chip_revision); wil->hw_name = "Unknown"; wil->hw_version = HW_VER_UNKNOWN; } @@ -55,7 +75,7 @@ void wil_set_capabilities(struct wil6210_priv *wil) wil_info(wil, "Board hardware is %s\n", wil->hw_name); /* extract FW capabilities from file without loading the FW */ - wil_request_firmware(wil, WIL_FW_NAME, false); + wil_request_firmware(wil, wil->wil_fw_name, false); } void wil_disable_irq(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index b9727ebe79ac..19de0ebb48f7 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -34,10 +34,12 @@ extern int agg_wsize; extern u32 vring_idle_trsh; extern bool rx_align_2; extern bool debug_fw; +extern bool disable_ap_sme; #define WIL_NAME "wil6210" -#define WIL_FW_NAME "wil6210.fw" /* code */ -#define WIL_FW2_NAME "wil6210.brd" /* board & radio parameters */ +#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */ +#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */ +#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */ #define WIL_DEFAULT_BUS_REQUEST_KBPS 128000 /* ~1Gbps */ #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ @@ -100,6 +102,9 @@ static inline u32 wil_mtu2macbuf(u32 mtu) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \ (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) +#define WIL_MAX_DMG_AID 254 /* for DMG only 1-254 allowed (see + * 802.11REVmc/D5.0, section 9.4.1.8) + */ /* Hardware definitions begin */ /* @@ -254,7 +259,12 @@ struct RGF_ICR { #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ - #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) + #define JTAG_DEV_ID_SPARROW (0x2632072f) + +#define RGF_USER_REVISION_ID (0x88afe4) +#define RGF_USER_REVISION_ID_MASK (3) + #define REVISION_ID_SPARROW_B0 (0x0) + #define REVISION_ID_SPARROW_D0 (0x3) /* crash codes for FW/Ucode stored here */ #define RGF_FW_ASSERT_CODE (0x91f020) @@ -262,7 +272,8 @@ struct RGF_ICR { enum { HW_VER_UNKNOWN, - HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ + HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */ + HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */ }; /* popular locations */ @@ -588,7 +599,9 @@ struct wil6210_priv { DECLARE_BITMAP(status, wil_status_last); u8 fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; + u8 chip_revision; const char *hw_name; + const char *wil_fw_name; DECLARE_BITMAP(hw_capabilities, hw_capability_last); DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); u8 n_mids; /* number of additional MIDs as reported by FW */ @@ -824,8 +837,8 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect); +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta); int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); @@ -835,6 +848,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile); int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid); int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); @@ -928,6 +942,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type); int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd); int wil_request_firmware(struct wil6210_priv *wil, const char *name, bool load); +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime); diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 0bddc9d9c632..ef6472fb1f7e 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -556,7 +556,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", __func__, evt->cid, rc); wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, - WLAN_REASON_UNSPECIFIED, false); + WLAN_REASON_UNSPECIFIED, false, false); } else { wil_info(wil, "%s: successful connection to CID %d\n", __func__, evt->cid); @@ -584,8 +584,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { - if (rc) + if (rc) { + if (disable_ap_sme) + /* notify new_sta has failed */ + cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL); goto out; + } memset(&sinfo, 0, sizeof(sinfo)); @@ -688,6 +692,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) { struct wmi_vring_en_event *evt = d; u8 vri = evt->vring_index; + struct wireless_dev *wdev = wil_to_wdev(wil); wil_dbg_wmi(wil, "Enable vring %d\n", vri); @@ -695,7 +700,12 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) wil_err(wil, "Enable for invalid vring %d\n", vri); return; } - wil->vring_tx_data[vri].dot1x_open = true; + + if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme) + /* in AP mode with disable_ap_sme, this is done by + * wil_cfg80211_change_station() + */ + wil->vring_tx_data[vri].dot1x_open = true; if (vri == wil->bcast_vring) /* no BA for bcast */ return; if (agg_wsize >= 0) @@ -1102,6 +1112,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, .is_go = is_go, + .disable_ap_sme = disable_ap_sme, }; struct { struct wmi_cmd_hdr wmi; @@ -1119,6 +1130,13 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, cmd.pcp_max_assoc_sta = WIL6210_MAX_CID; } + if (disable_ap_sme && + !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME, + wil->fw_capabilities)) { + wil_err(wil, "disable_ap_sme not supported by FW\n"); + return -EOPNOTSUPP; + } + /* * Processing time may be huge, in case of secure AP it takes about * 3500ms for FW to start AP @@ -1489,12 +1507,15 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect) +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta) { int rc; u16 reason_code; - struct wmi_disconnect_sta_cmd cmd = { + struct wmi_disconnect_sta_cmd disc_sta_cmd = { + .disconnect_reason = cpu_to_le16(reason), + }; + struct wmi_del_sta_cmd del_sta_cmd = { .disconnect_reason = cpu_to_le16(reason), }; struct { @@ -1502,12 +1523,19 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, struct wmi_disconnect_event evt; } __packed reply; - ether_addr_copy(cmd.dst_mac, mac); - wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason); - rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd), - WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000); + if (del_sta) { + ether_addr_copy(del_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd, + sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } else { + ether_addr_copy(disc_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd, + sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } /* failure to disconnect in reasonable time treated as FW error */ if (rc) { wil_fw_error_recovery(wil); @@ -1719,6 +1747,24 @@ int wmi_abort_scan(struct wil6210_priv *wil) return rc; } +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) +{ + int rc; + struct wmi_new_sta_cmd cmd = { + .aid = aid, + }; + + wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid); + + ether_addr_copy(cmd.dst_mac, mac); + + rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd)); + if (rc) + wil_err(wil, "Failed to send new sta (%d)\n", rc); + + return rc; +} + void wmi_event_flush(struct wil6210_priv *wil) { ulong flags; diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index d93a4d490d24..9c4a0bdc51f3 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * * Permission to use, copy, modify, and/or distribute this software for any @@ -56,6 +56,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PS_CONFIG = 1, WMI_FW_CAPABILITY_RF_SECTORS = 2, WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, + WMI_FW_CAPABILITY_DISABLE_AP_SME = 4, WMI_FW_CAPABILITY_MAX, }; @@ -187,6 +188,8 @@ enum wmi_command_id { WMI_AOA_MEAS_CMDID = 0x923, WMI_SET_MGMT_RETRY_LIMIT_CMDID = 0x930, WMI_GET_MGMT_RETRY_LIMIT_CMDID = 0x931, + WMI_NEW_STA_CMDID = 0x935, + WMI_DEL_STA_CMDID = 0x936, WMI_TOF_SESSION_START_CMDID = 0x991, WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, WMI_TOF_SET_LCR_CMDID = 0x993, @@ -543,7 +546,8 @@ struct wmi_pcp_start_cmd { u8 pcp_max_assoc_sta; u8 hidden_ssid; u8 is_go; - u8 reserved0[7]; + u8 reserved0[6]; + u8 disable_ap_sme; u8 network_type; u8 channel; u8 disable_sec_offload; @@ -902,6 +906,18 @@ struct wmi_set_mgmt_retry_limit_cmd { u8 reserved[3]; } __packed; +/* WMI_NEW_STA_CMDID */ +struct wmi_new_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + u8 aid; +} __packed; + +/* WMI_DEL_STA_CMDID */ +struct wmi_del_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 disconnect_reason; +} __packed; + enum wmi_tof_burst_duration { WMI_TOF_BURST_DURATION_250_USEC = 2, WMI_TOF_BURST_DURATION_500_USEC = 3, @@ -1292,7 +1308,7 @@ struct wmi_connect_event { u8 assoc_info[0]; } __packed; -/* WMI_DISCONNECT_EVENTID */ +/* disconnect_reason */ enum wmi_disconnect_reason { WMI_DIS_REASON_NO_NETWORK_AVAIL = 0x01, /* bmiss */ @@ -1310,6 +1326,7 @@ enum wmi_disconnect_reason { WMI_DIS_REASON_IBSS_MERGE = 0x0E, }; +/* WMI_DISCONNECT_EVENTID */ struct wmi_disconnect_event { /* reason code, see 802.11 spec. */ __le16 protocol_reason_status; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 1e79fd954969..fde087f07226 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -1827,7 +1827,7 @@ static int ipa_q6_clean_q6_tables(void) u32 max_cmds = ipa_get_max_flt_rt_cmds(ipa_ctx->ipa_num_pipes); mem.base = dma_alloc_coherent(ipa_ctx->pdev, 4, &mem.phys_base, - GFP_KERNEL); + GFP_ATOMIC); if (!mem.base) { IPAERR("failed to alloc DMA buff of size 4\n"); return -ENOMEM; diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h index 0d3fcc2ede86..c146654e438b 100644 --- a/drivers/power/supply/qcom/fg-core.h +++ b/drivers/power/supply/qcom/fg-core.h @@ -71,6 +71,10 @@ #define KI_COEFF_MAX 62200 #define KI_COEFF_SOC_LEVELS 3 +#define SLOPE_LIMIT_COEFF_MAX 31 + +#define BATT_THERM_NUM_COEFFS 3 + /* Debug flag definitions */ enum fg_debug_flag { FG_IRQ = BIT(0), /* Show interrupts */ @@ -164,6 +168,7 @@ enum fg_sram_param_id { FG_SRAM_KI_COEFF_HI_DISCHG, FG_SRAM_ESR_TIGHT_FILTER, FG_SRAM_ESR_BROAD_FILTER, + FG_SRAM_SLOPE_LIMIT, FG_SRAM_MAX, }; @@ -202,6 +207,14 @@ enum wa_flags { PMI8998_V1_REV_WA = BIT(0), }; +enum slope_limit_status { + LOW_TEMP_DISCHARGE = 0, + LOW_TEMP_CHARGE, + HIGH_TEMP_DISCHARGE, + HIGH_TEMP_CHARGE, + SLOPE_LIMIT_NUM_COEFFS, +}; + /* DT parameters for FG device */ struct fg_dt_props { bool force_load_profile; @@ -234,10 +247,13 @@ struct fg_dt_props { int esr_broad_flt_upct; int esr_tight_lt_flt_upct; int esr_broad_lt_flt_upct; + int slope_limit_temp; int jeita_thresholds[NUM_JEITA_LEVELS]; int ki_coeff_soc[KI_COEFF_SOC_LEVELS]; int ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS]; int ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS]; + int slope_limit_coeffs[SLOPE_LIMIT_NUM_COEFFS]; + u8 batt_therm_coeffs[BATT_THERM_NUM_COEFFS]; }; /* parameters from battery profile */ @@ -341,6 +357,7 @@ struct fg_chip { int maint_soc; int delta_soc; int last_msoc; + enum slope_limit_status slope_limit_sts; bool profile_available; bool profile_loaded; bool battery_missing; @@ -352,6 +369,7 @@ struct fg_chip { bool soc_reporting_ready; bool esr_flt_cold_temp_en; bool bsoc_delta_irq_en; + bool slope_limit_en; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index fdb458efd560..1fd092c550f3 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -31,6 +31,8 @@ #define FG_MEM_INFO_PMI8998 0x0D /* SRAM address and offset in ascending order */ +#define SLOPE_LIMIT_WORD 3 +#define SLOPE_LIMIT_OFFSET 0 #define CUTOFF_VOLT_WORD 5 #define CUTOFF_VOLT_OFFSET 0 #define SYS_TERM_CURR_WORD 6 @@ -220,6 +222,8 @@ static struct fg_sram_param pmi8998_v1_sram_params[] = { 1, 512, 1000000, 0, fg_encode_default, NULL), PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET, 1, 512, 1000000, 0, fg_encode_default, NULL), + PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, 1000, + 0, fg_encode_default, NULL), }; static struct fg_sram_param pmi8998_v2_sram_params[] = { @@ -286,6 +290,8 @@ static struct fg_sram_param pmi8998_v2_sram_params[] = { 1, 512, 1000000, 0, fg_encode_default, NULL), PARAM(ESR_BROAD_FILTER, ESR_FILTER_WORD, ESR_UPD_BROAD_OFFSET, 1, 512, 1000000, 0, fg_encode_default, NULL), + PARAM(SLOPE_LIMIT, SLOPE_LIMIT_WORD, SLOPE_LIMIT_OFFSET, 1, 8192, 1000, + 0, fg_encode_default, NULL), }; static struct fg_alg_flag pmi8998_v1_alg_flags[] = { @@ -1770,6 +1776,48 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip) return 0; } +static int fg_slope_limit_config(struct fg_chip *chip, int batt_temp) +{ + enum slope_limit_status status; + int rc; + u8 buf; + + if (!chip->slope_limit_en) + return 0; + + if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING || + chip->charge_status == POWER_SUPPLY_STATUS_FULL) { + if (batt_temp < chip->dt.slope_limit_temp) + status = LOW_TEMP_CHARGE; + else + status = HIGH_TEMP_CHARGE; + } else { + if (batt_temp < chip->dt.slope_limit_temp) + status = LOW_TEMP_DISCHARGE; + else + status = HIGH_TEMP_DISCHARGE; + } + + if (chip->slope_limit_sts == status) + return 0; + + fg_encode(chip->sp, FG_SRAM_SLOPE_LIMIT, + chip->dt.slope_limit_coeffs[status], &buf); + rc = fg_sram_write(chip, chip->sp[FG_SRAM_SLOPE_LIMIT].addr_word, + chip->sp[FG_SRAM_SLOPE_LIMIT].addr_byte, &buf, + chip->sp[FG_SRAM_SLOPE_LIMIT].len, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in configuring slope_limit coefficient, rc=%d\n", + rc); + return rc; + } + + chip->slope_limit_sts = status; + fg_dbg(chip, FG_STATUS, "Slope limit status: %d value: %x\n", status, + buf); + return 0; +} + static int fg_esr_filter_config(struct fg_chip *chip, int batt_temp) { u8 esr_tight_lt_flt, esr_broad_lt_flt; @@ -1918,7 +1966,7 @@ static void status_change_work(struct work_struct *work) struct fg_chip *chip = container_of(work, struct fg_chip, status_change_work); union power_supply_propval prop = {0, }; - int rc; + int rc, batt_temp; if (!batt_psy_initialized(chip)) { fg_dbg(chip, FG_STATUS, "Charger not available?!\n"); @@ -1971,6 +2019,14 @@ static void status_change_work(struct work_struct *work) if (rc < 0) pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc); + rc = fg_get_battery_temp(chip, &batt_temp); + if (!rc) { + rc = fg_slope_limit_config(chip, batt_temp); + if (rc < 0) + pr_err("Error in configuring slope limiter rc:%d\n", + rc); + } + fg_batt_avg_update(chip); out: @@ -2986,6 +3042,21 @@ static int fg_hw_init(struct fg_chip *chip) } } + /* + * configure battery thermal coefficients c1,c2,c3 + * if its value is not zero. + */ + if (chip->dt.batt_therm_coeffs[0] > 0) { + rc = fg_write(chip, BATT_INFO_THERM_C1(chip), + chip->dt.batt_therm_coeffs, BATT_THERM_NUM_COEFFS); + if (rc < 0) { + pr_err("Error in writing battery thermal coefficients, rc=%d\n", + rc); + return rc; + } + } + + if (chip->dt.recharge_soc_thr > 0 && chip->dt.recharge_soc_thr < 100) { rc = fg_set_recharge_soc(chip, chip->dt.recharge_soc_thr); if (rc < 0) { @@ -3221,6 +3292,10 @@ static irqreturn_t fg_delta_batt_temp_irq_handler(int irq, void *data) if (rc < 0) pr_err("Error in configuring ESR filter rc:%d\n", rc); + rc = fg_slope_limit_config(chip, batt_temp); + if (rc < 0) + pr_err("Error in configuring slope limiter rc:%d\n", rc); + if (!batt_psy_initialized(chip)) { chip->last_batt_temp = batt_temp; return IRQ_HANDLED; @@ -3458,6 +3533,40 @@ static int fg_register_interrupts(struct fg_chip *chip) return 0; } +static int fg_parse_slope_limit_coefficients(struct fg_chip *chip) +{ + struct device_node *node = chip->dev->of_node; + int rc, i; + + rc = of_property_read_u32(node, "qcom,slope-limit-temp-threshold", + &chip->dt.slope_limit_temp); + if (rc < 0) + return 0; + + rc = of_property_count_elems_of_size(node, "qcom,slope-limit-coeffs", + sizeof(u32)); + if (rc != SLOPE_LIMIT_NUM_COEFFS) + return -EINVAL; + + rc = of_property_read_u32_array(node, "qcom,slope-limit-coeffs", + chip->dt.slope_limit_coeffs, SLOPE_LIMIT_NUM_COEFFS); + if (rc < 0) { + pr_err("Error in reading qcom,slope-limit-coeffs, rc=%d\n", rc); + return rc; + } + + for (i = 0; i < SLOPE_LIMIT_NUM_COEFFS; i++) { + if (chip->dt.slope_limit_coeffs[i] > SLOPE_LIMIT_COEFF_MAX || + chip->dt.slope_limit_coeffs[i] < 0) { + pr_err("Incorrect slope limit coefficient\n"); + return -EINVAL; + } + } + + chip->slope_limit_en = true; + return 0; +} + static int fg_parse_ki_coefficients(struct fg_chip *chip) { struct device_node *node = chip->dev->of_node; @@ -3720,6 +3829,18 @@ static int fg_parse_dt(struct fg_chip *chip) rc); } + if (of_property_count_elems_of_size(node, + "qcom,battery-thermal-coefficients", + sizeof(u8)) == BATT_THERM_NUM_COEFFS) { + rc = of_property_read_u8_array(node, + "qcom,battery-thermal-coefficients", + chip->dt.batt_therm_coeffs, + BATT_THERM_NUM_COEFFS); + if (rc < 0) + pr_warn("Error reading battery thermal coefficients, rc:%d\n", + rc); + } + rc = of_property_read_u32(node, "qcom,fg-esr-timer-charging", &temp); if (rc < 0) chip->dt.esr_timer_charging = -EINVAL; @@ -3846,6 +3967,11 @@ static int fg_parse_dt(struct fg_chip *chip) chip->dt.esr_broad_lt_flt_upct = DEFAULT_ESR_BROAD_LT_FLT_UPCT; else chip->dt.esr_broad_lt_flt_upct = temp; + + rc = fg_parse_slope_limit_coefficients(chip); + if (rc < 0) + pr_err("Error in parsing slope limit coeffs, rc=%d\n", rc); + return 0; } diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 7a5a53695329..768871ffa9a7 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -77,15 +77,6 @@ module_param(qmi_timeout, ulong, 0600); ipc_log_string(icnss_ipc_log_context, _x); \ } while (0) -#ifdef CONFIG_ICNSS_DEBUG -#define icnss_ipc_log_long_string(_x...) do { \ - if (icnss_ipc_log_long_context) \ - ipc_log_string(icnss_ipc_log_long_context, _x); \ - } while (0) -#else -#define icnss_ipc_log_long_string(_x...) -#endif - #define icnss_pr_err(_fmt, ...) do { \ pr_err(_fmt, ##__VA_ARGS__); \ icnss_ipc_log_string("ERR: " pr_fmt(_fmt), \ @@ -110,12 +101,6 @@ module_param(qmi_timeout, ulong, 0600); ##__VA_ARGS__); \ } while (0) -#define icnss_reg_dbg(_fmt, ...) do { \ - pr_debug(_fmt, ##__VA_ARGS__); \ - icnss_ipc_log_long_string("REG: " pr_fmt(_fmt), \ - ##__VA_ARGS__); \ - } while (0) - #ifdef CONFIG_ICNSS_DEBUG #define ICNSS_ASSERT(_condition) do { \ if (!(_condition)) { \ @@ -157,10 +142,6 @@ module_param(dynamic_feature_mask, ullong, 0600); void *icnss_ipc_log_context; -#ifdef CONFIG_ICNSS_DEBUG -void *icnss_ipc_log_long_context; -#endif - #define ICNSS_EVENT_PENDING 2989 #define ICNSS_EVENT_SYNC BIT(0) @@ -4034,26 +4015,6 @@ static struct platform_driver icnss_driver = { }, }; -#ifdef CONFIG_ICNSS_DEBUG -static void __init icnss_ipc_log_long_context_init(void) -{ - icnss_ipc_log_long_context = ipc_log_context_create(NUM_REG_LOG_PAGES, - "icnss_long", 0); - if (!icnss_ipc_log_long_context) - icnss_pr_err("Unable to create register log context\n"); -} - -static void __exit icnss_ipc_log_long_context_destroy(void) -{ - ipc_log_context_destroy(icnss_ipc_log_long_context); - icnss_ipc_log_long_context = NULL; -} -#else - -static void __init icnss_ipc_log_long_context_init(void) { } -static void __exit icnss_ipc_log_long_context_destroy(void) { } -#endif - static int __init icnss_initialize(void) { icnss_ipc_log_context = ipc_log_context_create(NUM_LOG_PAGES, @@ -4061,8 +4022,6 @@ static int __init icnss_initialize(void) if (!icnss_ipc_log_context) icnss_pr_err("Unable to create log context\n"); - icnss_ipc_log_long_context_init(); - return platform_driver_register(&icnss_driver); } @@ -4071,8 +4030,6 @@ static void __exit icnss_exit(void) platform_driver_unregister(&icnss_driver); ipc_log_context_destroy(icnss_ipc_log_context); icnss_ipc_log_context = NULL; - - icnss_ipc_log_long_context_destroy(); } diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 2244c64d28af..4d9767b6f8a3 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -583,11 +583,35 @@ static int pil_init_mmap(struct pil_desc *desc, const struct pil_mdt *mdt) return pil_init_entry_addr(priv, mdt); } +struct pil_map_fw_info { + void *region; + struct dma_attrs attrs; + phys_addr_t base_addr; + struct device *dev; +}; + static void pil_release_mmap(struct pil_desc *desc) { struct pil_priv *priv = desc->priv; struct pil_seg *p, *tmp; u64 zero = 0ULL; + u8 __iomem *buf; + + struct pil_map_fw_info map_fw_info = { + .attrs = desc->attrs, + .region = priv->region, + .base_addr = priv->region_start, + .dev = desc->dev, + }; + + void *map_data = desc->map_data ? desc->map_data : &map_fw_info; + + /* Clear memory so that unauthorized ELF code is not left behind */ + buf = desc->map_fw_mem(priv->region_start, (priv->region_end - + priv->region_start), map_data); + pil_memset_io(buf, 0, (priv->region_end - priv->region_start)); + desc->unmap_fw_mem(buf, (priv->region_end - priv->region_start), + map_data); if (priv->info) { __iowrite32_copy(&priv->info->start, &zero, @@ -603,13 +627,6 @@ static void pil_release_mmap(struct pil_desc *desc) #define IOMAP_SIZE SZ_1M -struct pil_map_fw_info { - void *region; - struct dma_attrs attrs; - phys_addr_t base_addr; - struct device *dev; -}; - static void *map_fw_mem(phys_addr_t paddr, size_t size, void *data) { struct pil_map_fw_info *info = data; diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2ac9b28e036f..5b648460e621 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1079,7 +1079,7 @@ static int dwc3_probe(struct platform_device *pdev) dwc->regs_size = resource_size(res); /* default to highest possible threshold */ - lpm_nyet_threshold = 0xff; + lpm_nyet_threshold = 0xf; /* default to -3.5dB de-emphasis */ tx_de_emphasis = 1; diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 611750e209f9..087cd9fecfe9 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -309,7 +309,7 @@ struct usbpd { spinlock_t rx_lock; u32 received_pdos[7]; - int src_cap_id; + u16 src_cap_id; u8 selected_pdo; u8 requested_pdo; u32 rdo; /* can be either source or sink */ @@ -338,8 +338,10 @@ struct usbpd { enum power_role current_pr; bool in_pr_swap; bool pd_phy_opened; - struct completion swap_complete; + bool send_request; + struct completion is_ready; + struct mutex swap_lock; struct dual_role_phy_instance *dual_role; struct dual_role_phy_desc dr_desc; bool send_pr_swap; @@ -463,6 +465,9 @@ static inline void pd_reset_protocol(struct usbpd *pd) */ pd->rx_msgid = -1; pd->tx_msgid = 0; + pd->send_request = false; + pd->send_pr_swap = false; + pd->send_dr_swap = false; } static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data, @@ -842,7 +847,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) } kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); - complete(&pd->swap_complete); + complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; @@ -977,7 +982,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_READY: pd->in_explicit_contract = true; kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); - complete(&pd->swap_complete); + complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role); break; @@ -1546,9 +1551,9 @@ static void usbpd_sm(struct work_struct *w) pd->hard_reset_recvd = false; pd->caps_count = 0; pd->hard_reset_count = 0; - pd->src_cap_id = 0; pd->requested_voltage = 0; pd->requested_current = 0; + pd->selected_pdo = pd->requested_pdo = 0; memset(&pd->received_pdos, 0, sizeof(pd->received_pdos)); rx_msg_cleanup(pd); @@ -1616,8 +1621,12 @@ static void usbpd_sm(struct work_struct *w) POWER_SUPPLY_PROP_PD_IN_HARD_RESET, &val); pd->in_pr_swap = false; + pd->in_explicit_contract = false; + pd->selected_pdo = pd->requested_pdo = 0; + pd->rdo = 0; rx_msg_cleanup(pd); reset_vdm_state(pd); + kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); if (pd->current_pr == PR_SINK) { usbpd_set_state(pd, PE_SNK_TRANSITION_TO_DEFAULT); @@ -1840,8 +1849,10 @@ static void usbpd_sm(struct work_struct *w) pd_send_hard_reset(pd); pd->in_explicit_contract = false; + pd->rdo = 0; rx_msg_cleanup(pd); reset_vdm_state(pd); + kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); pd->current_state = PE_SRC_TRANSITION_TO_DEFAULT; kick_sm(pd, PS_HARD_RESET_TIME); @@ -2075,6 +2086,9 @@ static void usbpd_sm(struct work_struct *w) vconn_swap(pd); } else if (IS_DATA(rx_msg, MSG_VDM)) { handle_vdm_rx(pd, rx_msg); + } else if (pd->send_request) { + pd->send_request = false; + usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); } else if (pd->send_pr_swap && is_sink_tx_ok(pd)) { pd->send_pr_swap = false; ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG); @@ -2158,7 +2172,10 @@ static void usbpd_sm(struct work_struct *w) pd_send_hard_reset(pd); pd->in_explicit_contract = false; + pd->selected_pdo = pd->requested_pdo = 0; + pd->rdo = 0; reset_vdm_state(pd); + kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); usbpd_set_state(pd, PE_SNK_TRANSITION_TO_DEFAULT); break; @@ -2540,17 +2557,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } - reinit_completion(&pd->swap_complete); + mutex_lock(&pd->swap_lock); + reinit_completion(&pd->is_ready); pd->send_dr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ - if (!wait_for_completion_timeout(&pd->swap_complete, + if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(100))) { usbpd_err(&pd->dev, "data_role swap timed out\n"); + mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } + mutex_unlock(&pd->swap_lock); + if ((*val == DUAL_ROLE_PROP_DR_HOST && pd->current_dr != DR_DFP) || (*val == DUAL_ROLE_PROP_DR_DEVICE && @@ -2591,17 +2612,21 @@ static int usbpd_dr_set_property(struct dual_role_phy_instance *dual_role, return -EAGAIN; } - reinit_completion(&pd->swap_complete); + mutex_lock(&pd->swap_lock); + reinit_completion(&pd->is_ready); pd->send_pr_swap = true; kick_sm(pd, 0); /* wait for operation to complete */ - if (!wait_for_completion_timeout(&pd->swap_complete, + if (!wait_for_completion_timeout(&pd->is_ready, msecs_to_jiffies(2000))) { usbpd_err(&pd->dev, "power_role swap timed out\n"); + mutex_unlock(&pd->swap_lock); return -ETIMEDOUT; } + mutex_unlock(&pd->swap_lock); + if ((*val == DUAL_ROLE_PROP_PR_SRC && pd->current_pr != PR_SRC) || (*val == DUAL_ROLE_PROP_PR_SNK && @@ -2864,36 +2889,62 @@ static ssize_t select_pdo_store(struct device *dev, int pdo, uv = 0, ua = 0; int ret; + mutex_lock(&pd->swap_lock); + /* Only allowed if we are already in explicit sink contract */ if (pd->current_state != PE_SNK_READY || !is_sink_tx_ok(pd)) { usbpd_err(&pd->dev, "select_pdo: Cannot select new PDO yet\n"); - return -EBUSY; + ret = -EBUSY; + goto out; } ret = sscanf(buf, "%d %d %d %d", &src_cap_id, &pdo, &uv, &ua); if (ret != 2 && ret != 4) { usbpd_err(&pd->dev, "select_pdo: Must specify <src cap id> <PDO> [<uV> <uA>]\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } if (src_cap_id != pd->src_cap_id) { usbpd_err(&pd->dev, "select_pdo: src_cap_id mismatch. Requested:%d, current:%d\n", src_cap_id, pd->src_cap_id); - return -EINVAL; + ret = -EINVAL; + goto out; } if (pdo < 1 || pdo > 7) { usbpd_err(&pd->dev, "select_pdo: invalid PDO:%d\n", pdo); - return -EINVAL; + ret = -EINVAL; + goto out; } ret = pd_select_pdo(pd, pdo, uv, ua); if (ret) - return ret; + goto out; - usbpd_set_state(pd, PE_SNK_SELECT_CAPABILITY); + reinit_completion(&pd->is_ready); + pd->send_request = true; + kick_sm(pd, 0); - return size; + /* wait for operation to complete */ + if (!wait_for_completion_timeout(&pd->is_ready, + msecs_to_jiffies(1000))) { + usbpd_err(&pd->dev, "select_pdo: request timed out\n"); + ret = -ETIMEDOUT; + goto out; + } + + /* determine if request was accepted/rejected */ + if (pd->selected_pdo != pd->requested_pdo || + pd->current_voltage != pd->requested_voltage) { + usbpd_err(&pd->dev, "select_pdo: request rejected\n"); + ret = -EINVAL; + } + +out: + pd->send_request = false; + mutex_unlock(&pd->swap_lock); + return ret ? ret : size; } static ssize_t select_pdo_show(struct device *dev, @@ -3123,6 +3174,7 @@ struct usbpd *usbpd_create(struct device *parent) INIT_WORK(&pd->sm_work, usbpd_sm); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; + mutex_init(&pd->swap_lock); pd->usb_psy = power_supply_get_by_name("usb"); if (!pd->usb_psy) { @@ -3166,7 +3218,7 @@ struct usbpd *usbpd_create(struct device *parent) pd->num_sink_caps = device_property_read_u32_array(parent, "qcom,default-sink-caps", NULL, 0); - if (pd->num_sink_caps) { + if (pd->num_sink_caps > 0) { int i; u32 sink_caps[14]; @@ -3233,7 +3285,7 @@ struct usbpd *usbpd_create(struct device *parent) spin_lock_init(&pd->rx_lock); INIT_LIST_HEAD(&pd->rx_q); INIT_LIST_HEAD(&pd->svid_handlers); - init_completion(&pd->swap_complete); + init_completion(&pd->is_ready); pd->psy_nb.notifier_call = psy_changed; ret = power_supply_reg_notifier(&pd->psy_nb); diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 3d3a2022bc04..ddc21d0c1bbb 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -1818,11 +1818,14 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 { #define AFE_PORT_SAMPLE_RATE_16K 16000 #define AFE_PORT_SAMPLE_RATE_48K 48000 #define AFE_PORT_SAMPLE_RATE_96K 96000 +#define AFE_PORT_SAMPLE_RATE_176P4K 176400 #define AFE_PORT_SAMPLE_RATE_192K 192000 +#define AFE_PORT_SAMPLE_RATE_352P8K 352800 #define AFE_LINEAR_PCM_DATA 0x0 #define AFE_NON_LINEAR_DATA 0x1 #define AFE_LINEAR_PCM_DATA_PACKED_60958 0x2 #define AFE_NON_LINEAR_DATA_PACKED_60958 0x3 +#define AFE_GENERIC_COMPRESSED 0x8 /* This param id is used to configure I2S interface */ #define AFE_PARAM_ID_I2S_CONFIG 0x0001020D @@ -2755,25 +2758,31 @@ struct afe_param_id_tdm_cfg { - #AFE_PORT_SAMPLE_RATE_16K - #AFE_PORT_SAMPLE_RATE_24K - #AFE_PORT_SAMPLE_RATE_32K - - #AFE_PORT_SAMPLE_RATE_48K @tablebulletend */ + - #AFE_PORT_SAMPLE_RATE_48K + - #AFE_PORT_SAMPLE_RATE_176P4K + - #AFE_PORT_SAMPLE_RATE_352P8K @tablebulletend + */ u32 bit_width; /**< Bit width of the sample. - @values 16, 24 */ + * @values 16, 24, 32 + */ u16 data_format; - /**< Data format: linear and compressed - + /**< Data format: linear ,compressed, generic compresssed @values - #AFE_LINEAR_PCM_DATA - - #AFE_NON_LINEAR_DATA @tablebulletend */ + - #AFE_NON_LINEAR_DATA + - #AFE_GENERIC_COMPRESSED + */ u16 sync_mode; /**< TDM synchronization setting. @values (short, long, slot) sync mode - #AFE_PORT_TDM_SHORT_SYNC_BIT_MODE - #AFE_PORT_TDM_LONG_SYNC_MODE - - #AFE_PORT_TDM_SHORT_SYNC_SLOT_MODE @tablebulletend */ + - #AFE_PORT_TDM_SHORT_SYNC_SLOT_MODE @tablebulletend + */ u16 sync_src; /**< Synchronization source. @@ -3629,7 +3638,7 @@ struct afe_lpass_core_shared_clk_config_command { #define DEFAULT_COPP_TOPOLOGY 0x00010314 #define DEFAULT_POPP_TOPOLOGY 0x00010BE4 #define COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY 0x0001076B -#define COMPRESS_PASSTHROUGH_NONE_TOPOLOGY 0x00010774 +#define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774 #define VPM_TX_SM_ECNS_COPP_TOPOLOGY 0x00010F71 #define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72 #define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75 @@ -3935,6 +3944,8 @@ struct asm_softvolume_params { #define ASM_MEDIA_FMT_EVRCWB_FS 0x00010BF0 +#define ASM_MEDIA_FMT_GENERIC_COMPRESSED 0x00013212 + #define ASM_MAX_EQ_BANDS 12 #define ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2 0x00010D98 @@ -3944,6 +3955,40 @@ u32 fmt_blk_size; /* Media format block size in bytes.*/ } __packed; +struct asm_generic_compressed_fmt_blk_t { + struct apr_hdr hdr; + struct asm_data_cmd_media_fmt_update_v2 fmt_blk; + + /* + * Channel mapping array of bitstream output. + * Channel[i] mapping describes channel i inside the buffer, where + * i < num_channels. All valid used channels must be + * present at the beginning of the array. + */ + uint8_t channel_mapping[8]; + + /* + * Number of channels of the incoming bitstream. + * Supported values: 1,2,3,4,5,6,7,8 + */ + uint16_t num_channels; + + /* + * Nominal bits per sample value of the incoming bitstream. + * Supported values: 16, 32 + */ + uint16_t bits_per_sample; + + /* + * Nominal sampling rate of the incoming bitstream. + * Supported values: 8000, 11025, 16000, 22050, 24000, 32000, + * 44100, 48000, 88200, 96000, 176400, 192000, + * 352800, 384000 + */ + uint32_t sampling_rate; + +} __packed; + struct asm_multi_channel_pcm_fmt_blk_v2 { struct apr_hdr hdr; struct asm_data_cmd_media_fmt_update_v2 fmt_blk; @@ -9992,6 +10037,108 @@ struct afe_port_group_create { union afe_port_group_config data; } __packed; +/* ID of the parameter used by #AFE_MODULE_AUDIO_DEV_INTERFACE to specify + * the timing statistics of the corresponding device interface. + * Client can periodically query for the device time statistics to help adjust + * the PLL based on the drift value. The get param command must be sent to + * AFE port ID corresponding to device interface + + * This parameter ID supports following get param commands: + * #AFE_PORT_CMD_GET_PARAM_V2 and + * #AFE_PORT_CMD_GET_PARAM_V3. + */ +#define AFE_PARAM_ID_DEV_TIMING_STATS 0x000102AD + +/* Version information used to handle future additions to AFE device + * interface timing statistics (for backward compatibility). + */ +#define AFE_API_VERSION_DEV_TIMING_STATS 0x1 + +/* Enumeration for specifying a sink(Rx) device */ +#define AFE_SINK_DEVICE 0x0 + +/* Enumeration for specifying a source(Tx) device */ +#define AFE_SOURCE_DEVICE 0x1 + +/* Enumeration for specifying the drift reference is of type AV Timer */ +#define AFE_REF_TIMER_TYPE_AVTIMER 0x0 + +/* Message payload structure for the + * AFE_PARAM_ID_DEV_TIMING_STATS parameter. + */ +struct afe_param_id_dev_timing_stats { + /* Minor version used to track the version of device interface timing + * statistics. Currently, the supported version is 1. + * @values #AFE_API_VERSION_DEV_TIMING_STATS + */ + u32 minor_version; + + /* Indicates the device interface direction as either + * source (Tx) or sink (Rx). + * @values + * #AFE_SINK_DEVICE + * #AFE_SOURCE_DEVICE + */ + u16 device_direction; + + /* Reference timer for drift accumulation and time stamp information. + * @values + * #AFE_REF_TIMER_TYPE_AVTIMER @tablebulletend + */ + u16 reference_timer; + + /* + * Flag to indicate if resync is required on the client side for + * drift correction. Flag is set to TRUE for the first get_param + * response after device interface starts. This flag value can be + * used by client to identify if device interface restart has + * happened and if any re-sync is required at their end for drift + * correction. + * @values + * 0: FALSE (Resync not required) + * 1: TRUE (Resync required) @tablebulletend + */ + u32 resync_flag; + + /* Accumulated drift value in microseconds. This value is updated + * every 100th ms. + * Positive drift value indicates AV timer is running faster than device + * Negative drift value indicates AV timer is running slower than device + * @values Any valid int32 number + */ + s32 acc_drift_value; + + /* Lower 32 bits of the 64-bit absolute timestamp of reference + * timer in microseconds. + + * This timestamp corresponds to the time when the drift values + * are accumlated for every 100th ms. + * @values Any valid uint32 number + */ + u32 ref_timer_abs_ts_lsw; + + /* Upper 32 bits of the 64-bit absolute timestamp of reference + * timer in microseconds. + * This timestamp corresponds to the time when the drift values + * are accumlated for every 100th ms. + * @values Any valid uint32 number + */ + u32 ref_timer_abs_ts_msw; +} __packed; + +struct afe_av_dev_drift_get_param { + struct apr_hdr hdr; + struct afe_port_cmd_get_param_v2 get_param; + struct afe_port_param_data_v2 pdata; + struct afe_param_id_dev_timing_stats timing_stats; +} __packed; + +struct afe_av_dev_drift_get_param_resp { + uint32_t status; + struct afe_port_param_data_v2 pdata; + struct afe_param_id_dev_timing_stats timing_stats; +} __packed; + /* Command for Matrix or Stream Router */ #define ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2 0x00010DCE /* Module for AVSYNC */ @@ -10203,6 +10350,7 @@ enum { COMPRESSED_PASSTHROUGH_CONVERT, COMPRESSED_PASSTHROUGH_DSD, LISTEN, + COMPRESSED_PASSTHROUGH_GEN, }; #define AUDPROC_MODULE_ID_COMPRESSED_MUTE 0x00010770 diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index e4033e712804..b1c3b0baf4b3 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -364,6 +364,8 @@ int afe_send_custom_tdm_header_cfg( struct afe_param_id_custom_tdm_header_cfg *custom_tdm_header_cfg, u16 port_id); int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, - u32 rate); + u32 rate, u16 num_groups); void afe_set_routing_callback(routing_cb); +int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats, + u16 port); #endif /* __Q6AFE_V2_H__ */ diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 9a3db9aaa25e..76bb795119c2 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -54,6 +54,7 @@ #define FORMAT_DTS 0x001c #define FORMAT_DSD 0x001d #define FORMAT_APTX 0x001e +#define FORMAT_GEN_COMPR 0x001f #define ENCDEC_SBCBITRATE 0x0001 #define ENCDEC_IMMEDIATE_DECODE 0x0002 @@ -500,6 +501,11 @@ int q6asm_media_format_block_multi_ch_pcm_v2( uint32_t rate, uint32_t channels, bool use_default_chmap, char *channel_map, uint16_t bits_per_sample); +int q6asm_media_format_block_gen_compr( + struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, char *channel_map, + uint16_t bits_per_sample); int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac, uint32_t rate, uint32_t channels, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 432de7089d0e..5dd643d524d6 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -422,6 +422,9 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len, len += NET_SKB_PAD; + if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE)) + gfp_mask |= GFP_DMA; + if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) || (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) { skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c index e0b149cf1f7e..4fe9e2d50f7a 100644 --- a/sound/soc/codecs/wcd934x/wcd934x.c +++ b/sound/soc/codecs/wcd934x/wcd934x.c @@ -8098,13 +8098,8 @@ static struct snd_soc_dai_driver tavil_dai[] = { static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil) { - struct snd_soc_codec *codec = tavil->codec; - - if (!codec) - return; - mutex_lock(&tavil->power_lock); - dev_dbg(codec->dev, "%s: Entering power gating function, %d\n", + dev_dbg(tavil->dev, "%s: Entering power gating function, %d\n", __func__, tavil->power_active_ref); if (tavil->power_active_ref > 0) @@ -8113,16 +8108,16 @@ static void tavil_codec_power_gate_digital_core(struct tavil_priv *tavil) wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_COLLAPSE_BEGIN, WCD9XXX_DIG_CORE_REGION_1); - snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, - 0x04, 0x04); - snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, - 0x01, 0x00); - snd_soc_update_bits(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, - 0x02, 0x00); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x04, 0x04); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x01, 0x00); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x02, 0x00); wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_DOWN, WCD9XXX_DIG_CORE_REGION_1); exit: - dev_dbg(codec->dev, "%s: Exiting power gating function, %d\n", + dev_dbg(tavil->dev, "%s: Exiting power gating function, %d\n", __func__, tavil->power_active_ref); mutex_unlock(&tavil->power_lock); } @@ -8131,34 +8126,32 @@ static void tavil_codec_power_gate_work(struct work_struct *work) { struct tavil_priv *tavil; struct delayed_work *dwork; - struct snd_soc_codec *codec; dwork = to_delayed_work(work); tavil = container_of(dwork, struct tavil_priv, power_gate_work); - codec = tavil->codec; - - if (!codec) - return; tavil_codec_power_gate_digital_core(tavil); } /* called under power_lock acquisition */ -static int tavil_dig_core_remove_power_collapse(struct snd_soc_codec *codec) +static int tavil_dig_core_remove_power_collapse(struct tavil_priv *tavil) { - struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec); - - snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5); - snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7); - snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00); - snd_soc_update_bits(codec, WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02); - snd_soc_write(codec, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3); + regmap_write(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x05); + regmap_write(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x07); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x00); + regmap_update_bits(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_RST_CTL, 0x02, 0x02); + regmap_write(tavil->wcd9xxx->regmap, + WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x03); wcd9xxx_set_power_state(tavil->wcd9xxx, WCD_REGION_POWER_COLLAPSE_REMOVE, WCD9XXX_DIG_CORE_REGION_1); - regcache_mark_dirty(codec->component.regmap); - regcache_sync_region(codec->component.regmap, + regcache_mark_dirty(tavil->wcd9xxx->regmap); + regcache_sync_region(tavil->wcd9xxx->regmap, WCD934X_DIG_CORE_REG_MIN, WCD934X_DIG_CORE_REG_MAX); @@ -8168,7 +8161,6 @@ static int tavil_dig_core_remove_power_collapse(struct snd_soc_codec *codec) static int tavil_dig_core_power_collapse(struct tavil_priv *tavil, int req_state) { - struct snd_soc_codec *codec; int cur_state; /* Exit if feature is disabled */ @@ -8189,10 +8181,6 @@ static int tavil_dig_core_power_collapse(struct tavil_priv *tavil, goto unlock_mutex; } - codec = tavil->codec; - if (!codec) - goto unlock_mutex; - if (req_state == POWER_COLLAPSE) { if (tavil->power_active_ref == 0) { schedule_delayed_work(&tavil->power_gate_work, @@ -8210,7 +8198,7 @@ static int tavil_dig_core_power_collapse(struct tavil_priv *tavil, tavil->wcd9xxx, WCD9XXX_DIG_CORE_REGION_1); if (cur_state == WCD_REGION_POWER_DOWN) { - tavil_dig_core_remove_power_collapse(codec); + tavil_dig_core_remove_power_collapse(tavil); } else { mutex_unlock(&tavil->power_lock); cancel_delayed_work_sync( diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 83ae4c14d8ba..e6fa1143af02 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -159,6 +159,21 @@ struct msm_wsa881x_dev_info { u32 index; }; +enum pinctrl_pin_state { + STATE_DISABLE = 0, /* All pins are in sleep state */ + STATE_MI2S_ACTIVE, /* IS2 = active, TDM = sleep */ + STATE_TDM_ACTIVE, /* IS2 = sleep, TDM = active */ +}; + +struct msm_pinctrl_info { + struct pinctrl *pinctrl; + struct pinctrl_state *mi2s_disable; + struct pinctrl_state *tdm_disable; + struct pinctrl_state *mi2s_active; + struct pinctrl_state *tdm_active; + enum pinctrl_pin_state curr_state; +}; + struct msm_asoc_mach_data { u32 mclk_freq; int us_euro_gpio; /* used by gpio driver API */ @@ -166,6 +181,7 @@ struct msm_asoc_mach_data { struct device_node *hph_en1_gpio_p; /* used by pinctrl API */ struct device_node *hph_en0_gpio_p; /* used by pinctrl API */ struct snd_info_entry *codec_root; + struct msm_pinctrl_info pinctrl_info; }; struct msm_asoc_wcd93xx_codec { @@ -174,6 +190,9 @@ struct msm_asoc_wcd93xx_codec { void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec); }; +static const char *const pin_states[] = {"sleep", "i2s-active", + "tdm-active"}; + enum { TDM_0 = 0, TDM_1, @@ -3993,6 +4012,275 @@ done: return ret; } +static int msm_set_pinctrl(struct msm_pinctrl_info *pinctrl_info, + enum pinctrl_pin_state new_state) +{ + int ret = 0; + int curr_state = 0; + + if (pinctrl_info == NULL) { + pr_err("%s: pinctrl_info is NULL\n", __func__); + ret = -EINVAL; + goto err; + } + curr_state = pinctrl_info->curr_state; + pinctrl_info->curr_state = new_state; + pr_debug("%s: curr_state = %s new_state = %s\n", __func__, + pin_states[curr_state], pin_states[pinctrl_info->curr_state]); + + if (curr_state == pinctrl_info->curr_state) { + pr_debug("%s: Already in same state\n", __func__); + goto err; + } + + if (curr_state != STATE_DISABLE && + pinctrl_info->curr_state != STATE_DISABLE) { + pr_debug("%s: state already active cannot switch\n", __func__); + ret = -EIO; + goto err; + } + + switch (pinctrl_info->curr_state) { + case STATE_MI2S_ACTIVE: + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->mi2s_active); + if (ret) { + pr_err("%s: MI2S state select failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + break; + case STATE_TDM_ACTIVE: + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->tdm_active); + if (ret) { + pr_err("%s: TDM state select failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + break; + case STATE_DISABLE: + if (curr_state == STATE_MI2S_ACTIVE) { + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->mi2s_disable); + } else { + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->tdm_disable); + } + if (ret) { + pr_err("%s: state disable failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + break; + default: + pr_err("%s: TLMM pin state is invalid\n", __func__); + return -EINVAL; + } + +err: + return ret; +} + +static void msm_release_pinctrl(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); + struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; + + if (pinctrl_info->pinctrl) { + devm_pinctrl_put(pinctrl_info->pinctrl); + pinctrl_info->pinctrl = NULL; + } +} + +static int msm_get_pinctrl(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); + struct msm_pinctrl_info *pinctrl_info = NULL; + struct pinctrl *pinctrl; + int ret; + + pinctrl_info = &pdata->pinctrl_info; + + if (pinctrl_info == NULL) { + pr_err("%s: pinctrl_info is NULL\n", __func__); + return -EINVAL; + } + + pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR_OR_NULL(pinctrl)) { + pr_err("%s: Unable to get pinctrl handle\n", __func__); + return -EINVAL; + } + pinctrl_info->pinctrl = pinctrl; + + /* get all the states handles from Device Tree */ + pinctrl_info->mi2s_disable = pinctrl_lookup_state(pinctrl, + "quat-mi2s-sleep"); + if (IS_ERR(pinctrl_info->mi2s_disable)) { + pr_err("%s: could not get mi2s_disable pinstate\n", __func__); + goto err; + } + pinctrl_info->mi2s_active = pinctrl_lookup_state(pinctrl, + "quat-mi2s-active"); + if (IS_ERR(pinctrl_info->mi2s_active)) { + pr_err("%s: could not get mi2s_active pinstate\n", __func__); + goto err; + } + pinctrl_info->tdm_disable = pinctrl_lookup_state(pinctrl, + "quat-tdm-sleep"); + if (IS_ERR(pinctrl_info->tdm_disable)) { + pr_err("%s: could not get tdm_disable pinstate\n", __func__); + goto err; + } + pinctrl_info->tdm_active = pinctrl_lookup_state(pinctrl, + "quat-tdm-active"); + if (IS_ERR(pinctrl_info->tdm_active)) { + pr_err("%s: could not get tdm_active pinstate\n", + __func__); + goto err; + } + /* Reset the TLMM pins to a default state */ + ret = pinctrl_select_state(pinctrl_info->pinctrl, + pinctrl_info->mi2s_disable); + if (ret != 0) { + pr_err("%s: Disable TLMM pins failed with %d\n", + __func__, ret); + ret = -EIO; + goto err; + } + pinctrl_info->curr_state = STATE_DISABLE; + + return 0; + +err: + devm_pinctrl_put(pinctrl); + pinctrl_info->pinctrl = NULL; + return -EINVAL; +} + +static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + 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); + + if (cpu_dai->id == AFE_PORT_ID_QUATERNARY_TDM_RX) { + 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; + } else if (cpu_dai->id == AFE_PORT_ID_SECONDARY_TDM_RX) { + 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; + } else { + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + pr_debug("%s: dai id = 0x%x channels = %d rate = %d format = 0x%x\n", + __func__, cpu_dai->id, channels->max, rate->max, + params_format(params)); + + return 0; +} + +static int msm8998_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[8] = {0, 4, 8, 12, 16, 20, 24, 28}; + + pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); + + slots = tdm_rx_cfg[TDM_QUAT][TDM_0].channels; + /*2 slot config - bits 0 and 1 set for the first two slots */ + slot_mask = 0x0000FFFF >> (16-slots); + slot_width = 32; + channels = slots; + + pr_debug("%s: slot_width %d slots %d\n", __func__, slot_width, slots); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + pr_debug("%s: slot_width %d\n", __func__, slot_width); + 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 { + pr_err("%s: invalid use case, err:%d\n", + __func__, ret); + } + +end: + return ret; +} + +static int msm8998_tdm_snd_startup(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; + + ret = msm_set_pinctrl(pinctrl_info, STATE_TDM_ACTIVE); + if (ret) + pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + __func__, ret); + + return ret; +} + +static void msm8998_tdm_snd_shutdown(struct snd_pcm_substream *substream) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; + + ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); + if (ret) + pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + __func__, ret); + +} + +static struct snd_soc_ops msm8998_tdm_be_ops = { + .hw_params = msm8998_tdm_snd_hw_params, + .startup = msm8998_tdm_snd_startup, + .shutdown = msm8998_tdm_snd_shutdown +}; + static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) { int ret = 0; @@ -4000,6 +4288,9 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; int index = cpu_dai->id; unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; dev_dbg(rtd->card->dev, "%s: substream = %s stream = %d, dai name %s, dai ID %d\n", @@ -4013,6 +4304,15 @@ static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream) __func__, cpu_dai->id); goto done; } + if (index == QUAT_MI2S) { + ret = msm_set_pinctrl(pinctrl_info, STATE_MI2S_ACTIVE); + if (ret) { + pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + __func__, ret); + goto done; + } + } + /* * Muxtex protection in case the same MI2S * interface using for both TX and RX so @@ -4065,6 +4365,9 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) int ret; struct snd_soc_pcm_runtime *rtd = substream->private_data; int index = rtd->cpu_dai->id; + struct snd_soc_card *card = rtd->card; + struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); + struct msm_pinctrl_info *pinctrl_info = &pdata->pinctrl_info; pr_debug("%s(): substream = %s stream = %d\n", __func__, substream->name, substream->stream); @@ -4083,6 +4386,13 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) } } mutex_unlock(&mi2s_intf_conf[index].lock); + + if (index == QUAT_MI2S) { + ret = msm_set_pinctrl(pinctrl_info, STATE_DISABLE); + if (ret) + pr_err("%s: MI2S TLMM pinctrl set failed with %d\n", + __func__, ret); + } } static struct snd_soc_ops msm_mi2s_be_ops = { @@ -5210,8 +5520,8 @@ static struct snd_soc_dai_link msm_common_be_dai_links[] = { .no_pcm = 1, .dpcm_playback = 1, .be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0, - .be_hw_params_fixup = msm_be_hw_params_fixup, - .ops = &msm_tdm_be_ops, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm8998_tdm_be_ops, .ignore_suspend = 1, }, { @@ -6883,6 +7193,17 @@ static int msm_asoc_machine_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "msm_prepare_us_euro failed (%d)\n", ret); + /* Parse pinctrl info from devicetree */ + ret = msm_get_pinctrl(pdev); + if (!ret) { + pr_debug("%s: pinctrl parsing successful\n", __func__); + } else { + dev_dbg(&pdev->dev, + "%s: Parsing pinctrl failed with %d. Cannot use Ports\n", + __func__, ret); + ret = 0; + } + i2s_auxpcm_init(pdev); is_initial_boot = true; @@ -6900,6 +7221,7 @@ err: gpio_free(pdata->us_euro_gpio); pdata->us_euro_gpio = 0; } + msm_release_pinctrl(pdev); devm_kfree(&pdev->dev, pdata); return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c index 69a9e14c47de..46e2f7109b5a 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-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 @@ -124,6 +124,45 @@ static const struct soc_enum hdmi_config_enum[] = { SOC_ENUM_SINGLE_EXT(2, hdmi_format), }; +static int msm_dai_q6_ext_disp_drift_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = sizeof(struct afe_param_id_dev_timing_stats); + + return 0; +} + +static int msm_dai_q6_ext_disp_drift_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = -EINVAL; + struct afe_param_id_dev_timing_stats timing_stats; + struct snd_soc_dai *dai = kcontrol->private_data; + struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev); + + if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { + pr_err("%s: afe port not started. status_mask = %ld\n", + __func__, *dai_data->status_mask); + goto done; + } + + memset(&timing_stats, 0, sizeof(struct afe_param_id_dev_timing_stats)); + ret = afe_get_av_dev_drift(&timing_stats, dai->id); + if (ret) { + pr_err("%s: Error getting AFE Drift for port %d, err=%d\n", + __func__, dai->id, ret); + + ret = -EINVAL; + goto done; + } + + memcpy(ucontrol->value.bytes.data, (void *)&timing_stats, + sizeof(struct afe_param_id_dev_timing_stats)); +done: + return ret; +} + static const struct snd_kcontrol_new hdmi_config_controls[] = { SOC_ENUM_EXT("HDMI RX Format", hdmi_config_enum[0], msm_dai_q6_ext_disp_format_get, @@ -132,6 +171,13 @@ static const struct snd_kcontrol_new hdmi_config_controls[] = { HDMI_RX_CA_MAX, 0, 1, msm_dai_q6_ext_disp_ca_get, msm_dai_q6_ext_disp_ca_put), + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "HDMI RX Drift", + .info = msm_dai_q6_ext_disp_drift_info, + .get = msm_dai_q6_ext_disp_drift_get, + }, }; static const struct snd_kcontrol_new display_port_config_controls[] = { @@ -142,6 +188,13 @@ static const struct snd_kcontrol_new display_port_config_controls[] = { HDMI_RX_CA_MAX, 0, 1, msm_dai_q6_ext_disp_ca_get, msm_dai_q6_ext_disp_ca_put), + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "DISPLAY Port RX Drift", + .info = msm_dai_q6_ext_disp_drift_info, + .get = msm_dai_q6_ext_disp_drift_get, + }, }; /* Current implementation assumes hw_param is called once @@ -299,6 +352,10 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai) kcontrol = &hdmi_config_controls[1]; rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(kcontrol, dai_data)); + + kcontrol = &hdmi_config_controls[2]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai)); } else if (dai->driver->id == DISPLAY_PORT_RX) { kcontrol = &display_port_config_controls[0]; rc = snd_ctl_add(dai->component->card->snd_card, @@ -307,6 +364,10 @@ static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai) kcontrol = &display_port_config_controls[1]; rc = snd_ctl_add(dai->component->card->snd_card, snd_ctl_new1(kcontrol, dai_data)); + + kcontrol = &display_port_config_controls[2]; + rc = snd_ctl_add(dai->component->card->snd_card, + snd_ctl_new1(kcontrol, dai)); } else { dev_err(dai->dev, "%s: Invalid id:%d\n", __func__, dai->driver->id); diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index f081ef066bdd..19e2fad2920d 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -219,6 +219,7 @@ struct msm_dai_q6_tdm_dai_data { u32 rate; u32 channels; u32 bitwidth; + u32 num_group_ports; struct afe_clk_set clk_set; /* hold LPASS clock config. */ union afe_port_group_config group_cfg; /* hold tdm group config */ struct afe_tdm_port_config port_cfg; /* hold tdm config */ @@ -260,6 +261,7 @@ static const struct soc_enum sb_config_enum[] = { static const char *const tdm_data_format[] = { "LPCM", "Compr", + "Gen Compr" }; static const char *const tdm_header_type[] = { @@ -269,8 +271,8 @@ static const char *const tdm_header_type[] = { }; static const struct soc_enum tdm_config_enum[] = { - SOC_ENUM_SINGLE_EXT(2, tdm_data_format), - SOC_ENUM_SINGLE_EXT(3, tdm_header_type), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_data_format), tdm_data_format), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_header_type), tdm_header_type), }; static DEFINE_MUTEX(tdm_mutex); @@ -298,6 +300,8 @@ static struct afe_param_id_group_device_tdm_cfg tdm_group_cfg = { 0xFF, }; +static u32 num_tdm_group_ports; + static struct afe_clk_set tdm_clk_set = { AFE_API_VERSION_CLOCK_SET, Q6AFE_LPASS_CLK_ID_QUAD_TDM_EBIT, @@ -4981,7 +4985,6 @@ static struct platform_driver msm_dai_q6_spdif_driver = { static int msm_dai_tdm_q6_probe(struct platform_device *pdev) { int rc = 0; - u32 num_ports = 0; const uint32_t *port_id_array = NULL; uint32_t array_length = 0; int i = 0; @@ -5004,18 +5007,19 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev) rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-cpudai-tdm-group-num-ports", - &num_ports); + &num_tdm_group_ports); if (rc) { dev_err(&pdev->dev, "%s: Group Num Ports from DT file %s\n", __func__, "qcom,msm-cpudai-tdm-group-num-ports"); goto rtn; } dev_dbg(&pdev->dev, "%s: Group Num Ports from DT file 0x%x\n", - __func__, num_ports); + __func__, num_tdm_group_ports); - if (num_ports > AFE_GROUP_DEVICE_NUM_PORTS) { + if (num_tdm_group_ports > AFE_GROUP_DEVICE_NUM_PORTS) { dev_err(&pdev->dev, "%s Group Num Ports %d greater than Max %d\n", - __func__, num_ports, AFE_GROUP_DEVICE_NUM_PORTS); + __func__, num_tdm_group_ports, + AFE_GROUP_DEVICE_NUM_PORTS); rc = -EINVAL; goto rtn; } @@ -5029,18 +5033,19 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev) rc = -EINVAL; goto rtn; } - if (array_length != sizeof(uint32_t) * num_ports) { + if (array_length != sizeof(uint32_t) * num_tdm_group_ports) { dev_err(&pdev->dev, "%s array_length is %d, expected is %zd\n", - __func__, array_length, sizeof(uint32_t) * num_ports); + __func__, array_length, + sizeof(uint32_t) * num_tdm_group_ports); rc = -EINVAL; goto rtn; } - for (i = 0; i < num_ports; i++) + for (i = 0; i < num_tdm_group_ports; i++) tdm_group_cfg.port_id[i] = (u16)be32_to_cpu(port_id_array[i]); /* Unused index should be filled with 0 or AFE_PORT_INVALID */ - for (i = num_ports; i < AFE_GROUP_DEVICE_NUM_PORTS; i++) + for (i = num_tdm_group_ports; i < AFE_GROUP_DEVICE_NUM_PORTS; i++) tdm_group_cfg.port_id[i] = AFE_PORT_INVALID; @@ -5107,7 +5112,20 @@ static int msm_dai_q6_tdm_data_format_put(struct snd_kcontrol *kcontrol, struct msm_dai_q6_tdm_dai_data *dai_data = kcontrol->private_data; int value = ucontrol->value.integer.value[0]; - dai_data->port_cfg.tdm.data_format = value; + switch (value) { + case 0: + dai_data->port_cfg.tdm.data_format = AFE_LINEAR_PCM_DATA; + break; + case 1: + dai_data->port_cfg.tdm.data_format = AFE_NON_LINEAR_DATA; + break; + case 2: + dai_data->port_cfg.tdm.data_format = AFE_GENERIC_COMPRESSED; + break; + default: + pr_err("%s: data_format invalid\n", __func__); + break; + } pr_debug("%s: data_format = %d\n", __func__, dai_data->port_cfg.tdm.data_format); return 0; @@ -6047,6 +6065,9 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, /* HW only supports 16 and 8 slots configuration */ switch (slots) { + case 2: + cap_mask = 0x03; + break; case 8: cap_mask = 0xFF; break; @@ -6465,17 +6486,25 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream, __func__, dai->id); goto rtn; } - rc = afe_port_group_enable(group_id, - &dai_data->group_cfg, true); - if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to enable AFE group 0x%x\n", + + /* + * if only one port, don't do group enable as there + * is no group need for only one port + */ + if (dai_data->num_group_ports > 1) { + rc = afe_port_group_enable(group_id, + &dai_data->group_cfg, true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s: fail to enable AFE group 0x%x\n", __func__, group_id); - goto rtn; + goto rtn; + } } } rc = afe_tdm_port_start(dai->id, &dai_data->port_cfg, - dai_data->rate); + dai_data->rate, dai_data->num_group_ports); if (IS_ERR_VALUE(rc)) { if (atomic_read(group_ref) == 0) { afe_port_group_enable(group_id, @@ -6569,13 +6598,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM0 Playback", .aif_name = "PRI_TDM_RX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX, @@ -6587,13 +6618,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM1 Playback", .aif_name = "PRI_TDM_RX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_1, @@ -6605,13 +6638,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM2 Playback", .aif_name = "PRI_TDM_RX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_2, @@ -6623,13 +6658,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM3 Playback", .aif_name = "PRI_TDM_RX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_3, @@ -6641,13 +6678,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM4 Playback", .aif_name = "PRI_TDM_RX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_4, @@ -6659,13 +6698,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM5 Playback", .aif_name = "PRI_TDM_RX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_5, @@ -6677,13 +6718,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM6 Playback", .aif_name = "PRI_TDM_RX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_6, @@ -6695,13 +6738,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM7 Playback", .aif_name = "PRI_TDM_RX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_RX_7, @@ -6713,13 +6758,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM0 Capture", .aif_name = "PRI_TDM_TX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX, @@ -6731,13 +6778,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM1 Capture", .aif_name = "PRI_TDM_TX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_1, @@ -6749,13 +6798,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM2 Capture", .aif_name = "PRI_TDM_TX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_2, @@ -6767,13 +6818,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM3 Capture", .aif_name = "PRI_TDM_TX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_3, @@ -6785,13 +6838,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM4 Capture", .aif_name = "PRI_TDM_TX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_4, @@ -6803,13 +6858,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM5 Capture", .aif_name = "PRI_TDM_TX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_5, @@ -6821,13 +6878,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM6 Capture", .aif_name = "PRI_TDM_TX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_6, @@ -6839,13 +6898,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Primary TDM7 Capture", .aif_name = "PRI_TDM_TX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_PRIMARY_TDM_TX_7, @@ -6857,13 +6918,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM0 Playback", .aif_name = "SEC_TDM_RX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX, @@ -6875,13 +6938,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM1 Playback", .aif_name = "SEC_TDM_RX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_1, @@ -6893,13 +6958,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM2 Playback", .aif_name = "SEC_TDM_RX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_2, @@ -6911,13 +6978,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM3 Playback", .aif_name = "SEC_TDM_RX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_3, @@ -6929,13 +6998,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM4 Playback", .aif_name = "SEC_TDM_RX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_4, @@ -6947,13 +7018,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM5 Playback", .aif_name = "SEC_TDM_RX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_5, @@ -6965,13 +7038,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM6 Playback", .aif_name = "SEC_TDM_RX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_6, @@ -6983,13 +7058,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM7 Playback", .aif_name = "SEC_TDM_RX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_RX_7, @@ -7001,13 +7078,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM0 Capture", .aif_name = "SEC_TDM_TX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX, @@ -7019,13 +7098,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM1 Capture", .aif_name = "SEC_TDM_TX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_1, @@ -7037,13 +7118,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM2 Capture", .aif_name = "SEC_TDM_TX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_2, @@ -7055,13 +7138,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM3 Capture", .aif_name = "SEC_TDM_TX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_3, @@ -7073,13 +7158,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM4 Capture", .aif_name = "SEC_TDM_TX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_4, @@ -7091,13 +7178,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM5 Capture", .aif_name = "SEC_TDM_TX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_5, @@ -7109,13 +7198,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM6 Capture", .aif_name = "SEC_TDM_TX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_6, @@ -7127,13 +7218,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Secondary TDM7 Capture", .aif_name = "SEC_TDM_TX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_SECONDARY_TDM_TX_7, @@ -7145,13 +7238,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM0 Playback", .aif_name = "TERT_TDM_RX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX, @@ -7163,13 +7258,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM1 Playback", .aif_name = "TERT_TDM_RX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_1, @@ -7181,13 +7278,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM2 Playback", .aif_name = "TERT_TDM_RX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_2, @@ -7199,13 +7298,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM3 Playback", .aif_name = "TERT_TDM_RX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_3, @@ -7217,13 +7318,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM4 Playback", .aif_name = "TERT_TDM_RX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_4, @@ -7235,13 +7338,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM5 Playback", .aif_name = "TERT_TDM_RX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_5, @@ -7253,13 +7358,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM6 Playback", .aif_name = "TERT_TDM_RX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_6, @@ -7271,13 +7378,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM7 Playback", .aif_name = "TERT_TDM_RX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_RX_7, @@ -7289,13 +7398,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM0 Capture", .aif_name = "TERT_TDM_TX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX, @@ -7307,13 +7418,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM1 Capture", .aif_name = "TERT_TDM_TX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_1, @@ -7325,13 +7438,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM2 Capture", .aif_name = "TERT_TDM_TX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_2, @@ -7343,13 +7458,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM3 Capture", .aif_name = "TERT_TDM_TX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_3, @@ -7361,13 +7478,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM4 Capture", .aif_name = "TERT_TDM_TX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_4, @@ -7379,13 +7498,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM5 Capture", .aif_name = "TERT_TDM_TX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_5, @@ -7397,13 +7518,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM6 Capture", .aif_name = "TERT_TDM_TX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_6, @@ -7415,13 +7538,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Tertiary TDM7 Capture", .aif_name = "TERT_TDM_TX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_TERTIARY_TDM_TX_7, @@ -7433,13 +7558,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM0 Playback", .aif_name = "QUAT_TDM_RX_0", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX, @@ -7451,13 +7578,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM1 Playback", .aif_name = "QUAT_TDM_RX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_1, @@ -7469,13 +7598,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM2 Playback", .aif_name = "QUAT_TDM_RX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_2, @@ -7487,13 +7618,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM3 Playback", .aif_name = "QUAT_TDM_RX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_3, @@ -7505,13 +7638,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM4 Playback", .aif_name = "QUAT_TDM_RX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_4, @@ -7523,13 +7658,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM5 Playback", .aif_name = "QUAT_TDM_RX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_5, @@ -7541,13 +7678,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM6 Playback", .aif_name = "QUAT_TDM_RX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_6, @@ -7559,13 +7698,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM7 Playback", .aif_name = "QUAT_TDM_RX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_RX_7, @@ -7577,13 +7718,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM0 Capture", .aif_name = "QUAT_TDM_TX_0", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX, @@ -7595,13 +7738,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM1 Capture", .aif_name = "QUAT_TDM_TX_1", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_1, @@ -7613,13 +7758,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM2 Capture", .aif_name = "QUAT_TDM_TX_2", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_2, @@ -7631,13 +7778,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM3 Capture", .aif_name = "QUAT_TDM_TX_3", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_3, @@ -7649,13 +7798,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM4 Capture", .aif_name = "QUAT_TDM_TX_4", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_4, @@ -7667,13 +7818,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM5 Capture", .aif_name = "QUAT_TDM_TX_5", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_5, @@ -7685,13 +7838,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM6 Capture", .aif_name = "QUAT_TDM_TX_6", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_6, @@ -7703,13 +7858,15 @@ static struct snd_soc_dai_driver msm_dai_q6_tdm_dai[] = { .stream_name = "Quaternary TDM7 Capture", .aif_name = "QUAT_TDM_TX_7", .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000, + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800, .formats = SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 352800, }, .ops = &msm_dai_q6_tdm_ops, .id = AFE_PORT_ID_QUATERNARY_TDM_TX_7, @@ -7902,6 +8059,9 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev) dai_data->clk_set = tdm_clk_set; /* copy static group cfg per parent node */ dai_data->group_cfg.tdm_cfg = tdm_group_cfg; + /* copy static num group ports per parent node */ + dai_data->num_group_ports = num_tdm_group_ports; + dev_set_drvdata(&pdev->dev, dai_data); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 1fdb878a1a1f..33c5b6486cca 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -139,6 +139,17 @@ static struct snd_pcm_hw_constraint_list constraints_sample_rates = { .mask = 0, }; +static unsigned long msm_pcm_fe_topology[MSM_FRONTEND_DAI_MAX]; + +/* default value is DTS (i.e read from device tree) */ +static char const *msm_pcm_fe_topology_text[] = { + "DTS", "ULL", "ULL_PP", "LL" }; + +static const struct soc_enum msm_pcm_fe_topology_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(msm_pcm_fe_topology_text), + msm_pcm_fe_topology_text), +}; + static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv) { @@ -258,6 +269,8 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream, uint16_t bits_per_sample; int ret; int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? IN : OUT; + unsigned long topology; + int perf_mode; pdata = (struct msm_plat_data *) dev_get_drvdata(soc_prtd->platform->dev); @@ -268,11 +281,24 @@ static int msm_pcm_hw_params(struct snd_pcm_substream *substream, return ret; } + topology = msm_pcm_fe_topology[soc_prtd->dai_link->be_id]; + + if (!strcmp(msm_pcm_fe_topology_text[topology], "ULL_PP")) + perf_mode = ULL_POST_PROCESSING_PCM_MODE; + else if (!strcmp(msm_pcm_fe_topology_text[topology], "ULL")) + perf_mode = ULTRA_LOW_LATENCY_PCM_MODE; + else if (!strcmp(msm_pcm_fe_topology_text[topology], "LL")) + perf_mode = LOW_LATENCY_PCM_MODE; + else + /* use the default from the device tree */ + perf_mode = pdata->perf_mode; + + /* need to set LOW_LATENCY_PCM_MODE for capture since * push mode does not support ULL */ prtd->audio_client->perf_mode = (dir == IN) ? - pdata->perf_mode : + perf_mode : LOW_LATENCY_PCM_MODE; /* rate and channels are sent to audio driver */ @@ -721,6 +747,93 @@ static int msm_pcm_add_chmap_control(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_pcm_fe_topology_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + const struct soc_enum *e = &msm_pcm_fe_topology_enum[0]; + + return snd_ctl_enum_info(uinfo, 1, e->items, e->texts); +} + +static int msm_pcm_fe_topology_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned long fe_id = kcontrol->private_value; + + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id); + return -EINVAL; + } + + pr_debug("%s: %lu topology %s\n", __func__, fe_id, + msm_pcm_fe_topology_text[msm_pcm_fe_topology[fe_id]]); + ucontrol->value.enumerated.item[0] = msm_pcm_fe_topology[fe_id]; + return 0; +} + +static int msm_pcm_fe_topology_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + unsigned long fe_id = kcontrol->private_value; + unsigned int item; + + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id); + return -EINVAL; + } + + item = ucontrol->value.enumerated.item[0]; + if (item >= ARRAY_SIZE(msm_pcm_fe_topology_text)) { + pr_err("%s Received out of bound topology %lu\n", __func__, + fe_id); + return -EINVAL; + } + + pr_debug("%s: %lu new topology %s\n", __func__, fe_id, + msm_pcm_fe_topology_text[item]); + msm_pcm_fe_topology[fe_id] = item; + return 0; +} + +static int msm_pcm_add_fe_topology_control(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "PCM_Dev"; + const char *deviceNo = "NN"; + const char *topo_text = "Topology"; + char *mixer_str = NULL; + int ctl_len; + int ret; + struct snd_kcontrol_new topology_control[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .name = "?", + .info = msm_pcm_fe_topology_info, + .get = msm_pcm_fe_topology_get, + .put = msm_pcm_fe_topology_put, + .private_value = 0, + }, + }; + + ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + + strlen(topo_text) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name, + rtd->pcm->device, topo_text); + + topology_control[0].name = mixer_str; + topology_control[0].private_value = rtd->dai_link->be_id; + ret = snd_soc_add_platform_controls(rtd->platform, topology_control, + ARRAY_SIZE(topology_control)); + msm_pcm_fe_topology[rtd->dai_link->be_id] = 0; + kfree(mixer_str); + return ret; +} + static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct snd_card *card = rtd->card->snd_card; @@ -741,6 +854,12 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add pcm Volume Control %d\n", __func__, ret); } + + ret = msm_pcm_add_fe_topology_control(rtd); + if (ret) { + pr_err("%s: Could not add pcm topology control %d\n", + __func__, ret); + } pcm->nonatomic = true; exit: return ret; @@ -778,8 +897,12 @@ static int msm_pcm_probe(struct platform_device *pdev) rc = of_property_read_string(pdev->dev.of_node, "qcom,latency-level", &latency_level); - if (!rc && !strcmp(latency_level, "ultra")) - perf_mode = ULTRA_LOW_LATENCY_PCM_MODE; + if (!rc) { + if (!strcmp(latency_level, "ultra")) + perf_mode = ULTRA_LOW_LATENCY_PCM_MODE; + else if (!strcmp(latency_level, "ull-pp")) + perf_mode = ULL_POST_PROCESSING_PCM_MODE; + } } pdata = devm_kzalloc(&pdev->dev, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index e2f662f26cff..e14f410bd310 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -110,7 +110,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = { /* Conventional and unconventional sample rate supported */ static unsigned int supported_sample_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 88200, 96000, 176400, 192000, 384000 + 88200, 96000, 176400, 192000, 352800, 384000 }; static struct snd_pcm_hw_constraint_list constraints_sample_rates = { @@ -285,6 +285,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) struct msm_plat_data *pdata; struct snd_pcm_hw_params *params; int ret; + uint32_t fmt_type = FORMAT_LINEAR_PCM; uint16_t bits_per_sample; uint16_t sample_word_size; @@ -333,38 +334,67 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) sample_word_size = 16; break; } + if (prtd->compress_enable) { + fmt_type = FORMAT_GEN_COMPR; + pr_debug("%s: Compressed enabled!\n", __func__); + ret = q6asm_open_write_compressed(prtd->audio_client, fmt_type, + COMPRESSED_PASSTHROUGH_GEN); + if (ret < 0) { + pr_err("%s: q6asm_open_write_compressed failed (%d)\n", + __func__, ret); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return -ENOMEM; + } + } else { + ret = q6asm_open_write_v4(prtd->audio_client, + fmt_type, bits_per_sample); - ret = q6asm_open_write_v4(prtd->audio_client, - FORMAT_LINEAR_PCM, bits_per_sample); + if (ret < 0) { + pr_err("%s: q6asm_open_write_v4 failed (%d)\n", + __func__, ret); + q6asm_audio_client_free(prtd->audio_client); + prtd->audio_client = NULL; + return -ENOMEM; + } - if (ret < 0) { - pr_err("%s: q6asm_open_write_v2 failed\n", __func__); - q6asm_audio_client_free(prtd->audio_client); - prtd->audio_client = NULL; - return -ENOMEM; + ret = q6asm_send_cal(prtd->audio_client); + if (ret < 0) + pr_debug("%s : Send cal failed : %d", __func__, ret); } - - ret = q6asm_send_cal(prtd->audio_client); - if (ret < 0) - pr_debug("%s : Send cal failed : %d", __func__, ret); - pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session); prtd->session_id = prtd->audio_client->session; - ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id, + + if (prtd->compress_enable) { + ret = msm_pcm_routing_reg_phy_compr_stream( + soc_prtd->dai_link->be_id, + prtd->audio_client->perf_mode, + prtd->session_id, + SNDRV_PCM_STREAM_PLAYBACK, + COMPRESSED_PASSTHROUGH_GEN); + } else { + ret = msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id, prtd->audio_client->perf_mode, prtd->session_id, substream->stream); + } if (ret) { pr_err("%s: stream reg failed ret:%d\n", __func__, ret); return ret; } - - ret = q6asm_media_format_block_multi_ch_pcm_v4( + if (prtd->compress_enable) { + ret = q6asm_media_format_block_gen_compr( + prtd->audio_client, runtime->rate, + runtime->channels, !prtd->set_channel_map, + prtd->channel_map, bits_per_sample); + } else { + ret = q6asm_media_format_block_multi_ch_pcm_v4( prtd->audio_client, runtime->rate, runtime->channels, !prtd->set_channel_map, prtd->channel_map, bits_per_sample, sample_word_size, ASM_LITTLE_ENDIAN, DEFAULT_QF); + } if (ret < 0) pr_info("%s: CMD Format block failed\n", __func__); @@ -1091,6 +1121,136 @@ static int msm_pcm_add_volume_control(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_pcm_compress_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0x2000; + return 0; +} + +static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct snd_soc_platform *platform = snd_soc_component_to_platform(comp); + struct msm_plat_data *pdata = dev_get_drvdata(platform->dev); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + + if (!pdata) { + pr_err("%s pdata is NULL\n", __func__); + return -ENODEV; + } + substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + return -EINVAL; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + return 0; + } + prtd = substream->runtime->private_data; + if (prtd) + ucontrol->value.integer.value[0] = prtd->compress_enable; + return 0; +} + +static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int rc = 0; + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct snd_soc_platform *platform = snd_soc_component_to_platform(comp); + struct msm_plat_data *pdata = dev_get_drvdata(platform->dev); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + int compress = ucontrol->value.integer.value[0]; + + if (!pdata) { + pr_err("%s pdata is NULL\n", __func__); + return -ENODEV; + } + substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + pr_debug("%s: compress : 0x%x\n", __func__, compress); + if (!substream) { + pr_err("%s substream not found\n", __func__); + return -EINVAL; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + return 0; + } + prtd = substream->runtime->private_data; + if (prtd) { + pr_debug("%s: setting compress flag to 0x%x\n", + __func__, compress); + prtd->compress_enable = compress; + } + return rc; +} + +static int msm_pcm_add_compress_control(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "Playback "; + const char *mixer_ctl_end_name = " Compress"; + const char *deviceNo = "NN"; + char *mixer_str = NULL; + int ctl_len; + int ret = 0; + struct msm_plat_data *pdata; + struct snd_kcontrol_new pcm_compress_control[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "?", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = msm_pcm_compress_ctl_info, + .get = msm_pcm_compress_ctl_get, + .put = msm_pcm_compress_ctl_put, + .private_value = 0, + } + }; + + if (!rtd) { + pr_err("%s: NULL rtd\n", __func__); + return -EINVAL; + } + + ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + + strlen(mixer_ctl_end_name) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s%d%s", mixer_ctl_name, + rtd->pcm->device, mixer_ctl_end_name); + + pcm_compress_control[0].name = mixer_str; + pcm_compress_control[0].private_value = rtd->dai_link->be_id; + pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); + pdata = dev_get_drvdata(rtd->platform->dev); + if (pdata) { + if (!pdata->pcm) { + pdata->pcm = rtd->pcm; + snd_soc_add_platform_controls(rtd->platform, + pcm_compress_control, + ARRAY_SIZE + (pcm_compress_control)); + pr_debug("%s: add control success plt = %pK\n", + __func__, rtd->platform); + } + } else { + pr_err("%s: NULL pdata\n", __func__); + ret = -EINVAL; + } + kfree(mixer_str); + return ret; +} + static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1381,6 +1541,11 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add pcm Volume Control %d\n", __func__, ret); + ret = msm_pcm_add_compress_control(rtd); + if (ret) + pr_err("%s: Could not add pcm Compress Control %d\n", + __func__, ret); + return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h index 8fe31394eef0..f5ff63f34b82 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 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 @@ -109,6 +109,7 @@ struct msm_audio { int cmd_interrupt; bool meta_data_mode; uint32_t volume; + bool compress_enable; /* array of frame info */ struct msm_audio_in_frame_info in_frame_info[CAPTURE_MAX_NUM_PERIODS]; }; @@ -123,6 +124,7 @@ struct output_meta_data_st { struct msm_plat_data { int perf_mode; + struct snd_pcm *pcm; }; #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index e93d46b5f30f..cfade420c509 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -1143,8 +1143,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, topology = msm_routing_get_adm_topology(fe_id, session_type, i); - if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD) - topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY; + if ((passthr_mode == COMPRESSED_PASSTHROUGH_DSD) + || (passthr_mode == + COMPRESSED_PASSTHROUGH_GEN)) + topology = COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY; pr_debug("%s: Before adm open topology %d\n", __func__, topology); @@ -1194,7 +1196,9 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, num_copps++; } } - if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD) { + if (passthr_mode != COMPRESSED_PASSTHROUGH_DSD + && passthr_mode != + COMPRESSED_PASSTHROUGH_GEN) { msm_routing_send_device_pp_params( msm_bedais[i].port_id, copp_idx); @@ -12175,6 +12179,42 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, {"QUAT_TDM_RX_0", NULL, "QUAT_TDM_RX_0 Audio Mixer"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"PRI_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"PRI_TDM_RX_0", NULL, "PRI_TDM_RX_0 Audio Mixer"}, + + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia9", "MM_DL9"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_TDM_RX_0 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_TDM_RX_0", NULL, "SEC_TDM_RX_0 Audio Mixer"}, + {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia1", "MM_DL1"}, {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia2", "MM_DL2"}, {"QUAT_TDM_TX_0 Audio Mixer", "MultiMedia3", "MM_DL3"}, diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index be5437a186ea..bc1d21a826b5 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -113,6 +113,7 @@ struct afe_ctl { struct audio_cal_info_sp_ex_vi_ftm_cfg ex_ftm_cfg; struct afe_sp_th_vi_get_param_resp th_vi_resp; struct afe_sp_ex_vi_get_param_resp ex_vi_resp; + struct afe_av_dev_drift_get_param_resp av_dev_drift_resp; int vi_tx_port; int vi_rx_port; uint32_t afe_sample_rates[AFE_MAX_PORTS]; @@ -189,6 +190,38 @@ static void afe_callback_debug_print(struct apr_client_data *data) __func__, data->opcode, data->payload_size); } +static void av_dev_drift_afe_cb_handler(uint32_t *payload, + uint32_t payload_size) +{ + u32 param_id; + struct afe_av_dev_drift_get_param_resp *resp = + (struct afe_av_dev_drift_get_param_resp *) payload; + + if (!(&(resp->pdata))) { + pr_err("%s: Error: resp pdata is NULL\n", __func__); + return; + } + + param_id = resp->pdata.param_id; + if (param_id == AFE_PARAM_ID_DEV_TIMING_STATS) { + if (payload_size < sizeof(this_afe.av_dev_drift_resp)) { + pr_err("%s: Error: received size %d, resp size %zu\n", + __func__, payload_size, + sizeof(this_afe.av_dev_drift_resp)); + return; + } + memcpy(&this_afe.av_dev_drift_resp, payload, + sizeof(this_afe.av_dev_drift_resp)); + if (!this_afe.av_dev_drift_resp.status) { + atomic_set(&this_afe.state, 0); + } else { + pr_debug("%s: av_dev_drift_resp status: %d", __func__, + this_afe.av_dev_drift_resp.status); + atomic_set(&this_afe.state, -1); + } + } +} + static int32_t sp_make_afe_callback(uint32_t *payload, uint32_t payload_size) { u32 param_id; @@ -309,10 +342,7 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) } afe_callback_debug_print(data); if (data->opcode == AFE_PORT_CMDRSP_GET_PARAM_V2) { - u8 *payload = data->payload; - - if (rtac_make_afe_callback(data->payload, data->payload_size)) - return 0; + uint32_t *payload = data->payload; if (!payload || (data->token >= AFE_MAX_PORTS)) { pr_err("%s: Error: size %d payload %pK token %d\n", @@ -320,9 +350,19 @@ static int32_t afe_callback(struct apr_client_data *data, void *priv) payload, data->token); return -EINVAL; } - if (sp_make_afe_callback(data->payload, data->payload_size)) - return -EINVAL; + if (payload[2] == AFE_PARAM_ID_DEV_TIMING_STATS) { + av_dev_drift_afe_cb_handler(data->payload, + data->payload_size); + } else { + if (rtac_make_afe_callback(data->payload, + data->payload_size)) + return 0; + + if (sp_make_afe_callback(data->payload, + data->payload_size)) + return -EINVAL; + } wake_up(&this_afe.wait[data->token]); } else if (data->payload_size) { uint32_t *payload; @@ -1181,6 +1221,7 @@ static int afe_send_hw_delay(u16 port_id, u32 rate) pr_debug("%s:\n", __func__); + memset(&delay_entry, 0, sizeof(delay_entry)); delay_entry.sample_rate = rate; if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX) ret = afe_get_cal_hw_delay(TX_DEVICE, &delay_entry); @@ -2541,7 +2582,7 @@ fail_cmd: } int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, - u32 rate) + u32 rate, u16 num_groups) { struct afe_audioif_config_command config; int ret = 0; @@ -2581,9 +2622,10 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id); } - /* Also send the topology id here: */ + /* Also send the topology id here if multiple ports: */ port_index = afe_get_port_index(port_id); - if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) { + if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE) && + num_groups > 1) { /* One time call: only for first time */ afe_send_custom_topology(); afe_send_port_topology_id(port_id); @@ -2645,11 +2687,14 @@ int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, ret = -EINVAL; goto fail_cmd; } - - ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping, port_id); - if (ret < 0) { - pr_err("%s: afe send failed %d\n", __func__, ret); - goto fail_cmd; + /* slot mapping is not need if there is only one group */ + if (num_groups > 1) { + ret = afe_send_slot_mapping_cfg(&tdm_port->slot_mapping, + port_id); + if (ret < 0) { + pr_err("%s: afe send failed %d\n", __func__, ret); + goto fail_cmd; + } } if (tdm_port->custom_tdm_header.header_type) { @@ -2763,6 +2808,11 @@ static int q6afe_send_enc_config(u16 port_id, } memset(&config, 0, sizeof(config)); index = q6audio_get_port_index(port_id); + if (index < 0) { + pr_err("%s: Invalid index number: %d\n", __func__, index); + return -EINVAL; + } + config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); config.hdr.pkt_size = sizeof(config); @@ -6163,6 +6213,88 @@ done: return ret; } +int afe_get_av_dev_drift(struct afe_param_id_dev_timing_stats *timing_stats, + u16 port) +{ + int ret = -EINVAL; + int index = 0; + struct afe_av_dev_drift_get_param av_dev_drift; + + if (!timing_stats) { + pr_err("%s: Invalid params\n", __func__); + goto exit; + } + + ret = q6audio_validate_port(port); + if (ret < 0) { + pr_err("%s: invalid port 0x%x ret %d\n", __func__, port, ret); + ret = -EINVAL; + goto exit; + } + + index = q6audio_get_port_index(port); + if (index < 0 || index >= AFE_MAX_PORTS) { + pr_err("%s: Invalid AFE port index[%d]\n", + __func__, index); + ret = -EINVAL; + goto exit; + } + + memset(&av_dev_drift, 0, sizeof(struct afe_av_dev_drift_get_param)); + + av_dev_drift.hdr.hdr_field = + APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + av_dev_drift.hdr.pkt_size = sizeof(av_dev_drift); + av_dev_drift.hdr.src_port = 0; + av_dev_drift.hdr.dest_port = 0; + av_dev_drift.hdr.token = index; + av_dev_drift.hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2; + av_dev_drift.get_param.mem_map_handle = 0; + av_dev_drift.get_param.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + av_dev_drift.get_param.param_id = AFE_PARAM_ID_DEV_TIMING_STATS; + av_dev_drift.get_param.payload_address_lsw = 0; + av_dev_drift.get_param.payload_address_msw = 0; + av_dev_drift.get_param.payload_size = sizeof(av_dev_drift) + - sizeof(av_dev_drift.get_param) - sizeof(av_dev_drift.hdr); + av_dev_drift.get_param.port_id = q6audio_get_port_id(port); + av_dev_drift.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + av_dev_drift.pdata.param_id = AFE_PARAM_ID_DEV_TIMING_STATS; + av_dev_drift.pdata.param_size = sizeof(av_dev_drift.timing_stats); + atomic_set(&this_afe.status, 0); + atomic_set(&this_afe.state, 1); + ret = apr_send_pkt(this_afe.apr, (uint32_t *)&av_dev_drift); + if (ret < 0) { + pr_err("%s: get param port 0x%x param id[0x%x] failed %d\n", + __func__, port, av_dev_drift.get_param.param_id, ret); + goto exit; + } + + ret = wait_event_timeout(this_afe.wait[index], + (atomic_read(&this_afe.state) == 0), + msecs_to_jiffies(TIMEOUT_MS)); + if (!ret) { + pr_err("%s: wait_event timeout\n", __func__); + ret = -EINVAL; + goto exit; + } + + if (atomic_read(&this_afe.status) > 0) { + pr_err("%s: config cmd failed [%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&this_afe.status))); + ret = adsp_err_get_lnx_err_code( + atomic_read(&this_afe.status)); + goto exit; + } + + memcpy(timing_stats, &this_afe.av_dev_drift_resp.timing_stats, + sizeof(this_afe.av_dev_drift_resp.timing_stats)); + ret = 0; +exit: + return ret; +} + int afe_spk_prot_get_calib_data(struct afe_spkr_prot_get_vi_calib *calib_resp) { int ret = -EINVAL; diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 74fbe984e6e9..d55c28fab652 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -2490,6 +2490,10 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, case FORMAT_DSD: open.fmt_id = ASM_MEDIA_FMT_DSD; break; + case FORMAT_GEN_COMPR: + open.fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED; + break; + default: pr_err("%s: Invalid format[%d]\n", __func__, format); rc = -EINVAL; @@ -2498,7 +2502,8 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, /*Below flag indicates the DSP that Compressed audio input stream is not IEC 61937 or IEC 60958 packetizied*/ if (passthrough_flag == COMPRESSED_PASSTHROUGH || - passthrough_flag == COMPRESSED_PASSTHROUGH_DSD) { + passthrough_flag == COMPRESSED_PASSTHROUGH_DSD || + passthrough_flag == COMPRESSED_PASSTHROUGH_GEN) { open.flags = 0x0; pr_debug("%s: Flag 0 COMPRESSED_PASSTHROUGH\n", __func__); } else if (passthrough_flag == COMPRESSED_PASSTHROUGH_CONVERT) { @@ -2665,6 +2670,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, case FORMAT_APTX: open.dec_fmt_id = ASM_MEDIA_FMT_APTX; break; + case FORMAT_GEN_COMPR: + open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED; + break; default: pr_err("%s: Invalid format 0x%x\n", __func__, format); rc = -EINVAL; @@ -5191,6 +5199,82 @@ int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4); +/* + * q6asm_media_format_block_gen_compr - set up generic compress format params + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @use_default_chmap: true if default channel map to be used + * @channel_map: input channel map + * @bits_per_sample: bit width of gen compress stream + */ +int q6asm_media_format_block_gen_compr(struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, char *channel_map, + uint16_t bits_per_sample) +{ + struct asm_generic_compressed_fmt_blk_t fmt; + u8 *channel_mapping; + int rc = 0; + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]\n", + __func__, ac->session, rate, + channels, bits_per_sample); + + memset(&fmt, 0, sizeof(fmt)); + q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.num_channels = channels; + fmt.bits_per_sample = bits_per_sample; + fmt.sampling_rate = rate; + + channel_mapping = fmt.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + if (use_default_chmap) { + if (q6asm_map_channels(channel_mapping, channels, false)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + return -EINVAL; + } + } else { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } + + atomic_set(&ac->cmd_state, -1); + rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt); + if (rc < 0) { + pr_err("%s: Comamnd open failed %d\n", __func__, rc); + rc = -EINVAL; + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout. waited for format update\n", __func__); + rc = -ETIMEDOUT; + goto fail_cmd; + } + + 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)); + } + return 0; +fail_cmd: + return rc; +} +EXPORT_SYMBOL(q6asm_media_format_block_gen_compr); + static int __q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { |
